mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-16 17:44:24 +03:00
Compare commits
1090 Commits
v2_03_21
...
dev-perf-1
Author | SHA1 | Date | |
---|---|---|---|
|
ce9c5f2f7e | ||
|
eea78613ef | ||
|
00a8946e46 | ||
|
53d5e2e602 | ||
|
ce970403d6 | ||
|
4e623daf8e | ||
|
e03bdcfbc2 | ||
|
fa12a2398e | ||
|
18babdc3ac | ||
|
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 | ||
|
6e6d4c62b3 | ||
|
fe68fb0525 | ||
|
3a9689652d | ||
|
1813d0d186 | ||
|
b77edc337a | ||
|
1e2a3445d9 | ||
|
88681f05f1 | ||
|
5731d06bc5 | ||
|
76ca20a9af | ||
|
524df486b3 | ||
|
896410b393 | ||
|
cd0f5ee36c | ||
|
13e0222ba2 | ||
|
fffff2c2a2 | ||
|
915dd18361 | ||
|
85e0636623 | ||
|
91502446ac | ||
|
a8b8e1f074 | ||
|
ace25d5eeb | ||
|
9ee6a9b982 | ||
|
c14e0282ec | ||
|
2c8ff67470 | ||
|
f10de12ade | ||
|
7e59c3aa58 | ||
|
9207bae33b | ||
|
fbdd26a4a3 | ||
|
533a87d0ea | ||
|
80fa3511be | ||
|
c496cfa99a | ||
|
d825e8887c | ||
|
9dfe5ce2bc | ||
|
90c6c421cd | ||
|
3b649c3076 | ||
|
403ecb46fa | ||
|
1b90865843 | ||
|
88e0060aa8 | ||
|
2e6e752c3a | ||
|
cd56b04ef6 | ||
|
cdcd482fa4 | ||
|
e1fd179dc5 | ||
|
eaa4882924 | ||
|
ddf3b6e5e3 | ||
|
9ab2607c7f | ||
|
40cf4ce1e1 | ||
|
45c06025da | ||
|
bbe1b93ed9 | ||
|
93115ef91d | ||
|
fdfe80f024 | ||
|
01e014a246 | ||
|
b63e54d0ed | ||
|
e211768d1c | ||
|
d192477ae6 | ||
|
dac2bfe6a4 | ||
|
5da282fa23 | ||
|
1712845ab5 | ||
|
36691b9844 | ||
|
5c24d6d4db | ||
|
aad1add77f | ||
|
314c759a09 | ||
|
a198224666 | ||
|
d8e639ecba | ||
|
caa0e08738 | ||
|
2e0ac97903 | ||
|
9a371639fc | ||
|
83c0b19f61 | ||
|
93918a1990 | ||
|
59345da03f | ||
|
dd78573073 | ||
|
38d34dbe75 | ||
|
5173b0c222 | ||
|
73298635b9 | ||
|
47f8bda051 | ||
|
c609dedc2f | ||
|
6fdc8787eb | ||
|
90ec2cd92f | ||
|
15413226a8 | ||
|
5906f44bee | ||
|
32b2776afc | ||
|
a0c5b2c9fd | ||
|
e59c84ca3a | ||
|
e3dff2cba2 | ||
|
7d22be22d9 | ||
|
e08e5a5a07 | ||
|
915267c900 | ||
|
c2c028c680 | ||
|
a86fb27607 | ||
|
c6b5eb5b50 | ||
|
d58a2644e6 | ||
|
aafa22e643 | ||
|
af983ad3d3 | ||
|
c0e7cdff9d | ||
|
a1a1e13dbe | ||
|
60bad2f22d | ||
|
026344e8cc | ||
|
ee3be2807f | ||
|
d25c43c8cd | ||
|
ffdceeb982 | ||
|
74e487f3a9 | ||
|
8da0ab6fc1 | ||
|
c7a9a1fb6c | ||
|
46669fe9e8 | ||
|
5b7e30da76 | ||
|
429ab45a1c | ||
|
f86bdcb6e9 | ||
|
25236a963f | ||
|
fd8ed7554e | ||
|
1a219c69ee | ||
|
bebbb1e66a | ||
|
5840f90e82 | ||
|
82617852a4 | ||
|
f854e3a722 | ||
|
abe1b49b47 | ||
|
433154fc8a | ||
|
8ac1cc593e | ||
|
d85c9728fb | ||
|
1c396598ff | ||
|
d3c22aedc4 | ||
|
057b1bde75 | ||
|
e54bfe2a83 | ||
|
cd6e1d0475 | ||
|
b678decfca | ||
|
87cd61c6bd | ||
|
00cfe3a24e | ||
|
55a9fb98d1 | ||
|
44d58f28f1 | ||
|
d2c6866bdb | ||
|
868bd3b51e | ||
|
5aff63c07b | ||
|
8a323082ef | ||
|
04d9f13fa6 | ||
|
298bd24e53 | ||
|
7a74229a8e | ||
|
a3dcdf5671 | ||
|
6db19f6b51 | ||
|
57143a216e | ||
|
7c016506a2 | ||
|
5561f2a530 | ||
|
2f3fcbd245 | ||
|
4dda6d1555 | ||
|
8168b5e71d | ||
|
c48cc22b18 | ||
|
edbc0ed447 | ||
|
383d7c4413 | ||
|
cfcbf89ed0 | ||
|
09f70dbb87 | ||
|
5f1c799e6a | ||
|
f0d3d0482e | ||
|
5818fbfbcf | ||
|
3e91823b3e | ||
|
59b4c97564 | ||
|
3f41b4af55 | ||
|
5c7d6083a9 | ||
|
bbf352892d | ||
|
d7c2fe9723 | ||
|
f6e0e7b9aa | ||
|
9f4dc4170b | ||
|
a07bf7b90b | ||
|
dae792baad | ||
|
db40a2e33c | ||
|
4761753a6f | ||
|
04b407674c | ||
|
61a11f25a3 | ||
|
099a4e2146 | ||
|
91991e3cc1 | ||
|
e56e7ed533 | ||
|
a763420786 | ||
|
75a03c2c26 | ||
|
495ea0f058 | ||
|
c140601cf6 | ||
|
5d573cc91d | ||
|
7b872bc4cd | ||
|
2a75dc7465 | ||
|
09426b4663 | ||
|
d16a8f80e9 | ||
|
f3d3d4a07d | ||
|
2e38369ecf | ||
|
011e0672c5 | ||
|
2b198cd874 | ||
|
8daa702880 | ||
|
781bb0ea37 | ||
|
f65f5e1c22 | ||
|
9a9db862a4 | ||
|
7f25e58f66 | ||
|
0eb6a59299 | ||
|
e0bd66b73a | ||
|
8bbd00162b | ||
|
c9f9744f50 | ||
|
9247e754fe | ||
|
eae0314b55 | ||
|
9cf127b429 | ||
|
0e5250c475 | ||
|
e6f46fafe7 | ||
|
0bcf2c6514 | ||
|
efe2005022 | ||
|
abf7c40185 | ||
|
acabc995c0 | ||
|
9f506eb89e | ||
|
6430a6ca63 | ||
|
ff699eab24 | ||
|
41ffa8c74d | ||
|
64cb8b5940 | ||
|
effafa8fc8 | ||
|
2a1e200f7a | ||
|
9b2f9d64c0 | ||
|
e02695cb45 | ||
|
a6f4aed3c0 | ||
|
1f92fc2af7 | ||
|
a98f908c23 | ||
|
54e2de82c0 | ||
|
8f37c22df2 | ||
|
1ab66f37ae | ||
|
611975c51b | ||
|
eeffc1d52b | ||
|
b4670db008 | ||
|
0b064aedb3 | ||
|
6f8abdc978 | ||
|
db6bb6e90b | ||
|
061fa7b690 | ||
|
2a39ed7741 | ||
|
b8d5c4b41a | ||
|
d5da7604e5 | ||
|
7ec0f69cd1 | ||
|
9162ae0a0a | ||
|
c35385a1cd | ||
|
26cbd4057a | ||
|
e654b9cba9 | ||
|
45d9b2c470 | ||
|
d2f953c9db | ||
|
063910c54b | ||
|
f453665f92 | ||
|
cd69d58fcd | ||
|
0316dd7955 | ||
|
e1211d38a4 | ||
|
ee45cd8965 | ||
|
6ece8b74f0 | ||
|
063ade474c | ||
|
ecabdf68cf | ||
|
1bb03cff66 | ||
|
7c4be946cb | ||
|
d194fb8513 | ||
|
b3189d9b15 | ||
|
6e985f553b | ||
|
e51c2376dd | ||
|
38cc021d67 | ||
|
41e0a93a8f | ||
|
ce97056a7a | ||
|
82c062be74 | ||
|
95fca3d1d5 | ||
|
3fc34ac7ee | ||
|
21b683614c | ||
|
db96e81f76 | ||
|
d0cfe73326 | ||
|
57ab219d9b | ||
|
c6a37ddca4 | ||
|
4c5eb2e713 | ||
|
4557427a61 | ||
|
b0c0e8bd7a | ||
|
68a8555d69 | ||
|
baebd7ca29 | ||
|
b14f29ab5b | ||
|
a8009f72bf | ||
|
ba13ac8704 | ||
|
f569ac59a7 | ||
|
078445658c | ||
|
f022da9e5f | ||
|
5d23054cb3 | ||
|
0b3b40f056 | ||
|
6caeffa4be | ||
|
22571fb36a | ||
|
6ee731ba1a | ||
|
79bb9e3172 | ||
|
85b711caae | ||
|
f4911177da | ||
|
77ff83f784 | ||
|
b885355e76 | ||
|
2d01af8e56 | ||
|
bb276bf250 | ||
|
93c47a2b94 | ||
|
4ca9d478d4 | ||
|
485a1961e8 | ||
|
d3d06f8ca0 | ||
|
569dd5d089 | ||
|
3b9bb773fe | ||
|
716fc27fdd | ||
|
79cdfc8ca6 | ||
|
ecb8399005 | ||
|
84b084c9b6 | ||
|
2ea8afba93 | ||
|
f59ec61fa7 | ||
|
0168de83de | ||
|
fcfbef26e4 | ||
|
8ce8e33a44 | ||
|
aae7c98aaa | ||
|
81dc0e72da | ||
|
d6b15e755e | ||
|
5e3224c57d | ||
|
54840d867e | ||
|
3a433b14f2 | ||
|
449af6c335 | ||
|
fd0517c82b | ||
|
543011fa86 | ||
|
ac3cee638b | ||
|
8ba9574ed4 | ||
|
faf4fe0714 | ||
|
a14cb2495b | ||
|
8d1a946a9b | ||
|
8a2839c867 | ||
|
6382d141fa | ||
|
32c6dbb425 | ||
|
6a95c66f5b | ||
|
fa62397ff8 | ||
|
2b9c3f8dc9 | ||
|
82f50dc800 | ||
|
2b802ab413 | ||
|
c5b4574729 | ||
|
2a8c195360 | ||
|
cb16f5053f | ||
|
e7a54c1a50 | ||
|
3ce83f923d | ||
|
8545621d39 | ||
|
22a0cfdc05 | ||
|
f27273e1f0 | ||
|
f27388b5d8 | ||
|
cd9b2b32aa | ||
|
9dad6f202c | ||
|
f404d8ccb7 | ||
|
5125629f2a | ||
|
39d375ecd1 | ||
|
b120b2932d | ||
|
08888d57cb | ||
|
f524dd80f4 | ||
|
092951f634 | ||
|
d8e52aed87 | ||
|
6ec84993bd | ||
|
88ad83e3d6 | ||
|
d490572410 | ||
|
aae27f6be6 | ||
|
04e8f8c93d | ||
|
d6df31fba1 | ||
|
2fdf3b137a | ||
|
dbc0105e1a | ||
|
a82b93b298 | ||
|
7fbd3bac71 | ||
|
6305db53c1 | ||
|
dda859027c | ||
|
203c8b3997 | ||
|
000f55a1a2 | ||
|
ecacb2b544 | ||
|
50b188eebd | ||
|
41f13b2a3b | ||
|
5dec664ccf | ||
|
f9fefaaabe | ||
|
995ff58903 | ||
|
295e632e81 | ||
|
5c0ade35e2 | ||
|
fa81c7561f | ||
|
c78970c0d0 | ||
|
6d6e8d69eb | ||
|
fb80ed3143 | ||
|
adfa16c899 | ||
|
d39b47d665 | ||
|
46ef562c50 | ||
|
d65a428f2d | ||
|
b8d5744c6e | ||
|
4151df32c1 | ||
|
6172db5326 | ||
|
eba277bca8 | ||
|
a98709aeae | ||
|
466265eaa6 | ||
|
ee496f2846 | ||
|
93a633092a | ||
|
960df88621 | ||
|
fef49a0e86 | ||
|
fe2294769c | ||
|
2b7d0db7f1 | ||
|
7ec7d8cf54 | ||
|
59b46fc8cd | ||
|
f2edc96bb6 | ||
|
3430395c85 | ||
|
fc477192e5 | ||
|
4ba683bb18 | ||
|
f1e80f3be0 | ||
|
8965fd18aa | ||
|
1d150d63c7 | ||
|
69f9fcfd20 | ||
|
4a69bacc20 | ||
|
83b726e5dd | ||
|
0dbd90d74e | ||
|
2b864aeb14 | ||
|
f98d2ffe87 | ||
|
8c4b8c6e27 | ||
|
1c2dff2655 | ||
|
c4b1bfa5f0 | ||
|
421afd287a | ||
|
4abdc5981a | ||
|
4f1d89d37f | ||
|
ac90ab7736 | ||
|
ae7b59f509 | ||
|
b84702349f | ||
|
7e5e98e4f2 | ||
|
05993fd432 | ||
|
75e532417e | ||
|
8716d8c188 | ||
|
46e013988f | ||
|
3b47ce0a37 | ||
|
1ba2d40473 | ||
|
bca6f58848 | ||
|
835e8f9d7a | ||
|
781bf867cc | ||
|
658c446f13 | ||
|
e8b7b53db1 | ||
|
68939136c1 | ||
|
d7f6d5b9da | ||
|
e36c6a31e6 | ||
|
e450ad287e | ||
|
b951f81db5 | ||
|
50ad27a4ab | ||
|
ab3c690077 | ||
|
2eff6e1974 | ||
|
f09a992720 | ||
|
4203fdbfef | ||
|
eb4f744820 | ||
|
48188d7181 | ||
|
71bac6f45b | ||
|
038f9254d9 | ||
|
a196752969 | ||
|
21ca92c432 | ||
|
2b2f11a74c | ||
|
f98d020ead | ||
|
0fe2d778aa | ||
|
6f44e1093c | ||
|
e5dc11e26d | ||
|
635df7486f | ||
|
c5827b2013 | ||
|
b47b66ebff | ||
|
622884d67a | ||
|
363e8888ae | ||
|
a985d5c63d | ||
|
ad582da3ca | ||
|
abc1b44d8d | ||
|
9718fd2496 | ||
|
1658776aaf | ||
|
2fc66d2835 | ||
|
4efe8e83cf | ||
|
4b1664236b | ||
|
f93446486e | ||
|
d0c83d4680 | ||
|
7084b17c95 | ||
|
9c9c37aa11 | ||
|
901becc748 | ||
|
68fdae1184 | ||
|
8c7400121e | ||
|
3b9787d4ee | ||
|
7ae9662b4e | ||
|
457bd1392a | ||
|
a0776fe409 | ||
|
3bd9f936da | ||
|
386f0bfb4f | ||
|
edc91caffb | ||
|
27bdd038a8 | ||
|
9e2870cc9f | ||
|
d356561465 | ||
|
9d145c17c3 | ||
|
d1aacae0f7 | ||
|
e53703b88a | ||
|
66be32fbc1 | ||
|
4f936f2312 | ||
|
c534cf3bca | ||
|
d486b379d0 | ||
|
d19235993e | ||
|
1453ccd5b8 | ||
|
55937f9c8e | ||
|
4f9215e70f | ||
|
e59027e4f7 | ||
|
ee73875ff0 | ||
|
fe822f7043 | ||
|
82f187ce88 | ||
|
1c3ae2b678 | ||
|
5533f034e2 | ||
|
9d9e43b87f | ||
|
c81e204fd0 | ||
|
cdeb491498 | ||
|
c8f9dd2368 | ||
|
4ad98540bc | ||
|
cd3275ce73 | ||
|
db0de73d6e | ||
|
6ec2f1f44b | ||
|
7544b9fc10 | ||
|
4ccedceaa8 | ||
|
c496f80379 | ||
|
a176184b7d | ||
|
f3f7f5db89 | ||
|
2770485737 | ||
|
18d3283157 | ||
|
a882878eba | ||
|
2135bbe558 | ||
|
73967233e4 | ||
|
b058498404 | ||
|
b1e8af1c0c | ||
|
b69f73b13e | ||
|
d68c227aad | ||
|
7b64d9946d | ||
|
28786f826a | ||
|
ee31ba5023 | ||
|
d1f0b89e65 | ||
|
22e482d965 | ||
|
d786a8f820 | ||
|
9cf9ff6caf | ||
|
bbbe02b227 | ||
|
f4edd87ffc | ||
|
3589e515dc | ||
|
921ceddebf | ||
|
c44f3a5889 | ||
|
0e4fd4485f | ||
|
7ba0d8e07b | ||
|
622284740a | ||
|
29c0763480 | ||
|
6c6aebba88 | ||
|
8edc60ffdd | ||
|
8f77a14b69 | ||
|
db03270135 | ||
|
e71b663bf5 | ||
|
631b8edefb | ||
|
de2b11f39a | ||
|
2b7c832847 | ||
|
e38d974b50 | ||
|
35cefa50fa | ||
|
37773c1055 | ||
|
a5628cf782 | ||
|
ec47f0763d | ||
|
55e36d78a4 | ||
|
5210f6665c | ||
|
0e2904d2c5 | ||
|
3fa424f893 | ||
|
3f084b06e9 | ||
|
282d947c36 | ||
|
e291178633 | ||
|
46521a46d2 | ||
|
9ff0615546 | ||
|
c36e012926 | ||
|
d019c41f7a | ||
|
c7851b9c34 | ||
|
5d4b2f9ea9 | ||
|
e41da923a3 | ||
|
2b01af3de9 | ||
|
2e56778038 | ||
|
beae68890c | ||
|
8b8c9dea8a | ||
|
249446e0aa | ||
|
cb2873ba1c | ||
|
493af2bb16 | ||
|
7e017abb30 | ||
|
be9a64e654 | ||
|
a836872199 | ||
|
d8d4260df8 | ||
|
e6c6713a1b | ||
|
d12e843e4a | ||
|
f55dc3006e | ||
|
098bc780a2 | ||
|
dfaa891281 | ||
|
d5e58768aa | ||
|
63885da5b9 | ||
|
5cc54458b7 | ||
|
d2d8d0ab5a | ||
|
1a67bfe396 | ||
|
26766dcf73 | ||
|
c6efab0111 | ||
|
e8e5e6ee3c | ||
|
6afaaca2e5 | ||
|
9668d40d5a | ||
|
43020cc474 | ||
|
0627716f8a | ||
|
dd7663d2ae | ||
|
afe1b2bef7 | ||
|
46eeb62b04 | ||
|
85c7629345 | ||
|
b162475391 | ||
|
0bbbe08343 | ||
|
0b11b08b6e | ||
|
8b8b8ac1f8 | ||
|
9fa364414c | ||
|
1605d39b93 | ||
|
be2b3d5ab8 | ||
|
061c008e15 | ||
|
53da646495 | ||
|
627535f33e | ||
|
f117d47ffa | ||
|
48fd9fbd02 | ||
|
dc8837f079 | ||
|
fb124f0839 | ||
|
0ff027ae2c | ||
|
995c7b503b | ||
|
9aa47f9768 | ||
|
7d8981dd3f | ||
|
33931431c3 | ||
|
ac41deeeac | ||
|
f0fd03b122 | ||
|
eda99fc383 | ||
|
25ef7a7b1a | ||
|
63b469c160 | ||
|
f20be398a1 | ||
|
25a87ea16a | ||
|
f960fe0578 | ||
|
2c3742039c | ||
|
f5512315d2 | ||
|
37329e4184 | ||
|
44f86d38f9 | ||
|
1901a47df1 | ||
|
bccfd92f4a | ||
|
ede63b5029 | ||
|
b80404f2c6 | ||
|
470f1058a8 | ||
|
e3adccb528 | ||
|
e72e130e9d | ||
|
4edaa9fdf5 | ||
|
8f61a127b5 | ||
|
cf46f4baee | ||
|
0e8c631f5e | ||
|
c818f3dabc | ||
|
48fd6d6d40 | ||
|
6f52091668 | ||
|
d01e9de8b8 | ||
|
13bf42b8b8 | ||
|
a540b3f189 | ||
|
36bccbc4f3 | ||
|
3c70c243c5 | ||
|
19df4510c2 | ||
|
80899f7010 | ||
|
ffaff7afa6 | ||
|
e3cee67d77 | ||
|
368ab3051f | ||
|
529fe9ef75 | ||
|
e3dd3424fc | ||
|
d7b4a4ce01 | ||
|
df9e5f39a7 | ||
|
88aa285a79 | ||
|
d06378373e | ||
|
cb8486a9b2 | ||
|
d54deae0ad | ||
|
e930ee93f7 | ||
|
a9d7a9d128 | ||
|
3da18a06d8 | ||
|
744cdc3ba8 | ||
|
80d34abf49 | ||
|
637d812df5 | ||
|
c31dcf3632 | ||
|
396024713f | ||
|
a203499ba3 | ||
|
90713c84f3 | ||
|
a8fd6de907 | ||
|
fc2feabef7 | ||
|
984c024ef2 | ||
|
c7c51329f4 | ||
|
e2f29c4989 | ||
|
970e4d295e | ||
|
f5781144ab | ||
|
9d7061f1a3 | ||
|
f9d17f1f6d | ||
|
fac2e07333 | ||
|
fba81cf3e9 | ||
|
738c4b84fb | ||
|
de4cb219fb | ||
|
4276c703c5 | ||
|
f968833570 | ||
|
1885655e9a | ||
|
e75ac1b4c0 | ||
|
e1cfc075c2 | ||
|
8cbfd72f68 | ||
|
ab73ad4e5f | ||
|
b1b60887f0 | ||
|
d9cebeaf34 | ||
|
fa49651301 | ||
|
2eb34edeba | ||
|
5a44135233 | ||
|
2b8b51291f | ||
|
cc8178e911 | ||
|
e9eeb84040 | ||
|
86cf593e87 | ||
|
b85f9c183c | ||
|
39f312108d | ||
|
06464f7cfc | ||
|
9087ace2af | ||
|
d34d1f0173 | ||
|
670d982568 | ||
|
97770d5aeb | ||
|
a48847269a | ||
|
6a0e54f84f | ||
|
cb61d2294a | ||
|
29630b2d7f | ||
|
aa7f2ac954 | ||
|
c693aa8dac | ||
|
b81835b5ca | ||
|
c37416b6aa | ||
|
65d23a1d75 | ||
|
092f58a762 | ||
|
1f02c5f2e4 | ||
|
2ab2da5e02 | ||
|
5a6d1369f6 | ||
|
5a1248f1d4 | ||
|
14d0a9eef6 | ||
|
12b60e7c25 | ||
|
c4b42e9f59 | ||
|
71ff21f57c | ||
|
941c4a20d6 | ||
|
73abdedbc9 | ||
|
5803d9b689 | ||
|
61499e870a | ||
|
ba36ba8853 | ||
|
dde5b81079 | ||
|
ad73f571b8 | ||
|
8698f9dce6 | ||
|
6ca97e6e62 | ||
|
696ee52ffd | ||
|
096196281e | ||
|
5a96ca4a7f | ||
|
728617d25d | ||
|
085c3821a8 | ||
|
41e4cefc2e | ||
|
54617805b8 | ||
|
13225f1371 | ||
|
e548afd175 | ||
|
060491c4ee | ||
|
b764665f4d | ||
|
ee6519f8e2 | ||
|
741a166f3c | ||
|
23019946c2 | ||
|
2f3d8659b1 | ||
|
0b7239ebc7 | ||
|
80377eeb13 | ||
|
ac36153e99 | ||
|
2928891bd0 | ||
|
847f1dd99c | ||
|
abdb87dd23 | ||
|
606ecae5d7 | ||
|
016e469caf | ||
|
1fe2a74995 | ||
|
9385bea571 | ||
|
0e9fe272bc | ||
|
7cc414135a | ||
|
e3cc3e55c8 | ||
|
b2431d105e | ||
|
1c2782354c | ||
|
32b2e416cc | ||
|
ace8a2a868 | ||
|
39cc12e7c2 | ||
|
06e39625ee | ||
|
284fdb1745 | ||
|
96b2c20991 | ||
|
09e17f99c5 | ||
|
469bcc28ac | ||
|
d6771e513e | ||
|
f078ffc5e6 | ||
|
d040b68aee | ||
|
409a79621a | ||
|
4d2311655b | ||
|
f78b02477b | ||
|
c5e4326337 | ||
|
0670338e0b | ||
|
f6104adcb6 | ||
|
55b498b6b5 | ||
|
9b23ff5d50 | ||
|
ac25dd9be6 | ||
|
f71d3cce93 | ||
|
914d793858 | ||
|
81ef1fd0cc | ||
|
b3e45219c2 | ||
|
fdf2571679 | ||
|
1c60c6785c | ||
|
482501c21f | ||
|
a997714648 | ||
|
b89fc0564b | ||
|
a2b2ae35b2 | ||
|
8cbba1d164 | ||
|
75b28ab49d | ||
|
8eb3a5b557 | ||
|
bdcfd2d730 | ||
|
93484c2a62 | ||
|
97fc0ca49b | ||
|
f24eb81dbe | ||
|
4ae2dde5c3 | ||
|
2ecd290c0d | ||
|
ae512e20f5 | ||
|
7171260b94 | ||
|
f8712c6cab | ||
|
5ce236a691 | ||
|
64b28e0839 | ||
|
cb2d32bdc4 | ||
|
6e3b51681f | ||
|
6f1318c474 | ||
|
33f022617a | ||
|
85fb46d8a6 | ||
|
80bad4a3b4 | ||
|
a51c68aacb | ||
|
4d70e7bf78 | ||
|
c38b668fc3 | ||
|
7ec97ed5f2 | ||
|
491ee5d106 | ||
|
4c78bdcfaa | ||
|
857f5d6e65 | ||
|
b3b6c6b576 | ||
|
52f939caa7 | ||
|
00b5d7b037 | ||
|
9abcf5cb48 | ||
|
935813457f | ||
|
9ba9e99716 | ||
|
70c911b63f | ||
|
39457234db | ||
|
f35fa8c178 | ||
|
96123b9059 | ||
|
98a34e43ab | ||
|
721bee1b70 | ||
|
975368ba18 | ||
|
077b46e014 | ||
|
e022805f1d | ||
|
e36028b7d2 | ||
|
88f1e7a9a7 | ||
|
0dee6fc28c | ||
|
9bbbc1b265 | ||
|
558890ad0e | ||
|
5175e87fda | ||
|
226429058c | ||
|
44b070415b | ||
|
d43a79eec9 | ||
|
5154054af4 | ||
|
b90c5d6015 | ||
|
e84b00964f | ||
|
3596558861 | ||
|
8a07f57ba4 | ||
|
8b75bbe47d | ||
|
e48c9826e3 | ||
|
6ff65e6755 | ||
|
fa434a1837 | ||
|
b8db2c0a4a | ||
|
04860b6324 | ||
|
5848f75278 | ||
|
0a5712ada4 | ||
|
9756824f64 | ||
|
46fe47b8e0 | ||
|
a1d5fba666 | ||
|
aed91e49ae | ||
|
39d6a9601f | ||
|
2cb43449ee | ||
|
fec3087eef | ||
|
8d09124c62 | ||
|
657dde6208 | ||
|
ea6b5b694b | ||
|
1dbb86f8c7 | ||
|
7c3eca833f | ||
|
228a8e8c1f | ||
|
f0b48a23d9 | ||
|
4cf005d395 | ||
|
7ac5dbfd09 | ||
|
9105890d43 | ||
|
7f661a24c4 | ||
|
734d9791f8 | ||
|
4d64838048 | ||
|
17ee5df857 | ||
|
be6c34212b | ||
|
00633f8b66 | ||
|
fcf2057b38 | ||
|
74feebdab7 | ||
|
8e53b3bc14 | ||
|
e2ecc6c763 | ||
|
0591131a53 | ||
|
4cdb178968 | ||
|
24e4b6df11 | ||
|
3a75704756 | ||
|
3b4e7d1625 | ||
|
fd6e113bba | ||
|
05c2b10c5d | ||
|
bf794b66f4 | ||
|
bc28082b99 | ||
|
d418fc14f4 | ||
|
cc7c41abbd | ||
|
7b52a663a6 | ||
|
0cc5c2203b | ||
|
7267322fc1 | ||
|
4af8063c96 | ||
|
2fde4b6baa | ||
|
aa19f2aa3d | ||
|
6e8ede833b | ||
|
87eae82195 | ||
|
534269d0fb | ||
|
58293173cf | ||
|
f038fc3b17 | ||
|
c451d7925d | ||
|
39b2bd06b8 | ||
|
4fd2f433ad | ||
|
242bf56413 | ||
|
fae0ed8f10 | ||
|
871d9f379f | ||
|
662020c221 | ||
|
d7e922480e | ||
|
368381fd40 | ||
|
c4440b5b49 | ||
|
6d262eaf64 | ||
|
ffead4f333 | ||
|
7f2939d328 | ||
|
7b88c9f619 | ||
|
4a003ba671 | ||
|
7c8901dabd | ||
|
e42b56c31b | ||
|
b8aea8ae7d | ||
|
8476a09ee5 | ||
|
a51b6d5e42 | ||
|
5e4c0701d9 | ||
|
8947964f10 | ||
|
31cfcf7ce9 | ||
|
afc02ae6e7 | ||
|
ce8835d4c4 | ||
|
7cf5feb7d2 | ||
|
bbc67abeed | ||
|
f239ce2353 | ||
|
1f4e3832e0 | ||
|
2043bb0e38 | ||
|
b0f26a135b | ||
|
8bcf46a0ac | ||
|
80ebec099d | ||
|
4e0aab7428 | ||
|
b2360437e0 | ||
|
c331a3b1da | ||
|
11562bcc6b | ||
|
b030ef31de |
11
.gitignore
vendored
11
.gitignore
vendored
@@ -14,6 +14,8 @@
|
||||
*.so
|
||||
*.so.*
|
||||
*.sw*
|
||||
*.su
|
||||
*.patch
|
||||
*~
|
||||
|
||||
# gcov files:
|
||||
@@ -43,6 +45,12 @@ make.tmpl
|
||||
|
||||
coverity/coverity_model.xml
|
||||
|
||||
/.cache/
|
||||
/compile_commands.json
|
||||
|
||||
/doc/.ikiwiki
|
||||
/public
|
||||
|
||||
/libdm/.symver_check
|
||||
|
||||
daemons/clvmd
|
||||
@@ -50,7 +58,6 @@ daemons/dmfilemapd
|
||||
daemons/lvmetad/
|
||||
|
||||
tools/man-generator
|
||||
tools/man-generator.c
|
||||
|
||||
test/.lib-dir-stamp
|
||||
test/.tests-stamp
|
||||
@@ -144,6 +151,8 @@ test/lib/lvmchange
|
||||
test/lib/lvmdbusd.profile
|
||||
test/lib/lvmdevices
|
||||
test/lib/lvmetad
|
||||
test/lib/lvmlockctl
|
||||
test/lib/lvmlockd
|
||||
test/lib/lvmpolld
|
||||
test/lib/lvm_import_vdo
|
||||
test/lib/lvm_vdo_wrapper
|
||||
|
104
.gitlab-ci.yml
Normal file
104
.gitlab-ci.yml
Normal file
@@ -0,0 +1,104 @@
|
||||
stages:
|
||||
- approve
|
||||
- test
|
||||
|
||||
approve1:
|
||||
stage: approve
|
||||
script:
|
||||
- echo "Approved..."
|
||||
rules:
|
||||
# TODO: Filter only safe repositories, or user in developers
|
||||
- if: $CI_PROJECT_PATH != "csonto/lvm2" && $CI_PROJECT_PATH != "lvmteam/lvm2"
|
||||
when: manual
|
||||
# TODO: for other branches than main/rhel: run pipeline only when requested:
|
||||
- if: $CI_COMMIT_BRANCH != "main" && $CI_COMMIT_BRANCH !~ "^rhel.*"
|
||||
when: manual
|
||||
- when: on_success
|
||||
allow_failure: false
|
||||
|
||||
|
||||
pages:
|
||||
image: elecnix/ikiwiki
|
||||
stage: test
|
||||
script:
|
||||
- ikiwiki --setup ikiwiki.setup --libdir themes/ikistrap/lib
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
only:
|
||||
refs:
|
||||
- main
|
||||
changes:
|
||||
- doc/**/*
|
||||
- ikiwiki.setup
|
||||
|
||||
|
||||
# TODO:
|
||||
# - check results of autoreconf and make generate - may need additional commit
|
||||
# - we need a particular setup (rawhide OR latest supported fedora?)
|
||||
# - do make rpm and publish results as artifacts - we will use packit/COPR for this eventually
|
||||
|
||||
# Run on any commits to main (master), rhel8, rhel9 branches
|
||||
test-job:
|
||||
stage: test
|
||||
parallel:
|
||||
matrix:
|
||||
- TAG: rhel8
|
||||
CONFIGURE: >
|
||||
--with-cluster=internal
|
||||
--enable-cmirrord
|
||||
- TAG: rhel9
|
||||
CONFIGURE: >
|
||||
--with-default-use-devices-file=1
|
||||
--enable-app-machineid
|
||||
--enable-editline
|
||||
--disable-readline
|
||||
artifacts:
|
||||
paths:
|
||||
- test/results/
|
||||
expire_in: 1 week
|
||||
tags:
|
||||
- ${TAG}
|
||||
timeout: 2h
|
||||
script:
|
||||
# Common options go here, diffs to the above matrix
|
||||
- >
|
||||
./configure ${CONFIGURE}
|
||||
--enable-fsadm
|
||||
--enable-write_install
|
||||
--enable-pkgconfig
|
||||
--enable-cmdlib
|
||||
--enable-dmeventd
|
||||
--enable-blkid_wiping
|
||||
--enable-udev_sync
|
||||
--with-thin=internal
|
||||
--with-cache=internal
|
||||
--enable-lvmpolld
|
||||
--enable-lvmlockd-dlm --enable-lvmlockd-dlmcontrol
|
||||
--enable-lvmlockd-sanlock
|
||||
--enable-dbus-service --enable-notify-dbus
|
||||
--enable-dmfilemapd
|
||||
--with-writecache=internal
|
||||
--with-vdo=internal --with-vdo-format=/usr/bin/vdoformat
|
||||
--with-integrity=internal
|
||||
--disable-silent-rules
|
||||
- make
|
||||
- rm -rf test/results
|
||||
- mkdir -p /dev/shm/lvm2-test
|
||||
- mount -o remount,dev /dev/shm
|
||||
# TODO: Need to distinguish failed test from failed harness
|
||||
# TODO: Also need a way to find if run is incomplete, e.g. full disk resulting in many skipped tests
|
||||
- VERBOSE=0 BATCH=1 LVM_TEST_DIR=/dev/shm/lvm2-test make check || true
|
||||
- rm -rf /dev/shm/lvm2-test
|
||||
- cut -d' ' -f2 test/results/list | sort | uniq -c
|
||||
# Filter artifacts - keep only logs from tests which are not pass
|
||||
- cd test/results && rm $(grep 'passed$' list | cut -d' ' -f1 | sed -e 's|/|_|g' -e 's|.*|\0.txt|')
|
||||
# TODO: Keep a list of known failures, and translate into regexp - or simply use python...
|
||||
- if grep failed test/results/list | grep -v '\\\(dbustest\|lvconvert-mirror\)\.sh' | sort; then false; else true; fi
|
||||
rules:
|
||||
# Filter only safe repositories, or user in developers:
|
||||
# NOTE: Already done in approve stage, may be more caution than necessary
|
||||
- if: $CI_PROJECT_PATH != "csonto/lvm2" && $CI_PROJECT_PATH != "lvmteam/lvm2"
|
||||
when: manual
|
||||
- when: on_success
|
||||
|
@@ -38,7 +38,7 @@ ifeq ($(MAKECMDGOALS),distclean)
|
||||
udev po
|
||||
tools.distclean: test.distclean
|
||||
endif
|
||||
DISTCLEAN_DIRS += lcov_reports*
|
||||
DISTCLEAN_DIRS += lcov_reports* autom4te.cache
|
||||
DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
|
||||
|
||||
include make.tmpl
|
||||
@@ -55,7 +55,7 @@ po: tools daemons
|
||||
man: tools
|
||||
all_man: tools
|
||||
test: tools daemons
|
||||
unit-test run-unit-test: test
|
||||
unit-test run-unit-test: test libdm
|
||||
|
||||
daemons.device-mapper: libdm.device-mapper
|
||||
tools.device-mapper: libdm.device-mapper
|
||||
@@ -127,6 +127,7 @@ all_man:
|
||||
|
||||
install_system_dirs:
|
||||
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)/devices
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR)
|
||||
|
29
README
29
README
@@ -1,7 +1,5 @@
|
||||
This tree contains the LVM2 and device-mapper tools and libraries.
|
||||
|
||||
This is development branch, for stable 2.02 release see stable-2.02 branch.
|
||||
|
||||
For more information about LVM2 read the changelog in the WHATS_NEW file.
|
||||
Installation instructions are in INSTALL.
|
||||
|
||||
@@ -12,20 +10,30 @@ Tarballs are available from:
|
||||
https://github.com/lvmteam/lvm2/releases
|
||||
|
||||
The source code is stored in git:
|
||||
https://sourceware.org/git/?p=lvm2.git
|
||||
git clone git://sourceware.org/git/lvm2.git
|
||||
mirrored to:
|
||||
https://github.com/lvmteam/lvm2
|
||||
https://gitlab.com/lvmteam/lvm2
|
||||
Clone:
|
||||
git clone git@gitlab.com:lvmteam/lvm2.git
|
||||
Anonymous access:
|
||||
git clone https://gitlab.com/lvmteam/lvm2.git
|
||||
Mirrored to:
|
||||
* https://github.com/lvmteam/lvm2
|
||||
git clone https://github.com/lvmteam/lvm2.git
|
||||
git clone git@github.com:lvmteam/lvm2.git
|
||||
* https://sourceware.org/git/?p=lvm2.git
|
||||
git clone https://sourceware.org/git/lvm2.git
|
||||
git clone git://sourceware.org/git/lvm2.git
|
||||
|
||||
Mailing list for general discussion related to LVM2:
|
||||
linux-lvm@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||
linux-lvm@lists.linux.dev
|
||||
Subscribe via email to: linux-lvm+subscribe@lists.linux.dev
|
||||
Archive https://lore.kernel.org/linux-lvm/
|
||||
Older archive https://listman.redhat.com/archives/linux-lvm/
|
||||
|
||||
Mailing lists for LVM2 development, patches and commits:
|
||||
lvm-devel@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/lvm-devel
|
||||
lvm-devel@lists.linux.dev
|
||||
Subscribe via email to: lvm-devel+subscribe@lists.linux.dev
|
||||
Archive https://lore.kernel.org/lvm-devel/
|
||||
Older archive https://listman.redhat.com/archives/lvm-devel/
|
||||
|
||||
lvm2-commits@lists.fedorahosted.org (Read-only archive of commits)
|
||||
Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits
|
||||
@@ -41,6 +49,7 @@ Website:
|
||||
Report upstream bugs at:
|
||||
https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper
|
||||
or open issues at:
|
||||
https://gitlab.com/groups/lvmteam/-/issues
|
||||
https://github.com/lvmteam/lvm2/issues
|
||||
|
||||
The source code repository used until 7th June 2012 is accessible using CVS:
|
||||
|
5
TESTING
5
TESTING
@@ -21,6 +21,11 @@ You MUST disable (or mask) any LVM daemons:
|
||||
- clvmd
|
||||
- cmirrord
|
||||
|
||||
Some lvm.conf options should be set:
|
||||
|
||||
- global/event_activation = 0
|
||||
- activation/monitoring = 0
|
||||
|
||||
For running cluster tests, we are using singlenode locking. Pass
|
||||
`--with-clvmd=singlenode` to configure.
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
1.02.195 (2023-04-21)
|
||||
1.02.202-git (2024-10-02)
|
||||
|
281
WHATS_NEW
281
WHATS_NEW
@@ -1,3 +1,127 @@
|
||||
Version 2.03.28 -
|
||||
==================
|
||||
|
||||
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.
|
||||
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 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.
|
||||
Skip checking of pools for lvremove and vgremove commands.
|
||||
VDO modprobes dm-vdo for 6.9 kernel and kvdo for older kernel version.
|
||||
Fix lvs reporting for VDO volumes with new upstream kernel driver.
|
||||
Don't import DM_UDEV_DISABLE_OTHER_RULES_FLAG in LVM rules, DM rules cover it.
|
||||
Fix table line generation for cache snapshots using cachevol.
|
||||
Enhance lvconvert support for external origins stacking.
|
||||
When swapping LV names also swap properties like hostname, time and data.
|
||||
Fix removal of stacked external origins.
|
||||
Lock filesystem when converting volume to read-only external origin.
|
||||
Support external origin between different thin-pool.
|
||||
Improve validation of acceptable volumes for external origins.
|
||||
Reduce amount of preloaded devices for complex device trees.
|
||||
Avoid logging problems from monitoring snapshots with inactive origins.
|
||||
Check for cache policy module presence in kernel's builtin modules file.
|
||||
Add configure --with-modulesdir to select kernel modules directory.
|
||||
Support creation of thin-pool with VDO use for its data volume.
|
||||
|
||||
Version 2.03.23 - 21st November 2023
|
||||
====================================
|
||||
Set the first lv_attr flag for raid integrity images to i or I.
|
||||
Add -A option for pvs and pvscan to show PVs outside devices file.
|
||||
Improve searched_devnames temp file usage to prevent redundant scanning.
|
||||
Change default search_for_devnames from auto to all.
|
||||
Add lvmdevices --refresh to search for missing PVIDs on all devices.
|
||||
Add comparison between old and new entries in lvmdevices --check.
|
||||
Fix device_id matching order - match non-devname first.
|
||||
Fix "lvconvert -m 0" when there is other than first in-sync leg.
|
||||
Use system.devices as default for dmeventd when dmeventd.devices is undefined.
|
||||
Accept WWIDs containing QEMU HARDDISK for device_id.
|
||||
Improve handling of non-standard WWID prefixes used for device_id.
|
||||
Configure automatically enables cmdlib for dmeventd and notify-dbus for dbus.
|
||||
Fix hint calculation for pools with zero or error segment.
|
||||
Configure supports --disable-shared to build only static binaries.
|
||||
Configure supports --without-{blkid|systemd|udev} for easier static build.
|
||||
Refresh device ids if the system changes.
|
||||
Fix pvmove when specifying raid components as moved LVs.
|
||||
Enhance error detection for lvm_import_vdo.
|
||||
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.
|
||||
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.
|
||||
Require writable LV for conversion to vdo pool.
|
||||
Fix return value from lvconvert integrity remove.
|
||||
Preserve UUID for pool metadata spare.
|
||||
Preserve UUID for swapped pool metadata.
|
||||
Rewrite validation of device name entries used as device_id.
|
||||
|
||||
version 2.03.22 - 02nd August 2023
|
||||
==================================
|
||||
Fix pv_major/pv_minor report field types so they are integers, not strings.
|
||||
Add lvmdevices --delnotfound to delete entries for missing devices.
|
||||
Always use cachepool name for metadata backup LV for lvconvert --repair.
|
||||
Make metadata backup LVs read-only after pool's lvconvert --repair.
|
||||
Improve VDO and Thin support with lvmlockd.
|
||||
Handle 'lvextend --usepolicies' for pools for all activation variants.
|
||||
Fix memleak in vgchange autoactivation setup.
|
||||
Update py-compile building script.
|
||||
Support conversion from thick to fully provisioned thin LV.
|
||||
Cache/Thin-pool can use error and zero volumes for testing.
|
||||
Individual thin volume can be cached, but cannot take snapshot.
|
||||
Better internal support for handling error and zero target (for testing).
|
||||
Resize COW above trimmed maximal size is does not return error.
|
||||
Support parsing of vdo geometry format version 4.
|
||||
Add lvm.conf thin_restore and cache_restore settings.
|
||||
Handle multiple mounts while resizing volume with a FS.
|
||||
Handle leading/trailing spaces in sys_wwid and sys_serial used by device_id.
|
||||
Enhance lvm_import_vdo and use snapshot when converting VDO volume.
|
||||
Fix parsing of VDO metadata.
|
||||
Fix failing -S|--select for non-reporting cmds if using LV info/status fields.
|
||||
Allow snapshots of raid+integrity LV.
|
||||
Fix multisegment RAID1 allocator to prevent using single disk for more legs.
|
||||
|
||||
version 2.03.21 - 21st April 2023
|
||||
=================================
|
||||
Fix activation of vdo-pool for with 0 length headers (converted pools).
|
||||
@@ -33,6 +157,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.
|
||||
@@ -52,7 +177,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
|
||||
====================================
|
||||
@@ -139,8 +264,8 @@ 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 -Zn for conversion of already formated VDO pools.
|
||||
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.
|
||||
Support option --errorwhenfull when converting volume to thin-pool.
|
||||
@@ -170,7 +295,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.
|
||||
@@ -297,7 +422,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.
|
||||
@@ -310,14 +435,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.
|
||||
@@ -379,7 +504,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.
|
||||
@@ -424,7 +549,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.
|
||||
|
||||
@@ -440,7 +565,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.
|
||||
@@ -462,7 +587,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.
|
||||
@@ -552,13 +677,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".
|
||||
@@ -626,7 +751,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.
|
||||
@@ -676,8 +801,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.
|
||||
@@ -740,7 +865,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.
|
||||
@@ -780,7 +905,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.
|
||||
@@ -933,11 +1058,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
|
||||
@@ -962,7 +1087,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).
|
||||
@@ -1039,7 +1164,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.
|
||||
@@ -1068,7 +1193,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.
|
||||
@@ -1218,7 +1343,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.
|
||||
@@ -1375,7 +1500,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.
|
||||
@@ -1453,7 +1578,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.
|
||||
@@ -1519,13 +1644,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.
|
||||
@@ -1578,7 +1703,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.
|
||||
@@ -1646,7 +1771,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.
|
||||
@@ -1665,7 +1790,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.
|
||||
@@ -1770,7 +1895,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.
|
||||
@@ -1797,7 +1922,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.
|
||||
@@ -1839,7 +1964,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.
|
||||
|
||||
@@ -1912,7 +2037,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.
|
||||
@@ -2075,11 +2200,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
|
||||
@@ -2280,7 +2405,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.
|
||||
@@ -2330,7 +2455,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.
|
||||
@@ -2414,7 +2539,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.
|
||||
@@ -2427,7 +2552,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.
|
||||
@@ -2462,7 +2587,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().
|
||||
@@ -2535,7 +2660,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.
|
||||
@@ -2554,7 +2679,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).
|
||||
@@ -2584,7 +2709,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)
|
||||
@@ -2655,11 +2780,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.
|
||||
@@ -2725,13 +2850,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().
|
||||
@@ -2804,7 +2929,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.
|
||||
@@ -2830,7 +2955,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.
|
||||
@@ -2839,10 +2964,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.
|
||||
@@ -2856,7 +2981,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.
|
||||
@@ -2870,7 +2995,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.
|
||||
@@ -2925,7 +3050,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.
|
||||
@@ -2957,7 +3082,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.
|
||||
@@ -3226,7 +3351,7 @@ Version 2.02.68 - 23rd June 2010
|
||||
Add device name and offset to raw_read_mda_header error messages.
|
||||
Honour log argument when down-converting stacked mirror.
|
||||
Sleep to workaround clvmd -S race: socket closed early and server drops cmd.
|
||||
Use early udev synchronisation and update of dev nodes for clustered mirrors.
|
||||
Use early udev synchronization and update of dev nodes for clustered mirrors.
|
||||
Remove incorrect inclusion of kdev_t.h from cmirrord/functions.h.
|
||||
Add man pages for lvmconf and non-existent lvmsadc and lvmsar tools.
|
||||
Exit successfully when using -o help (but not -o +help) with LVM reports.
|
||||
@@ -3254,7 +3379,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.
|
||||
@@ -3305,7 +3430,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.
|
||||
@@ -3464,7 +3589,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
|
||||
===================================
|
||||
@@ -3480,7 +3605,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().
|
||||
@@ -3556,7 +3681,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
|
||||
@@ -3594,14 +3719,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.
|
||||
@@ -3781,7 +3906,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.
|
||||
@@ -3842,7 +3967,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.
|
||||
@@ -3915,7 +4040,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.
|
||||
@@ -4092,7 +4217,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.
|
||||
@@ -4139,7 +4264,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.
|
||||
@@ -4157,7 +4282,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.
|
||||
@@ -4165,7 +4290,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.
|
||||
@@ -4215,7 +4340,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.
|
||||
@@ -4587,7 +4712,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.
|
||||
@@ -4914,7 +5039,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.
|
||||
@@ -5145,7 +5270,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.
|
||||
@@ -5360,3 +5485,5 @@ Display output. Some metadata information cannot yet be displayed.
|
||||
|
||||
Recovery tools to salvage "lost" metadata directly from the disks:
|
||||
but we hope the new format will mean such tools are hardly ever needed!
|
||||
|
||||
|
||||
|
85
WHATS_NEW_DM
85
WHATS_NEW_DM
@@ -1,3 +1,48 @@
|
||||
Version 1.02.202 -
|
||||
===================
|
||||
|
||||
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.
|
||||
Use better code for closing opened descriptors when starting dmeventd.
|
||||
Correct dmeventd -R for systemd environment.
|
||||
Restart of dmeventd -R checks pid file to detect running dmeventd first.
|
||||
Query with dmeventd -i quickly ends when there is no running dmeventd.
|
||||
Enhance dm_get_status_raid to handle mismatching status or reported legs.
|
||||
Create /dev/disk/by-label symlinks for DM devs that have crypto as next layer.
|
||||
Persist udev db for DM devs on cleanup used in initrd to rootfs transition.
|
||||
Process synthetic udev events other than 'add/change' as 'change' events.
|
||||
Increase DM_UDEV_RULES_VSN to 3 to indicate changed udev rules.
|
||||
Rename DM_NOSCAN to .DM_NOSCAN so it's not stored in udev db.
|
||||
Rename DM_SUSPENDED to .DM_SUSPENDED so it's not stored in udev db.
|
||||
Do not import DM_UDEV_DISABLE_OTHER_RULES_FLAG from db in 10-dm-disk.rules.
|
||||
Test DISK_RO after importing properties from db in 10-dm.rules.
|
||||
Also import ID_FS_TYPE in 13-dm-disk.rules from db if needed.
|
||||
|
||||
Version 1.02.197 - 21st November 2023
|
||||
=====================================
|
||||
Fix invalid JSON report if using DM_REPORT_OUTPUT_MULTIPLE_TIMES and selection.
|
||||
Propagate ioctl errno from dm_task_run when creating new table line.
|
||||
Add support for group aliases in dmstats.
|
||||
Add support for exit-on file for dmeventd to reduce shutdown delays.
|
||||
Add configure option --with-dmeventd-exit-on-path to specify default path.
|
||||
Add dmsetup --headings none|abbrev|full to set report headings type.
|
||||
Add DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS to provide alternative headings.
|
||||
|
||||
Version 1.02.196 - 02nd August 2023
|
||||
===================================
|
||||
|
||||
Version 1.02.195 - 21st April 2023
|
||||
==================================
|
||||
|
||||
@@ -51,7 +96,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
|
||||
@@ -82,7 +127,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.
|
||||
|
||||
@@ -111,7 +156,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.
|
||||
@@ -160,7 +205,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).
|
||||
|
||||
@@ -355,7 +400,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
|
||||
=====================================
|
||||
@@ -370,7 +415,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'.
|
||||
@@ -543,7 +588,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
|
||||
@@ -562,7 +607,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.
|
||||
@@ -649,7 +694,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
|
||||
=====================================
|
||||
@@ -674,7 +719,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().
|
||||
@@ -771,7 +816,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.
|
||||
@@ -865,7 +910,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
|
||||
===============================
|
||||
@@ -880,7 +925,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
|
||||
==================================
|
||||
@@ -894,7 +939,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.
|
||||
@@ -1063,7 +1108,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
|
||||
@@ -1119,7 +1164,7 @@ Version 1.02.37 - 15th September 2009
|
||||
Version 1.02.36 - 6th August 2009
|
||||
=================================
|
||||
Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
|
||||
Add libdevmapper functions to support synchronisation with udev.
|
||||
Add libdevmapper functions to support synchronization with udev.
|
||||
|
||||
Version 1.02.35 - 28th July 2009
|
||||
================================
|
||||
@@ -1187,7 +1232,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.
|
||||
@@ -1243,7 +1288,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.
|
||||
@@ -1274,7 +1319,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.
|
||||
|
||||
@@ -1522,3 +1567,5 @@ Version 1.00.08 - 27 Feb 2004
|
||||
Fixed DESTDIR for make install/install_static_lib.
|
||||
Updated README/INSTALL to reflect move to sources.redhat.com.
|
||||
Updated autoconf files to 2003-06-17.
|
||||
|
||||
|
||||
|
13
aclocal.m4
vendored
13
aclocal.m4
vendored
@@ -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
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
#!/bin/sh
|
||||
# py-compile - Compile a Python program
|
||||
|
||||
scriptversion=2011-06-08.12; # UTC
|
||||
scriptversion=2023-03-30.00; # UTC
|
||||
|
||||
# Copyright (C) 2000-2014 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2000-2023 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,7 +16,7 @@ scriptversion=2011-06-08.12; # UTC
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
@@ -27,7 +27,7 @@ scriptversion=2011-06-08.12; # UTC
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
if [ -z "$PYTHON" ]; then
|
||||
if test -z "$PYTHON"; then
|
||||
PYTHON=python
|
||||
fi
|
||||
|
||||
@@ -62,13 +62,19 @@ while test $# -ne 0; do
|
||||
;;
|
||||
-h|--help)
|
||||
cat <<\EOF
|
||||
Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..."
|
||||
Usage: py-compile [options] FILES...
|
||||
|
||||
Byte compile some python scripts FILES. Use --destdir to specify any
|
||||
leading directory path to the FILES that you don't want to include in the
|
||||
byte compiled file. Specify --basedir for any additional path information you
|
||||
do want to be shown in the byte compiled file.
|
||||
|
||||
Options:
|
||||
--basedir DIR Prefix all FILES with DIR, and include in error messages.
|
||||
--destdir DIR Prefix all FILES with DIR before compiling.
|
||||
-v, --version Display version information.
|
||||
-h, --help This help screen.
|
||||
|
||||
Example:
|
||||
py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py
|
||||
|
||||
@@ -94,77 +100,143 @@ EOF
|
||||
shift
|
||||
done
|
||||
|
||||
files=$*
|
||||
if test -z "$files"; then
|
||||
usage_error "no files given"
|
||||
if test $# -eq 0; then
|
||||
usage_error "no files given"
|
||||
fi
|
||||
|
||||
# if basedir was given, then it should be prepended to filenames before
|
||||
# byte compilation.
|
||||
if [ -z "$basedir" ]; then
|
||||
pathtrans="path = file"
|
||||
if test -z "$basedir"; then
|
||||
pathtrans="path = file"
|
||||
else
|
||||
pathtrans="path = os.path.join('$basedir', file)"
|
||||
pathtrans="path = os.path.join('$basedir', file)"
|
||||
fi
|
||||
|
||||
# if destdir was given, then it needs to be prepended to the filename to
|
||||
# byte compile but not go into the compiled file.
|
||||
if [ -z "$destdir" ]; then
|
||||
filetrans="filepath = path"
|
||||
if test -z "$destdir"; then
|
||||
filetrans="filepath = path"
|
||||
else
|
||||
filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
|
||||
filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
|
||||
fi
|
||||
|
||||
$PYTHON -c "
|
||||
import sys, os, py_compile, imp
|
||||
python_major=`$PYTHON -c 'import sys; print(sys.version_info[0])'`
|
||||
if test -z "$python_major"; then
|
||||
usage_error "could not determine $PYTHON major version"
|
||||
fi
|
||||
|
||||
files = '''$files'''
|
||||
case $python_major in
|
||||
[01])
|
||||
usage_error "python version 0.x and 1.x not supported"
|
||||
;;
|
||||
esac
|
||||
|
||||
python_minor=`$PYTHON -c 'import sys; print(sys.version_info[1])'`
|
||||
|
||||
# NB: When adding support for newer versions, prefer copying & adding new cases
|
||||
# rather than try to keep things merged with shell variables.
|
||||
|
||||
# First byte compile (no optimization) all the modules.
|
||||
# This works for all currently known Python versions.
|
||||
$PYTHON -c "
|
||||
import sys, os, py_compile
|
||||
|
||||
try:
|
||||
import importlib
|
||||
except ImportError:
|
||||
importlib = None
|
||||
|
||||
# importlib.util.cache_from_source was added in 3.4
|
||||
if (
|
||||
hasattr(importlib, 'util')
|
||||
and hasattr(importlib.util, 'cache_from_source')
|
||||
):
|
||||
destpath = importlib.util.cache_from_source
|
||||
else:
|
||||
destpath = lambda filepath: filepath + 'c'
|
||||
|
||||
sys.stdout.write('Byte-compiling python modules...\n')
|
||||
for file in files.split():
|
||||
for file in sys.argv[1:]:
|
||||
$pathtrans
|
||||
$filetrans
|
||||
if not os.path.exists(filepath) or not (len(filepath) >= 3
|
||||
and filepath[-3:] == '.py'):
|
||||
continue
|
||||
sys.stdout.write(file)
|
||||
if (
|
||||
not os.path.exists(filepath)
|
||||
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
|
||||
):
|
||||
continue
|
||||
sys.stdout.write(file + ' ')
|
||||
sys.stdout.flush()
|
||||
if hasattr(imp, 'get_tag'):
|
||||
py_compile.compile(filepath, imp.cache_from_source(filepath), path)
|
||||
else:
|
||||
py_compile.compile(filepath, filepath + 'c', path)
|
||||
sys.stdout.write('\n')" || exit $?
|
||||
py_compile.compile(filepath, destpath(filepath), path)
|
||||
sys.stdout.write('\n')" "$@" || exit $?
|
||||
|
||||
# this will fail for python < 1.5, but that doesn't matter ...
|
||||
# Then byte compile w/optimization all the modules.
|
||||
$PYTHON -O -c "
|
||||
import sys, os, py_compile, imp
|
||||
import sys, os, py_compile
|
||||
|
||||
# pypy does not use .pyo optimization
|
||||
if hasattr(sys, 'pypy_translation_info'):
|
||||
try:
|
||||
import importlib
|
||||
except ImportError:
|
||||
importlib = None
|
||||
|
||||
# importlib.util.cache_from_source was added in 3.4
|
||||
if (
|
||||
hasattr(importlib, 'util')
|
||||
and hasattr(importlib.util, 'cache_from_source')
|
||||
):
|
||||
destpath = importlib.util.cache_from_source
|
||||
else:
|
||||
destpath = lambda filepath: filepath + 'o'
|
||||
|
||||
# pypy2 does not use .pyo optimization
|
||||
if sys.version_info.major <= 2 and hasattr(sys, 'pypy_translation_info'):
|
||||
sys.exit(0)
|
||||
|
||||
files = '''$files'''
|
||||
sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n')
|
||||
for file in files.split():
|
||||
for file in sys.argv[1:]:
|
||||
$pathtrans
|
||||
$filetrans
|
||||
if not os.path.exists(filepath) or not (len(filepath) >= 3
|
||||
and filepath[-3:] == '.py'):
|
||||
continue
|
||||
sys.stdout.write(file)
|
||||
if (
|
||||
not os.path.exists(filepath)
|
||||
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
|
||||
):
|
||||
continue
|
||||
sys.stdout.write(file + ' ')
|
||||
sys.stdout.flush()
|
||||
if hasattr(imp, 'get_tag'):
|
||||
py_compile.compile(filepath, imp.cache_from_source(filepath, False), path)
|
||||
else:
|
||||
py_compile.compile(filepath, filepath + 'o', path)
|
||||
sys.stdout.write('\n')" 2>/dev/null || :
|
||||
py_compile.compile(filepath, destpath(filepath), path)
|
||||
sys.stdout.write('\n')" "$@" 2>/dev/null || exit $?
|
||||
|
||||
# Then byte compile w/more optimization.
|
||||
# Only do this for Python 3.5+, see https://bugs.gnu.org/38043 for background.
|
||||
case $python_major.$python_minor in
|
||||
2.*|3.[0-4])
|
||||
;;
|
||||
*)
|
||||
$PYTHON -OO -c "
|
||||
import sys, os, py_compile, importlib
|
||||
|
||||
sys.stdout.write('Byte-compiling python modules (more optimized versions)'
|
||||
' ...\n')
|
||||
for file in sys.argv[1:]:
|
||||
$pathtrans
|
||||
$filetrans
|
||||
if (
|
||||
not os.path.exists(filepath)
|
||||
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
|
||||
):
|
||||
continue
|
||||
sys.stdout.write(file + ' ')
|
||||
sys.stdout.flush()
|
||||
py_compile.compile(filepath, importlib.util.cache_from_source(filepath), path)
|
||||
sys.stdout.write('\n')" "$@" 2>/dev/null || exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
@@ -31,10 +31,10 @@ CLEAN_TARGETS += $(BASE_DEPENDS) $(BASE_OBJECTS) \
|
||||
$(BASE_TARGET)
|
||||
|
||||
$(BASE_TARGET): $(BASE_OBJECTS)
|
||||
@echo " [AR] $@"
|
||||
$(SHOW) " [AR] $@"
|
||||
$(Q) $(RM) $@
|
||||
$(Q) $(AR) rsv $@ $(BASE_OBJECTS) > /dev/null
|
||||
|
||||
ifeq ("$(DEPENDS)","yes")
|
||||
ifeq ("$(USE_TRACKING)","yes")
|
||||
-include $(BASE_DEPENDS)
|
||||
endif
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ struct dm_hash_table {
|
||||
static unsigned _hash(const void *key, unsigned len)
|
||||
{
|
||||
/* Permutation of the Integers 0 through 255 */
|
||||
static unsigned char _nums[] = {
|
||||
static const unsigned char _nums[] = {
|
||||
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
|
||||
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
|
||||
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
|
||||
@@ -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)
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
@@ -69,7 +70,7 @@ struct node48 {
|
||||
};
|
||||
|
||||
struct node256 {
|
||||
uint32_t nr_entries;
|
||||
uint32_t nr_entries;
|
||||
struct value values[256];
|
||||
};
|
||||
|
||||
@@ -99,7 +100,7 @@ struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
|
||||
static inline void _dtr(struct radix_tree *rt, union radix_value v)
|
||||
{
|
||||
if (rt->dtr)
|
||||
rt->dtr(rt->dtr_context, v);
|
||||
rt->dtr(rt->dtr_context, v);
|
||||
}
|
||||
|
||||
// Returns the number of values removed
|
||||
@@ -118,8 +119,8 @@ static unsigned _free_node(struct radix_tree *rt, struct value v)
|
||||
break;
|
||||
|
||||
case VALUE:
|
||||
_dtr(rt, v.value);
|
||||
nr = 1;
|
||||
_dtr(rt, v.value);
|
||||
nr = 1;
|
||||
break;
|
||||
|
||||
case VALUE_CHAIN:
|
||||
@@ -178,9 +179,9 @@ unsigned radix_tree_size(struct radix_tree *rt)
|
||||
return rt->nr_entries;
|
||||
}
|
||||
|
||||
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv);
|
||||
static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv);
|
||||
|
||||
static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert_unset(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
unsigned len = ke - kb;
|
||||
|
||||
@@ -207,7 +208,7 @@ static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, u
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert_value(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
unsigned len = ke - kb;
|
||||
|
||||
@@ -234,7 +235,7 @@ static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, u
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
struct value_chain *vc = v->value.ptr;
|
||||
return _insert(rt, &vc->child, kb, ke, rv);
|
||||
@@ -248,7 +249,7 @@ static unsigned min(unsigned lhs, unsigned rhs)
|
||||
return rhs;
|
||||
}
|
||||
|
||||
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
struct prefix_chain *pc = v->value.ptr;
|
||||
|
||||
@@ -313,7 +314,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert_node4(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
struct node4 *n4 = v->value.ptr;
|
||||
if (n4->nr_entries == 4) {
|
||||
@@ -343,7 +344,7 @@ static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, u
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert_node16(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
struct node16 *n16 = v->value.ptr;
|
||||
|
||||
@@ -382,7 +383,7 @@ static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert_node48(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
struct node48 *n48 = v->value.ptr;
|
||||
if (n48->nr_entries == 48) {
|
||||
@@ -417,20 +418,20 @@ static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _insert_node256(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert_node256(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
struct node256 *n256 = v->value.ptr;
|
||||
bool r, was_unset = n256->values[*kb].type == UNSET;
|
||||
|
||||
r = _insert(rt, n256->values + *kb, kb + 1, ke, rv);
|
||||
if (r && was_unset)
|
||||
n256->nr_entries++;
|
||||
n256->nr_entries++;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// FIXME: the tree should not be touched if insert fails (eg, OOM)
|
||||
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
|
||||
{
|
||||
if (kb == ke) {
|
||||
if (v->type == UNSET) {
|
||||
@@ -487,10 +488,10 @@ static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t
|
||||
|
||||
struct lookup_result {
|
||||
struct value *v;
|
||||
uint8_t *kb;
|
||||
const uint8_t *kb;
|
||||
};
|
||||
|
||||
static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t *ke)
|
||||
static struct lookup_result _lookup_prefix(struct value *v, const uint8_t *kb, const uint8_t *ke)
|
||||
{
|
||||
unsigned i;
|
||||
struct value_chain *vc;
|
||||
@@ -500,7 +501,7 @@ static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t
|
||||
struct node48 *n48;
|
||||
struct node256 *n256;
|
||||
|
||||
if (kb == ke)
|
||||
if (kb == ke || !kb) /* extra check for !kb for coverity */
|
||||
return (struct lookup_result) {.v = v, .kb = kb};
|
||||
|
||||
switch (v->type) {
|
||||
@@ -555,8 +556,10 @@ static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t
|
||||
return (struct lookup_result) {.v = v, .kb = kb};
|
||||
}
|
||||
|
||||
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value rv)
|
||||
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value rv)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
|
||||
return _insert(rt, lr.v, lr.kb, ke, rv);
|
||||
}
|
||||
@@ -564,14 +567,14 @@ bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union ra
|
||||
// Note the degrade functions also free the original node.
|
||||
static void _degrade_to_n4(struct node16 *n16, struct value *result)
|
||||
{
|
||||
struct node4 *n4 = zalloc(sizeof(*n4));
|
||||
struct node4 *n4 = zalloc(sizeof(*n4));
|
||||
|
||||
assert(n4 != NULL);
|
||||
|
||||
n4->nr_entries = n16->nr_entries;
|
||||
memcpy(n4->keys, n16->keys, n16->nr_entries * sizeof(*n4->keys));
|
||||
memcpy(n4->values, n16->values, n16->nr_entries * sizeof(*n4->values));
|
||||
free(n16);
|
||||
n4->nr_entries = n16->nr_entries;
|
||||
memcpy(n4->keys, n16->keys, n16->nr_entries * sizeof(*n4->keys));
|
||||
memcpy(n4->values, n16->values, n16->nr_entries * sizeof(*n4->values));
|
||||
free(n16);
|
||||
|
||||
result->type = NODE4;
|
||||
result->value.ptr = n4;
|
||||
@@ -580,20 +583,20 @@ static void _degrade_to_n4(struct node16 *n16, struct value *result)
|
||||
static void _degrade_to_n16(struct node48 *n48, struct value *result)
|
||||
{
|
||||
unsigned i, count = 0;
|
||||
struct node16 *n16 = zalloc(sizeof(*n16));
|
||||
struct node16 *n16 = zalloc(sizeof(*n16));
|
||||
|
||||
assert(n16 != NULL);
|
||||
|
||||
n16->nr_entries = n48->nr_entries;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (n48->keys[i] < 48) {
|
||||
n16->keys[count] = i;
|
||||
n16->values[count] = n48->values[n48->keys[i]];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
n16->nr_entries = n48->nr_entries;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (n48->keys[i] < 48) {
|
||||
n16->keys[count] = i;
|
||||
n16->values[count] = n48->values[n48->keys[i]];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
free(n48);
|
||||
free(n48);
|
||||
|
||||
result->type = NODE16;
|
||||
result->value.ptr = n16;
|
||||
@@ -601,13 +604,13 @@ static void _degrade_to_n16(struct node48 *n48, struct value *result)
|
||||
|
||||
static void _degrade_to_n48(struct node256 *n256, struct value *result)
|
||||
{
|
||||
unsigned i, count = 0;
|
||||
struct node48 *n48 = zalloc(sizeof(*n48));
|
||||
unsigned i, count = 0;
|
||||
struct node48 *n48 = zalloc(sizeof(*n48));
|
||||
|
||||
assert(n48 != NULL);
|
||||
|
||||
n48->nr_entries = n256->nr_entries;
|
||||
for (i = 0; i < 256; i++) {
|
||||
n48->nr_entries = n256->nr_entries;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (n256->values[i].type == UNSET)
|
||||
n48->keys[i] = 48;
|
||||
|
||||
@@ -616,9 +619,9 @@ static void _degrade_to_n48(struct node256 *n256, struct value *result)
|
||||
n48->values[count] = n256->values[i];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(n256);
|
||||
free(n256);
|
||||
|
||||
result->type = NODE48;
|
||||
result->value.ptr = n48;
|
||||
@@ -632,14 +635,14 @@ static void _erase_elt(void *array, size_t obj_size, unsigned count, unsigned id
|
||||
return;
|
||||
|
||||
memmove(((uint8_t *) array) + (obj_size * idx),
|
||||
((uint8_t *) array) + (obj_size * (idx + 1)),
|
||||
obj_size * (count - idx - 1));
|
||||
((uint8_t *) array) + (obj_size * (idx + 1)),
|
||||
obj_size * (count - idx - 1));
|
||||
|
||||
// Zero the now unused last elt (set's v.type to UNSET)
|
||||
memset(((uint8_t *) array) + (count - 1) * obj_size, 0, obj_size);
|
||||
}
|
||||
|
||||
static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke)
|
||||
static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb, const uint8_t *ke)
|
||||
{
|
||||
bool r;
|
||||
unsigned i, j;
|
||||
@@ -651,27 +654,27 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
|
||||
struct node256 *n256;
|
||||
|
||||
if (kb == ke) {
|
||||
if (root->type == VALUE) {
|
||||
root->type = UNSET;
|
||||
_dtr(rt, root->value);
|
||||
return true;
|
||||
if (root->type == VALUE) {
|
||||
root->type = UNSET;
|
||||
_dtr(rt, root->value);
|
||||
return true;
|
||||
|
||||
} else if (root->type == VALUE_CHAIN) {
|
||||
} else if (root->type == VALUE_CHAIN) {
|
||||
vc = root->value.ptr;
|
||||
_dtr(rt, vc->value);
|
||||
memcpy(root, &vc->child, sizeof(*root));
|
||||
free(vc);
|
||||
return true;
|
||||
|
||||
} else
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (root->type) {
|
||||
case UNSET:
|
||||
case VALUE:
|
||||
// this is a value for a prefix of the key
|
||||
return false;
|
||||
// this is a value for a prefix of the key
|
||||
return false;
|
||||
|
||||
case VALUE_CHAIN:
|
||||
vc = root->value.ptr;
|
||||
@@ -686,11 +689,11 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
|
||||
case PREFIX_CHAIN:
|
||||
pc = root->value.ptr;
|
||||
if (ke - kb < pc->len)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
for (i = 0; i < pc->len; i++)
|
||||
if (kb[i] != pc->prefix[i])
|
||||
return false;
|
||||
return false;
|
||||
|
||||
r = _remove(rt, &pc->child, kb + pc->len, ke);
|
||||
if (r && pc->child.type == UNSET) {
|
||||
@@ -705,12 +708,12 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
|
||||
if (n4->keys[i] == *kb) {
|
||||
r = _remove(rt, n4->values + i, kb + 1, ke);
|
||||
if (r && n4->values[i].type == UNSET) {
|
||||
if (i < n4->nr_entries) {
|
||||
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
|
||||
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
|
||||
}
|
||||
if (i < n4->nr_entries) {
|
||||
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
|
||||
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
|
||||
}
|
||||
|
||||
n4->nr_entries--;
|
||||
n4->nr_entries--;
|
||||
if (!n4->nr_entries) {
|
||||
free(n4);
|
||||
root->type = UNSET;
|
||||
@@ -722,19 +725,19 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
|
||||
return false;
|
||||
|
||||
case NODE16:
|
||||
n16 = root->value.ptr;
|
||||
n16 = root->value.ptr;
|
||||
for (i = 0; i < n16->nr_entries; i++) {
|
||||
if (n16->keys[i] == *kb) {
|
||||
r = _remove(rt, n16->values + i, kb + 1, ke);
|
||||
if (r && n16->values[i].type == UNSET) {
|
||||
if (i < n16->nr_entries) {
|
||||
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
|
||||
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
|
||||
}
|
||||
if (i < n16->nr_entries) {
|
||||
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
|
||||
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
|
||||
}
|
||||
|
||||
n16->nr_entries--;
|
||||
n16->nr_entries--;
|
||||
if (n16->nr_entries <= 4) {
|
||||
_degrade_to_n4(n16, root);
|
||||
_degrade_to_n4(n16, root);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
@@ -746,18 +749,18 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
|
||||
n48 = root->value.ptr;
|
||||
i = n48->keys[*kb];
|
||||
if (i < 48) {
|
||||
r = _remove(rt, n48->values + i, kb + 1, ke);
|
||||
if (r && n48->values[i].type == UNSET) {
|
||||
n48->keys[*kb] = 48;
|
||||
for (j = 0; j < 256; j++)
|
||||
if (n48->keys[j] < 48 && n48->keys[j] > i)
|
||||
n48->keys[j]--;
|
||||
r = _remove(rt, n48->values + i, kb + 1, ke);
|
||||
if (r && n48->values[i].type == UNSET) {
|
||||
n48->keys[*kb] = 48;
|
||||
for (j = 0; j < 256; j++)
|
||||
if (n48->keys[j] < 48 && n48->keys[j] > i)
|
||||
n48->keys[j]--;
|
||||
_erase_elt(n48->values, sizeof(*n48->values), n48->nr_entries, i);
|
||||
n48->nr_entries--;
|
||||
if (n48->nr_entries <= 16)
|
||||
_degrade_to_n16(n48, root);
|
||||
}
|
||||
return r;
|
||||
_degrade_to_n16(n48, root);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -767,7 +770,7 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
|
||||
if (r && n256->values[*kb].type == UNSET) {
|
||||
n256->nr_entries--;
|
||||
if (n256->nr_entries <= 48)
|
||||
_degrade_to_n48(n256, root);
|
||||
_degrade_to_n48(n256, root);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -775,11 +778,14 @@ static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint
|
||||
return false;
|
||||
}
|
||||
|
||||
bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_end)
|
||||
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
{
|
||||
if (_remove(rt, &rt->root, key_begin, key_end)) {
|
||||
rt->nr_entries--;
|
||||
return true;
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
|
||||
if (_remove(rt, &rt->root, kb, ke)) {
|
||||
rt->nr_entries--;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -787,25 +793,25 @@ bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_e
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
static bool _prefix_chain_matches(struct lookup_result *lr, uint8_t *ke)
|
||||
static bool _prefix_chain_matches(const struct lookup_result *lr, const uint8_t *ke)
|
||||
{
|
||||
// It's possible the top node is a prefix chain, and
|
||||
// the remaining key matches part of it.
|
||||
if (lr->v->type == PREFIX_CHAIN) {
|
||||
unsigned i, rlen = ke - lr->kb;
|
||||
struct prefix_chain *pc = lr->v->value.ptr;
|
||||
if (rlen < pc->len) {
|
||||
for (i = 0; i < rlen; i++)
|
||||
if (pc->prefix[i] != lr->kb[i])
|
||||
return false;
|
||||
return true;
|
||||
// It's possible the top node is a prefix chain, and
|
||||
// the remaining key matches part of it.
|
||||
if (lr->v->type == PREFIX_CHAIN) {
|
||||
unsigned i, rlen = ke - lr->kb;
|
||||
const struct prefix_chain *pc = lr->v->value.ptr;
|
||||
if (rlen < pc->len) {
|
||||
for (i = 0; i < rlen; i++)
|
||||
if (pc->prefix[i] != lr->kb[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke, unsigned *count)
|
||||
static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uint8_t *kb, const uint8_t *ke, unsigned *count)
|
||||
{
|
||||
bool r;
|
||||
unsigned i, j, len;
|
||||
@@ -826,7 +832,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
|
||||
case UNSET:
|
||||
case VALUE:
|
||||
// No entries with the given prefix
|
||||
return true;
|
||||
return true;
|
||||
|
||||
case VALUE_CHAIN:
|
||||
vc = root->value.ptr;
|
||||
@@ -843,7 +849,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
|
||||
len = min(pc->len, ke - kb);
|
||||
for (i = 0; i < len; i++)
|
||||
if (kb[i] != pc->prefix[i])
|
||||
return true;
|
||||
return true;
|
||||
|
||||
r = _remove_subtree(rt, &pc->child, len < pc->len ? ke : (kb + pc->len), ke, count);
|
||||
if (r && pc->child.type == UNSET) {
|
||||
@@ -858,12 +864,12 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
|
||||
if (n4->keys[i] == *kb) {
|
||||
r = _remove_subtree(rt, n4->values + i, kb + 1, ke, count);
|
||||
if (r && n4->values[i].type == UNSET) {
|
||||
if (i < n4->nr_entries) {
|
||||
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
|
||||
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
|
||||
}
|
||||
if (i < n4->nr_entries) {
|
||||
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
|
||||
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
|
||||
}
|
||||
|
||||
n4->nr_entries--;
|
||||
n4->nr_entries--;
|
||||
if (!n4->nr_entries) {
|
||||
free(n4);
|
||||
root->type = UNSET;
|
||||
@@ -875,19 +881,19 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
|
||||
return true;
|
||||
|
||||
case NODE16:
|
||||
n16 = root->value.ptr;
|
||||
n16 = root->value.ptr;
|
||||
for (i = 0; i < n16->nr_entries; i++) {
|
||||
if (n16->keys[i] == *kb) {
|
||||
r = _remove_subtree(rt, n16->values + i, kb + 1, ke, count);
|
||||
if (r && n16->values[i].type == UNSET) {
|
||||
if (i < n16->nr_entries) {
|
||||
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
|
||||
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
|
||||
}
|
||||
if (i < n16->nr_entries) {
|
||||
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
|
||||
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
|
||||
}
|
||||
|
||||
n16->nr_entries--;
|
||||
n16->nr_entries--;
|
||||
if (n16->nr_entries <= 4)
|
||||
_degrade_to_n4(n16, root);
|
||||
_degrade_to_n4(n16, root);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -898,18 +904,18 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
|
||||
n48 = root->value.ptr;
|
||||
i = n48->keys[*kb];
|
||||
if (i < 48) {
|
||||
r = _remove_subtree(rt, n48->values + i, kb + 1, ke, count);
|
||||
if (r && n48->values[i].type == UNSET) {
|
||||
n48->keys[*kb] = 48;
|
||||
for (j = 0; j < 256; j++)
|
||||
if (n48->keys[j] < 48 && n48->keys[j] > i)
|
||||
n48->keys[j]--;
|
||||
r = _remove_subtree(rt, n48->values + i, kb + 1, ke, count);
|
||||
if (r && n48->values[i].type == UNSET) {
|
||||
n48->keys[*kb] = 48;
|
||||
for (j = 0; j < 256; j++)
|
||||
if (n48->keys[j] < 48 && n48->keys[j] > i)
|
||||
n48->keys[j]--;
|
||||
_erase_elt(n48->values, sizeof(*n48->values), n48->nr_entries, i);
|
||||
n48->nr_entries--;
|
||||
if (n48->nr_entries <= 16)
|
||||
_degrade_to_n16(n48, root);
|
||||
}
|
||||
return r;
|
||||
_degrade_to_n16(n48, root);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -922,7 +928,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
|
||||
if (r && n256->values[*kb].type == UNSET) {
|
||||
n256->nr_entries--;
|
||||
if (n256->nr_entries <= 48)
|
||||
_degrade_to_n48(n256, root);
|
||||
_degrade_to_n48(n256, root);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -931,11 +937,13 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len)
|
||||
{
|
||||
unsigned count = 0;
|
||||
const uint8_t *kb = prefix;
|
||||
const uint8_t *ke = kb + prefix_len;
|
||||
unsigned count = 0;
|
||||
|
||||
if (_remove_subtree(rt, &rt->root, kb, ke, &count))
|
||||
if (_remove_subtree(rt, &rt->root, kb, ke, &count))
|
||||
rt->nr_entries -= count;
|
||||
|
||||
return count;
|
||||
@@ -943,9 +951,11 @@ unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *k
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
bool radix_tree_lookup(struct radix_tree *rt,
|
||||
uint8_t *kb, uint8_t *ke, union radix_value *result)
|
||||
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
union radix_value *result)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
struct value_chain *vc;
|
||||
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
|
||||
if (lr.kb == ke) {
|
||||
@@ -968,58 +978,58 @@ bool radix_tree_lookup(struct radix_tree *rt,
|
||||
}
|
||||
|
||||
// FIXME: build up the keys too
|
||||
static bool _iterate(struct value *v, struct radix_tree_iterator *it)
|
||||
static bool _iterate(struct radix_tree_iterator *it, const struct value *v)
|
||||
{
|
||||
unsigned i;
|
||||
struct value_chain *vc;
|
||||
struct prefix_chain *pc;
|
||||
struct node4 *n4;
|
||||
struct node16 *n16;
|
||||
struct node48 *n48;
|
||||
struct node256 *n256;
|
||||
const struct value_chain *vc;
|
||||
const struct prefix_chain *pc;
|
||||
const struct node4 *n4;
|
||||
const struct node16 *n16;
|
||||
const struct node48 *n48;
|
||||
const struct node256 *n256;
|
||||
|
||||
switch (v->type) {
|
||||
case UNSET:
|
||||
// can't happen
|
||||
// can't happen
|
||||
break;
|
||||
|
||||
case VALUE:
|
||||
return it->visit(it, NULL, NULL, v->value);
|
||||
return it->visit(it, NULL, 0, v->value);
|
||||
|
||||
case VALUE_CHAIN:
|
||||
vc = v->value.ptr;
|
||||
return it->visit(it, NULL, NULL, vc->value) && _iterate(&vc->child, it);
|
||||
return it->visit(it, NULL, 0, vc->value) && _iterate(it, &vc->child);
|
||||
|
||||
case PREFIX_CHAIN:
|
||||
pc = v->value.ptr;
|
||||
return _iterate(&pc->child, it);
|
||||
return _iterate(it, &pc->child);
|
||||
|
||||
case NODE4:
|
||||
n4 = (struct node4 *) v->value.ptr;
|
||||
n4 = (const struct node4 *) v->value.ptr;
|
||||
for (i = 0; i < n4->nr_entries; i++)
|
||||
if (!_iterate(n4->values + i, it))
|
||||
return false;
|
||||
return true;
|
||||
if (!_iterate(it, n4->values + i))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
case NODE16:
|
||||
n16 = (struct node16 *) v->value.ptr;
|
||||
n16 = (const struct node16 *) v->value.ptr;
|
||||
for (i = 0; i < n16->nr_entries; i++)
|
||||
if (!_iterate(n16->values + i, it))
|
||||
return false;
|
||||
if (!_iterate(it, n16->values + i))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
case NODE48:
|
||||
n48 = (struct node48 *) v->value.ptr;
|
||||
n48 = (const struct node48 *) v->value.ptr;
|
||||
for (i = 0; i < n48->nr_entries; i++)
|
||||
if (!_iterate(n48->values + i, it))
|
||||
return false;
|
||||
if (!_iterate(it, n48->values + i))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
case NODE256:
|
||||
n256 = (struct node256 *) v->value.ptr;
|
||||
n256 = (const struct node256 *) v->value.ptr;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (n256->values[i].type != UNSET && !_iterate(n256->values + i, it))
|
||||
return false;
|
||||
if (n256->values[i].type != UNSET && !_iterate(it, n256->values + i))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1027,12 +1037,14 @@ static bool _iterate(struct value *v, struct radix_tree_iterator *it)
|
||||
return false;
|
||||
}
|
||||
|
||||
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
|
||||
struct radix_tree_iterator *it)
|
||||
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
struct radix_tree_iterator *it)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
|
||||
if (lr.kb == ke || _prefix_chain_matches(&lr, ke))
|
||||
(void) _iterate(lr.v, it);
|
||||
(void) _iterate(it, lr.v);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
@@ -1130,7 +1142,7 @@ static bool _check_nodes(struct value *v, unsigned *count)
|
||||
|
||||
if (ncount != n48->nr_entries) {
|
||||
fprintf(stderr, "incorrect number of entries in n48, n48->nr_entries = %u, actual = %u\n",
|
||||
n48->nr_entries, ncount);
|
||||
n48->nr_entries, ncount);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1166,7 +1178,7 @@ static bool _check_nodes(struct value *v, unsigned *count)
|
||||
|
||||
if (ncount != n256->nr_entries) {
|
||||
fprintf(stderr, "incorrect number of entries in n256, n256->nr_entries = %u, actual = %u\n",
|
||||
n256->nr_entries, ncount);
|
||||
n256->nr_entries, ncount);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1189,7 +1201,7 @@ bool radix_tree_is_well_formed(struct radix_tree *rt)
|
||||
|
||||
if (rt->nr_entries != count) {
|
||||
fprintf(stderr, "incorrect entry count: rt->nr_entries = %u, actual = %u\n",
|
||||
rt->nr_entries, count);
|
||||
rt->nr_entries, count);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1207,6 +1219,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
|
||||
struct node16 *n16;
|
||||
struct node48 *n48;
|
||||
struct node256 *n256;
|
||||
unsigned printable;
|
||||
|
||||
if (v.type == UNSET)
|
||||
return;
|
||||
@@ -1231,9 +1244,22 @@ static void _dump(FILE *out, struct value v, unsigned indent)
|
||||
|
||||
case PREFIX_CHAIN:
|
||||
pc = v.value.ptr;
|
||||
fprintf(out, "<prefix: ");
|
||||
fprintf(out, "<prefix(%u): ", pc->len);
|
||||
printable = 1;
|
||||
for (i = 0; i < pc->len; i++)
|
||||
fprintf(out, "%x.", (unsigned) *(pc->prefix + i));
|
||||
if (!isprint(pc->prefix[i])) {
|
||||
printable = 0;
|
||||
break;
|
||||
}
|
||||
if (printable)
|
||||
fputc('"', out);
|
||||
for (i = 0; i < pc->len; i++)
|
||||
if (printable)
|
||||
fprintf(out, "%c", pc->prefix[i]);
|
||||
else
|
||||
fprintf(out, "%02x.", (unsigned) *(pc->prefix + i));
|
||||
if (printable)
|
||||
fputc('"', out);
|
||||
fprintf(out, ">\n");
|
||||
_dump(out, pc->child, indent + 1);
|
||||
break;
|
||||
@@ -1242,7 +1268,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
|
||||
n4 = v.value.ptr;
|
||||
fprintf(out, "<n4: ");
|
||||
for (i = 0; i < n4->nr_entries; i++)
|
||||
fprintf(out, "%x ", (unsigned) n4->keys[i]);
|
||||
fprintf(out, "%02x ", (unsigned) n4->keys[i]);
|
||||
fprintf(out, ">\n");
|
||||
|
||||
for (i = 0; i < n4->nr_entries; i++)
|
||||
@@ -1253,7 +1279,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
|
||||
n16 = v.value.ptr;
|
||||
fprintf(out, "<n16: ");
|
||||
for (i = 0; i < n16->nr_entries; i++)
|
||||
fprintf(out, "%x ", (unsigned) n16->keys[i]);
|
||||
fprintf(out, "%02x ", (unsigned) n16->keys[i]);
|
||||
fprintf(out, ">\n");
|
||||
|
||||
for (i = 0; i < n16->nr_entries; i++)
|
||||
@@ -1265,7 +1291,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
|
||||
fprintf(out, "<n48: ");
|
||||
for (i = 0; i < 256; i++)
|
||||
if (n48->keys[i] < 48)
|
||||
fprintf(out, "%x ", i);
|
||||
fprintf(out, "%02x ", i);
|
||||
fprintf(out, ">\n");
|
||||
|
||||
for (i = 0; i < n48->nr_entries; i++) {
|
||||
@@ -1279,7 +1305,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
|
||||
fprintf(out, "<n256: ");
|
||||
for (i = 0; i < 256; i++)
|
||||
if (n256->values[i].type != UNSET)
|
||||
fprintf(out, "%x ", i);
|
||||
fprintf(out, "%02x ", i);
|
||||
fprintf(out, ">\n");
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
// This file is part of LVM2.
|
||||
//
|
||||
// This copyrighted material is made available to anyone wishing to use,
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// This implementation is based around nested binary trees. Very
|
||||
@@ -37,12 +38,12 @@ struct node {
|
||||
struct radix_tree {
|
||||
radix_value_dtr dtr;
|
||||
void *dtr_context;
|
||||
unsigned nr_entries;
|
||||
|
||||
struct node *root;
|
||||
};
|
||||
|
||||
struct radix_tree *
|
||||
radix_tree_create(radix_value_dtr dtr, void *dtr_context)
|
||||
struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
|
||||
{
|
||||
struct radix_tree *rt = zalloc(sizeof(*rt));
|
||||
|
||||
@@ -105,7 +106,7 @@ unsigned radix_tree_size(struct radix_tree *rt)
|
||||
return _count(rt->root);
|
||||
}
|
||||
|
||||
static struct node **_lookup(struct node **pn, uint8_t *kb, uint8_t *ke)
|
||||
static struct node **_lookup(struct node **pn, const uint8_t *kb, const uint8_t *ke)
|
||||
{
|
||||
struct node *n = *pn;
|
||||
|
||||
@@ -122,7 +123,7 @@ static struct node **_lookup(struct node **pn, uint8_t *kb, uint8_t *ke)
|
||||
return _lookup(&n->center, kb + 1, ke);
|
||||
}
|
||||
|
||||
static bool _insert(struct node **pn, uint8_t *kb, uint8_t *ke, union radix_value v)
|
||||
static bool _insert(struct node **pn, const uint8_t *kb, const uint8_t *ke, union radix_value v)
|
||||
{
|
||||
struct node *n = *pn;
|
||||
|
||||
@@ -151,39 +152,51 @@ static bool _insert(struct node **pn, uint8_t *kb, uint8_t *ke, union radix_valu
|
||||
return _insert(&n->center, kb + 1, ke, v);
|
||||
}
|
||||
|
||||
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v)
|
||||
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
union radix_value v)
|
||||
{
|
||||
return _insert(&rt->root, kb, ke, v);
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
|
||||
if (!_insert(&rt->root, kb, ke, v))
|
||||
return false;
|
||||
|
||||
rt->nr_entries++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
|
||||
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
struct node **pn = _lookup(&rt->root, kb, ke);
|
||||
struct node *n = *pn;
|
||||
|
||||
if (!n || !n->has_value)
|
||||
return false;
|
||||
|
||||
else {
|
||||
if (rt->dtr)
|
||||
rt->dtr(rt->dtr_context, n->value);
|
||||
rt->nr_entries--;
|
||||
|
||||
if (n->left || n->center || n->right) {
|
||||
n->has_value = false;
|
||||
return true;
|
||||
if (rt->dtr)
|
||||
rt->dtr(rt->dtr_context, n->value);
|
||||
|
||||
} else {
|
||||
// FIXME: delete parent if this was the last entry
|
||||
free(n);
|
||||
*pn = NULL;
|
||||
}
|
||||
if (n->left || n->center || n->right) {
|
||||
n->has_value = false;
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: delete parent if this was the last entry
|
||||
free(n);
|
||||
*pn = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
struct node **pn;
|
||||
unsigned count;
|
||||
|
||||
@@ -197,17 +210,20 @@ unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *k
|
||||
return count;
|
||||
}
|
||||
|
||||
bool
|
||||
radix_tree_lookup(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value *result)
|
||||
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
union radix_value *result)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
struct node **pn = _lookup(&rt->root, kb, ke);
|
||||
struct node *n = *pn;
|
||||
|
||||
if (n && n->has_value) {
|
||||
*result = n->value;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void _iterate(struct node *n, struct radix_tree_iterator *it)
|
||||
@@ -219,15 +235,18 @@ static void _iterate(struct node *n, struct radix_tree_iterator *it)
|
||||
|
||||
if (n->has_value)
|
||||
// FIXME: fill out the key
|
||||
it->visit(it, NULL, NULL, n->value);
|
||||
it->visit(it, NULL, 0, n->value);
|
||||
|
||||
_iterate(n->center, it);
|
||||
_iterate(n->right, it);
|
||||
}
|
||||
|
||||
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
|
||||
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
struct radix_tree_iterator *it)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
|
||||
if (kb == ke)
|
||||
_iterate(rt->root, it);
|
||||
|
||||
@@ -237,7 +256,7 @@ void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
|
||||
|
||||
if (n) {
|
||||
if (n->has_value)
|
||||
it->visit(it, NULL, NULL, n->value);
|
||||
it->visit(it, NULL, 0, n->value);
|
||||
_iterate(n->center, it);
|
||||
}
|
||||
}
|
||||
@@ -248,8 +267,32 @@ bool radix_tree_is_well_formed(struct radix_tree *rt)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _dump(FILE *out, struct node *n, unsigned indent)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
_dump(out, n->left, indent + 1);
|
||||
|
||||
for (i = 0; i < 2 * indent; i++)
|
||||
fprintf(out, " ");
|
||||
|
||||
if (n->has_value) {
|
||||
fprintf(out, "value: %llu\n", n->value.n);
|
||||
} else {
|
||||
fprintf(out, "key: '%c' [0x%02x] %u\n",
|
||||
isprint(n->key) ? n->key : ' ', n->key, indent);
|
||||
}
|
||||
|
||||
_dump(out, n->center, indent + 1);
|
||||
_dump(out, n->right, indent + 1);
|
||||
}
|
||||
|
||||
void radix_tree_dump(struct radix_tree *rt, FILE *out)
|
||||
{
|
||||
_dump(out, rt->root, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
@@ -19,3 +19,45 @@
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
struct visitor {
|
||||
struct radix_tree_iterator it;
|
||||
unsigned pos, nr_entries;
|
||||
union radix_value *values;
|
||||
};
|
||||
|
||||
static bool _visitor(struct radix_tree_iterator *it,
|
||||
const void *key, size_t keylen,
|
||||
union radix_value v)
|
||||
{
|
||||
struct visitor *vt = container_of(it, struct visitor, it);
|
||||
|
||||
if (vt->pos >= vt->nr_entries)
|
||||
return false;
|
||||
|
||||
vt->values[vt->pos++] = v;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool radix_tree_values(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
union radix_value **values, unsigned *nr_values)
|
||||
{
|
||||
struct visitor vt = {
|
||||
.it.visit = _visitor,
|
||||
.nr_entries = rt->nr_entries,
|
||||
.values = calloc(rt->nr_entries + 1, sizeof(union radix_value)),
|
||||
};
|
||||
|
||||
if (vt.values) {
|
||||
// build set of all values in current radix tree
|
||||
radix_tree_iterate(rt, key, keylen, &vt.it);
|
||||
*nr_values = vt.pos;
|
||||
*values = vt.values;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
@@ -33,32 +33,51 @@ struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context);
|
||||
void radix_tree_destroy(struct radix_tree *rt);
|
||||
|
||||
unsigned radix_tree_size(struct radix_tree *rt);
|
||||
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v);
|
||||
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke);
|
||||
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 the number of values removed
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *prefix_b, uint8_t *prefix_e);
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len);
|
||||
|
||||
bool radix_tree_lookup(struct radix_tree *rt,
|
||||
uint8_t *kb, uint8_t *ke, union radix_value *result);
|
||||
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
union radix_value *result);
|
||||
|
||||
// The radix tree stores entries in lexicographical order. Which means
|
||||
// we can iterate entries, in order. Or iterate entries with a particular
|
||||
// prefix.
|
||||
struct radix_tree_iterator {
|
||||
// Returns false if the iteration should end.
|
||||
// Returns false if the iteration should end.
|
||||
bool (*visit)(struct radix_tree_iterator *it,
|
||||
uint8_t *kb, uint8_t *ke, union radix_value v);
|
||||
const void *key, size_t keylen, union radix_value v);
|
||||
};
|
||||
|
||||
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
|
||||
struct radix_tree_iterator *it);
|
||||
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
struct radix_tree_iterator *it);
|
||||
|
||||
// Alternative traversing radix_tree.
|
||||
// Builds whole set all radix_tree nr_values values.
|
||||
// After use, free(values).
|
||||
bool radix_tree_values(struct radix_tree *rt, const void *key, size_t keylen,
|
||||
union radix_value **values, unsigned *nr_values);
|
||||
|
||||
// Checks that some constraints on the shape of the tree are
|
||||
// being held. For debug only.
|
||||
bool radix_tree_is_well_formed(struct radix_tree *rt);
|
||||
void radix_tree_dump(struct radix_tree *rt, FILE *out);
|
||||
|
||||
// Shortcut for ptr value return
|
||||
// Note: if value would be NULL, it's same result for not/found case.
|
||||
static inline void *radix_tree_lookup_ptr(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
{
|
||||
union radix_value v;
|
||||
return radix_tree_lookup(rt, key, keylen, &v) ? v.ptr : NULL;
|
||||
}
|
||||
|
||||
static inline bool radix_tree_insert_ptr(struct radix_tree *rt, const void *key, size_t keylen, void *ptr)
|
||||
{
|
||||
union radix_value v = { .ptr = ptr };
|
||||
return radix_tree_insert(rt, key, keylen, v);
|
||||
}
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
|
@@ -49,7 +49,7 @@ install_localconf: $(CONFLOCAL)
|
||||
fi
|
||||
|
||||
install_profiles: $(PROFILES)
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_DIR) $(profiledir)
|
||||
$(Q) $(INSTALL_DATA) $(PROFILES) $(profiledir)/
|
||||
|
||||
|
@@ -122,7 +122,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.
|
||||
@@ -135,6 +135,16 @@ devices {
|
||||
# This configuration option has an automatic default value.
|
||||
# devicesfile = "system.devices"
|
||||
|
||||
# Configuration option devices/devicesfile_backup_limit.
|
||||
# The max number of backup files to keep in /etc/lvm/devices/backup.
|
||||
# LVM creates a backup of the devices file each time a new
|
||||
# version is created, or each time a modification is detected.
|
||||
# When the max number of backups is reached, the oldest are
|
||||
# removed to remain at the limit. Set to 0 to disable backups.
|
||||
# Only the system devices file is backed up.
|
||||
# This configuration option has an automatic default value.
|
||||
# devicesfile_backup_limit = 50
|
||||
|
||||
# Configuration option devices/search_for_devnames.
|
||||
# Look outside of the devices file for missing devname entries.
|
||||
# A devname entry is used for a device that does not have a stable
|
||||
@@ -149,7 +159,27 @@ devices {
|
||||
# at other devices, but only those that are likely to have the PV.
|
||||
# If "all", lvm will look at all devices on the system.
|
||||
# This configuration option has an automatic default value.
|
||||
# search_for_devnames = "auto"
|
||||
# search_for_devnames = "all"
|
||||
|
||||
# Configuration option devices/device_ids_refresh.
|
||||
# Find PVs on new devices and update the device IDs in the devices file.
|
||||
# If PVs are restored or moved to a new system with new devices, but
|
||||
# an old system.devices remains with old device IDs, then search for
|
||||
# the PVIDs on new devices and update the device IDs in system.devices.
|
||||
# The original device IDs must also not be found on the new system.
|
||||
# See device_ids_refresh_check for conditions that trigger the refresh.
|
||||
# This configuration option has an automatic default value.
|
||||
# device_ids_refresh = 1
|
||||
|
||||
# Configuration option devices/device_ids_refresh_checks.
|
||||
# Conditions that trigger device_ids_refresh to locate PVIDs on new devices.
|
||||
# product_uuid: refresh if /sys/devices/virtual/dmi/id/product_uuid does not
|
||||
# match the value saved in system.devices.
|
||||
# hostname: refresh if hostname does not match the value saved in system.devices.
|
||||
# (hostname is used if product_uuid is not available.)
|
||||
# Remove values from this list to prevent lvm from using them.
|
||||
# This configuration option has an automatic default value.
|
||||
# device_ids_refresh_checks = [ "product_uuid", "hostname" ]
|
||||
|
||||
# Configuration option devices/filter.
|
||||
# Limit the block devices that are used by LVM commands.
|
||||
@@ -211,17 +241,12 @@ devices {
|
||||
# sysfs_scan = 1
|
||||
|
||||
# Configuration option devices/scan_lvs.
|
||||
# Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.
|
||||
# When 1, LVM will detect PVs layered on LVs, and caution must be
|
||||
# taken to avoid a host accessing a layered VG that may not belong
|
||||
# to it, e.g. from a guest image. This generally requires excluding
|
||||
# the LVs with device filters. Also, when this setting is enabled,
|
||||
# every LVM command will scan every active LV on the system (unless
|
||||
# filtered), which can cause performance problems on systems with
|
||||
# many active LVs. When this setting is 0, LVM will not detect or
|
||||
# use PVs that exist on LVs, and will not allow a PV to be created on
|
||||
# an LV. The LVs are ignored using a built in device filter that
|
||||
# identifies and excludes LVs.
|
||||
# Allow LVM LVs to be used as PVs. When enabled, LVM commands will
|
||||
# scan active LVs to look for other PVs. Caution is required to
|
||||
# avoid using PVs that belong to guest images stored on LVs.
|
||||
# When enabled, the LVs scanned should be restricted using the
|
||||
# devices file or the filter. This option does not enable autoactivation
|
||||
# of layered VGs, which requires editing LVM udev rules (see LVM_PVSCAN_ON_LVS.)
|
||||
# This configuration option has an automatic default value.
|
||||
# scan_lvs = 0
|
||||
|
||||
@@ -537,7 +562,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.
|
||||
|
||||
@@ -621,13 +646,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.
|
||||
@@ -650,11 +668,6 @@ allocation {
|
||||
# This configuration option has an automatic default value.
|
||||
# vdo_block_map_period = 16380
|
||||
|
||||
# Configuration option allocation/vdo_check_point_frequency.
|
||||
# The default check point frequency for VDO volume.
|
||||
# This configuration option has an automatic default value.
|
||||
# vdo_check_point_frequency = 0
|
||||
|
||||
# Configuration option allocation/vdo_use_sparse_index.
|
||||
# Enables sparse indexing for VDO volume.
|
||||
# This configuration option has an automatic default value.
|
||||
@@ -731,19 +744,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,
|
||||
@@ -781,6 +781,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
|
||||
|
||||
@@ -810,8 +813,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)"
|
||||
|
||||
@@ -1012,7 +1016,7 @@ global {
|
||||
# Location of proc filesystem.
|
||||
# This configuration option is advanced.
|
||||
# This configuration option has an automatic default value.
|
||||
# proc = "/proc"
|
||||
# proc = "@DEFAULT_PROC_DIR@"
|
||||
|
||||
# Configuration option global/etc.
|
||||
# Location of /etc system configuration directory.
|
||||
@@ -1156,7 +1160,7 @@ global {
|
||||
# services (via the lvm2-activation-generator), but the autoactivation
|
||||
# services and generator have been removed.
|
||||
# This configuration option has an automatic default value.
|
||||
# event_activation = 1
|
||||
# event_activation = @DEFAULT_EVENT_ACTIVATION@
|
||||
|
||||
# Configuration option global/use_aio.
|
||||
# Use async I/O when reading and writing devices.
|
||||
@@ -1188,6 +1192,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
|
||||
@@ -1201,7 +1215,7 @@ global {
|
||||
|
||||
# Configuration option global/thin_check_executable.
|
||||
# The full path to the thin_check command.
|
||||
# LVM uses this command to check that a thin metadata device is in a
|
||||
# LVM uses this command to check that a thin pool metadata device is in a
|
||||
# usable state. When a thin pool is activated and after it is
|
||||
# deactivated, this command is run. Activation will only proceed if
|
||||
# the command has an exit status of 0. Set to "" to skip this check.
|
||||
@@ -1225,6 +1239,14 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_repair_executable = "@THIN_REPAIR_CMD@"
|
||||
|
||||
# Configuration option global/thin_restore_executable.
|
||||
# The full path to the thin_restore command.
|
||||
# LVM uses this command to restore generated data for a thin pool metadata device.
|
||||
# Also see thin_restore_options.
|
||||
# (See package device-mapper-persistent-data or thin-provisioning-tools)
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_restore_executable = "@THIN_RESTORE_CMD@"
|
||||
|
||||
# Configuration option global/thin_check_options.
|
||||
# List of options passed to the thin_check command.
|
||||
# With thin_check version 2.1 or newer you can add the option
|
||||
@@ -1239,6 +1261,11 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_repair_options = [ "" ]
|
||||
|
||||
# Configuration option global/thin_restore_options.
|
||||
# List of options passed to the thin_restore command.
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_restore_options = [ "" ]
|
||||
|
||||
# Configuration option global/thin_disabled_features.
|
||||
# Features to not use in the thin driver.
|
||||
# This can be helpful for testing, or to avoid using a feature that is
|
||||
@@ -1287,6 +1314,14 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_repair_executable = "@CACHE_REPAIR_CMD@"
|
||||
|
||||
# Configuration option global/cache_restore_executable.
|
||||
# The full path to the cache_restore command.
|
||||
# LVM uses this command to restore generated data for a cache metadata device.
|
||||
# Also see cache_restore_options.
|
||||
# (See package device-mapper-persistent-data or thin-provisioning-tools)
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_restore_executable = "@CACHE_RESTORE_CMD@"
|
||||
|
||||
# Configuration option global/cache_check_options.
|
||||
# List of options passed to the cache_check command.
|
||||
# With cache_check version 5.0 or newer you should include the option
|
||||
@@ -1299,6 +1334,11 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_repair_options = [ "" ]
|
||||
|
||||
# Configuration option global/cache_restore_options.
|
||||
# List of options passed to the cache_restore command.
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_restore_options = [ "" ]
|
||||
|
||||
# Configuration option global/vdo_format_executable.
|
||||
# The full path to the vdoformat command.
|
||||
# LVM uses this command to initial data volume for VDO type logical volume
|
||||
@@ -1313,10 +1353,10 @@ global {
|
||||
# Configuration option global/vdo_disabled_features.
|
||||
# Features to not use in the vdo driver.
|
||||
# This can be helpful for testing, or to avoid using a feature that is
|
||||
# causing problems. Features include: online_rename
|
||||
# causing problems. Features include: online_rename, version4
|
||||
#
|
||||
# Example
|
||||
# vdo_disabled_features = [ "online_rename" ]
|
||||
# vdo_disabled_features = [ "online_rename", "version4" ]
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
@@ -1346,8 +1386,9 @@ global {
|
||||
# Use an LVM-specific derivation of the local machine-id as the
|
||||
# system ID. See 'man machine-id'.
|
||||
# machineid
|
||||
# Use the contents of the machine-id file to set the system ID
|
||||
# (appmachineid is recommended.)
|
||||
# Use the contents of the machine-id file to set the system ID.
|
||||
# (appmachineid is recommended to avoid exposing the confidential
|
||||
# machine-id.)
|
||||
# file
|
||||
# Use the contents of another file (system_id_file) to set the
|
||||
# system ID.
|
||||
@@ -1464,12 +1505,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
|
||||
|
||||
@@ -1790,7 +1833,7 @@ activation {
|
||||
# Configuration option activation/polling_interval.
|
||||
# Check pvmove or lvconvert progress at this interval (seconds).
|
||||
# When pvmove or lvconvert must wait for the kernel to finish
|
||||
# synchronising or merging data, they check and report progress at
|
||||
# synchronizing or merging data, they check and report progress at
|
||||
# intervals of this number of seconds. If this is set to 0 and there
|
||||
# is only one thing to wait for, there are no progress reports, but
|
||||
# the process is awoken immediately once the operation is complete.
|
||||
@@ -1818,7 +1861,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
|
||||
@@ -1935,15 +1978,14 @@ activation {
|
||||
|
||||
# Configuration section report.
|
||||
# LVM report command output formatting.
|
||||
# This configuration section has an automatic default value.
|
||||
# report {
|
||||
report {
|
||||
|
||||
# Configuration option report/output_format.
|
||||
# Format of LVM command's report output.
|
||||
# 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
|
||||
@@ -1957,6 +1999,7 @@ activation {
|
||||
# - 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"
|
||||
|
||||
@@ -1996,7 +2039,11 @@ activation {
|
||||
# buffered = 1
|
||||
|
||||
# Configuration option report/headings.
|
||||
# Show headings for columns on report.
|
||||
# Format of LVM command's report output headings.
|
||||
# Accepted values:
|
||||
# 0 no headings,
|
||||
# 1 headings with column abbreviations,
|
||||
# 2 headings with full column names.
|
||||
# This configuration option has an automatic default value.
|
||||
# headings = 1
|
||||
|
||||
@@ -2075,7 +2122,7 @@ activation {
|
||||
# %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
|
||||
@@ -2346,7 +2393,7 @@ activation {
|
||||
# This is displayed when the device for a PV is not known.
|
||||
# This configuration option has an automatic default value.
|
||||
# two_word_unknown_device = 0
|
||||
# }
|
||||
}
|
||||
|
||||
# Configuration section dmeventd.
|
||||
# Settings for the LVM event daemon.
|
||||
|
@@ -49,9 +49,10 @@ 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.
|
||||
# Applicable only if LVM is compiled with support for lvmlockd+sanlock.
|
||||
# This configuration option has an automatic default value.
|
||||
# host_id = 0
|
||||
}
|
||||
|
@@ -4,11 +4,9 @@
|
||||
allocation {
|
||||
vdo_use_compression=1
|
||||
vdo_use_deduplication=1
|
||||
vdo_use_metadata_hints=1
|
||||
vdo_minimum_io_size=4096
|
||||
vdo_block_map_cache_size_mb=128
|
||||
vdo_block_map_period=16380
|
||||
vdo_check_point_frequency=0
|
||||
vdo_use_sparse_index=0
|
||||
vdo_index_memory_size_mb=256
|
||||
vdo_slab_size_mb=2048
|
||||
@@ -19,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
|
||||
}
|
||||
|
280
configure.ac
280
configure.ac
@@ -20,7 +20,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)
|
||||
|
||||
################################################################################
|
||||
@@ -57,7 +57,7 @@ AS_CASE(["$host_os"],
|
||||
FSADM="no"
|
||||
LVMIMPORTVDO="no"
|
||||
BLKDEACTIVATE="no"],
|
||||
[CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"])
|
||||
[])
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for programs.
|
||||
@@ -75,6 +75,8 @@ dnl probably no longer needed in 2008, but...
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_GREP
|
||||
AC_PROG_EGREP
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_MKDIR_P
|
||||
AC_PROG_RANLIB
|
||||
@@ -185,11 +187,19 @@ AC_ARG_ENABLE(static_link,
|
||||
STATIC_LINK=$enableval, STATIC_LINK="no")
|
||||
AC_MSG_RESULT([$STATIC_LINK])
|
||||
|
||||
################################################################################
|
||||
dnl -- Disables shared linking
|
||||
AC_MSG_CHECKING([whether to use dynamic linking])
|
||||
AC_ARG_ENABLE(shared,
|
||||
AS_HELP_STRING([--disable-shared], [disable dynamic linking]),
|
||||
SHARED_LINK=$enableval, SHARED_LINK="yes")
|
||||
AC_MSG_RESULT([$SHARED_LINK])
|
||||
|
||||
################################################################################
|
||||
dnl -- Check if compiler/linker supports PIE and RELRO
|
||||
AC_TRY_CCFLAG([-pie], [HAVE_PIE], [], [])
|
||||
AC_SUBST(HAVE_PIE)
|
||||
AC_TRY_LDFLAGS([-Wl,-z,relro,-z,now], [HAVE_FULL_RELRO], [], [])
|
||||
AC_TRY_LDFLAGS([-Wl,-z,relro,-z,now,-z,pack-relative-relocs,--as-needed], [HAVE_FULL_RELRO], [], [])
|
||||
AC_SUBST(HAVE_FULL_RELRO)
|
||||
|
||||
################################################################################
|
||||
@@ -204,6 +214,14 @@ test "$prefix" = "NONE" && prefix=$ac_default_prefix
|
||||
# Let make expand exec_prefix.
|
||||
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(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])],
|
||||
[], with_udev="yes")
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup the ownership of the files
|
||||
AC_MSG_CHECKING([file owner])
|
||||
@@ -273,7 +291,7 @@ AC_DEFINE_UNQUOTED([DEFAULT_DM_ADD_NODE], $add_on, [Define default node creation
|
||||
dnl -- Default settings for lvm.conf { devices/use_devicesfile }
|
||||
AC_MSG_CHECKING([default for use_devicesfile])
|
||||
AC_ARG_WITH(default-use-devices-file,
|
||||
AS_HELP_STRING([--with-default-use-devices-file], [default for lvm.conf devices/use_devicesfile = [0]]),
|
||||
AS_HELP_STRING([--with-default-use-devices-file=ON], [default lvm.conf devices/use_devicesfile = [ON=0]]),
|
||||
DEFAULT_USE_DEVICES_FILE=$withval, DEFAULT_USE_DEVICES_FILE=0)
|
||||
AS_CASE(["$DEFAULT_USE_DEVICES_FILE"],
|
||||
[0|1], [],
|
||||
@@ -295,6 +313,17 @@ AS_CASE(["$MANGLING"],
|
||||
AC_MSG_RESULT([$MANGLING])
|
||||
AC_DEFINE_UNQUOTED([DEFAULT_DM_NAME_MANGLING], $mangling, [Define default name mangling behaviour])
|
||||
|
||||
AC_MSG_CHECKING([default for event_activation])
|
||||
AC_ARG_WITH(default-event-activation,
|
||||
AS_HELP_STRING([--with-default-event-activation=ON], [default lvm.conf global/event_activation = [ON=1]]),
|
||||
DEFAULT_EVENT_ACTIVATION=$withval, DEFAULT_EVENT_ACTIVATION=1)
|
||||
AS_CASE(["$DEFAULT_EVENT_ACTIVATION"],
|
||||
[0|1], [],
|
||||
[AC_MSG_ERROR([--with-default-event-activation parameter invalid])])
|
||||
AC_MSG_RESULT([$DEFAULT_EVENT_ACTIVATION])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_EVENT_ACTIVATION, [$DEFAULT_EVENT_ACTIVATION],
|
||||
[Default for lvm.conf event_activation.])
|
||||
|
||||
################################################################################
|
||||
dnl -- snapshots inclusion type
|
||||
AC_MSG_CHECKING([whether to include snapshots])
|
||||
@@ -410,6 +439,7 @@ AS_CASE(["$THIN"],
|
||||
])
|
||||
AS_IF([test "$THIN_CHECK_NEEDS_CHECK" = "yes" && test "$THIN_CONFIGURE_WARN" != "y"], [
|
||||
THIN_CHECK_VSN=$("$THIN_CHECK_CMD" -V 2>/dev/null)
|
||||
THIN_CHECK_VSN=${THIN_CHECK_VSN##* } # trim away all before the first space
|
||||
THIN_CHECK_VSN_MAJOR=$(echo "$THIN_CHECK_VSN" | $AWK -F '.' '{print $1}')
|
||||
THIN_CHECK_VSN_MINOR=$(echo "$THIN_CHECK_VSN" | $AWK -F '.' '{print $2}')
|
||||
|
||||
@@ -451,7 +481,7 @@ AS_CASE(["$THIN"],
|
||||
])
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([whether thin_check supports the needs-check flag])
|
||||
AC_MSG_CHECKING([whether $THIN_CHECK_CMD ($THIN_CHECK_VSN_MAJOR.$THIN_CHECK_VSN_MINOR) supports the needs-check flag])
|
||||
AC_MSG_RESULT([$THIN_CHECK_NEEDS_CHECK])
|
||||
AS_IF([test "$THIN_CHECK_NEEDS_CHECK" = "yes"], [
|
||||
AC_DEFINE([THIN_CHECK_NEEDS_CHECK], 1, [Define to 1 if the external 'thin_check' tool requires the --clear-needs-check-flag option])
|
||||
@@ -521,12 +551,13 @@ AS_CASE(["$CACHE"],
|
||||
])
|
||||
])
|
||||
AS_IF([test "$CACHE_CHECK_NEEDS_CHECK" = "yes" && test "$CACHE_CONFIGURE_WARN" != "y"], [
|
||||
$CACHE_CHECK_CMD -V 2>/dev/null >conftest.tmp
|
||||
"$CACHE_CHECK_CMD" -V 2>/dev/null >conftest.tmp
|
||||
read -r CACHE_CHECK_VSN < conftest.tmp
|
||||
IFS=.- read -r CACHE_CHECK_VSN_MAJOR CACHE_CHECK_VSN_MINOR CACHE_CHECK_VSN_PATCH LEFTOVER < conftest.tmp
|
||||
rm -f conftest.tmp
|
||||
|
||||
# Require version >= 0.5.4 for --clear-needs-check-flag
|
||||
CACHE_CHECK_VSN_MAJOR=${CACHE_CHECK_VSN_MAJOR##* }
|
||||
AS_IF([test -z "$CACHE_CHECK_VSN_MAJOR" \
|
||||
|| test -z "$CACHE_CHECK_VSN_MINOR" \
|
||||
|| test -z "$CACHE_CHECK_VSN_PATCH"], [
|
||||
@@ -574,7 +605,7 @@ AS_CASE(["$CACHE"],
|
||||
])
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([whether cache_check supports the needs-check flag])
|
||||
AC_MSG_CHECKING([whether $CACHE_CHECK_CMD ($CACHE_CHECK_VSN_MAJOR.$CACHE_CHECK_VSN_MINOR.$CACHE_CHECK_VSN_PATCH) supports the needs-check flag])
|
||||
AC_MSG_RESULT([$CACHE_CHECK_NEEDS_CHECK])
|
||||
AS_IF([test "$CACHE_CHECK_NEEDS_CHECK" = "yes"], [
|
||||
AC_DEFINE([CACHE_CHECK_NEEDS_CHECK], 1, [Define to 1 if the external 'cache_check' tool requires the --clear-needs-check-flag option])
|
||||
@@ -625,7 +656,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 vdoformating ?
|
||||
# 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],
|
||||
@@ -805,7 +836,7 @@ AS_IF([test "$GCC" = "yes" && test "$symvers" = "gnu"], [
|
||||
[Define to use GNU versioning in the shared library.])
|
||||
AS_CASE(["$host_os"],
|
||||
[linux*], [
|
||||
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
|
||||
CLDFLAGS="-Wl,--version-script,.export.sym"
|
||||
LDDEPS="$LDDEPS .export.sym"])
|
||||
])
|
||||
|
||||
@@ -819,7 +850,7 @@ AC_ARG_ENABLE(profiling,
|
||||
AC_MSG_RESULT([$PROFILING])
|
||||
|
||||
AS_IF([test "$PROFILING" = "yes"], [
|
||||
COPTIMISE_FLAG="$COPTIMISE_FLAG -fprofile-arcs -ftest-coverage"
|
||||
COPTIMISE_FLAG="$COPTIMISE_FLAG -fprofile-arcs -fprofile-update=atomic -ftest-coverage"
|
||||
AC_PATH_TOOL(LCOV, lcov)
|
||||
AC_PATH_TOOL(GENHTML, genhtml)
|
||||
AS_IF([test -z "$LCOV" || test -z "$GENHTML"], [
|
||||
@@ -902,7 +933,7 @@ AC_MSG_RESULT([$BUILD_LOCKDSANLOCK])
|
||||
|
||||
dnl -- Look for sanlock libraries
|
||||
AS_IF([test "$BUILD_LOCKDSANLOCK" = "yes"], [
|
||||
PKG_CHECK_MODULES(LIBSANLOCKCLIENT, libsanlock_client >= 3.3.0, [BUILD_LVMLOCKD="yes"])
|
||||
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.])
|
||||
])
|
||||
|
||||
@@ -921,7 +952,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"])
|
||||
])
|
||||
@@ -1012,36 +1043,24 @@ AC_DEFINE_UNQUOTED(DEFAULT_USE_LVMPOLLD, [$DEFAULT_USE_LVMPOLLD],
|
||||
|
||||
|
||||
SYSTEMD_MIN_VERSION=0
|
||||
PKG_CHECK_EXISTS(systemd >= 221, [SYSTEMD_MIN_VERSION=221])
|
||||
PKG_CHECK_EXISTS(systemd >= 234, [SYSTEMD_MIN_VERSION=234])
|
||||
|
||||
################################################################################
|
||||
dnl -- Build notifydbus
|
||||
AC_MSG_CHECKING([whether to build notifydbus])
|
||||
AC_ARG_ENABLE(notify-dbus,
|
||||
AS_HELP_STRING([--enable-notify-dbus],
|
||||
[enable LVM notification using dbus]),
|
||||
NOTIFYDBUS_SUPPORT=$enableval, NOTIFYDBUS_SUPPORT="no")
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" && test "$SYSTEMD_MIN_VERSION" -lt 221],
|
||||
[AC_MSG_ERROR([Enabling notify-dbus requires systemd >= 221])])
|
||||
AC_MSG_RESULT([$NOTIFYDBUS_SUPPORT])
|
||||
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes"],
|
||||
AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.]))
|
||||
NOTIFYDBUS_SUPPORT="no"
|
||||
SYSTEMD_JOURNAL_SUPPORT="no"
|
||||
APP_MACHINEID_SUPPORT="no"
|
||||
AS_IF([test "$with_systemd" = "yes"],
|
||||
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"]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Build with systemd journaling when the header file is present
|
||||
AS_IF([test "$SYSTEMD_MIN_VERSION" -ge 221], [SYSTEMD_JOURNAL_SUPPORT="maybe"], [SYSTEMD_JOURNAL_SUPPORT="no"])
|
||||
AC_CHECK_HEADER([systemd/sd-journal.h],
|
||||
[AS_IF([test "$SYSTEMD_JOURNAL_SUPPORT" != "no"], [SYSTEMD_JOURNAL_SUPPORT="yes"])],
|
||||
[SYSTEMD_JOURNAL_SUPPORT="no"])
|
||||
AC_MSG_CHECKING([whether to log to systemd journal])
|
||||
AS_IF([test "$SYSTEMD_JOURNAL_SUPPORT" != "no"],
|
||||
AC_CHECK_HEADER([systemd/sd-journal.h], [SYSTEMD_JOURNAL_SUPPORT="yes"], [SYSTEMD_JOURNAL_SUPPORT="no"]))
|
||||
AC_ARG_ENABLE(systemd-journal,
|
||||
AS_HELP_STRING([--disable-systemd-journal],
|
||||
[disable LVM systemd journaling]),
|
||||
AS_IF([test "$enableval" = "yes" && test "$SYSTEMD_JOURNAL_SUPPORT" = "no"],
|
||||
AC_MSG_ERROR([Enabling systemd journal requires systemd/sd-journal.h and systemd >= 221.]))
|
||||
AC_MSG_ERROR([--enable-systemd-journal requires systemd/sd-journal.h and systemd >= 221. (--with-systemd=$with_systemd)]))
|
||||
SYSTEMD_JOURNAL_SUPPORT=$enableval, [])
|
||||
AC_MSG_CHECKING([whether to log to systemd journal])
|
||||
AC_MSG_RESULT([$SYSTEMD_JOURNAL_SUPPORT])
|
||||
|
||||
AS_IF([test "$SYSTEMD_JOURNAL_SUPPORT" = "yes"],
|
||||
@@ -1049,27 +1068,20 @@ AS_IF([test "$SYSTEMD_JOURNAL_SUPPORT" = "yes"],
|
||||
|
||||
################################################################################
|
||||
dnl -- Build appmachineid when header file sd-id128.h is present
|
||||
AS_IF([test "$SYSTEMD_MIN_VERSION" -ge 234], [APP_MACHINEID_SUPPORT="maybe"], [APP_MACHINEID_SUPPORT="no"])
|
||||
AC_CHECK_HEADER([systemd/sd-id128.h],
|
||||
[AS_IF([test "$APP_MACHINEID_SUPPORT" != "no"], [APP_MACHINEID_SUPPORT="yes"])],
|
||||
[APP_MACHINEID_SUPPORT="no"])
|
||||
AC_MSG_CHECKING([whether to support systemd appmachineid])
|
||||
AS_IF([test "$APP_MACHINEID_SUPPORT" != "no"],
|
||||
[AC_CHECK_HEADER([systemd/sd-id128.h], [APP_MACHINEID_SUPPORT="yes"], [APP_MACHINEID_SUPPORT="no"])])
|
||||
AC_ARG_ENABLE(app-machineid,
|
||||
AS_HELP_STRING([--disable-app-machineid],
|
||||
[disable LVM system ID using app-specific machine-id]),
|
||||
AS_IF([test "$enableval" = "yes" && test "$APP_MACHINEID_SUPPORT" = "no"],
|
||||
AC_MSG_ERROR([Enabling app machineid requires systemd/sd-id128.h and systemd >= 234.]))
|
||||
AC_MSG_ERROR([--enable-app-machineid requires systemd/sd-id128.h and systemd >= 234. (--with-systemd=$with_systemd)]))
|
||||
APP_MACHINEID_SUPPORT=$enableval, [])
|
||||
AC_MSG_CHECKING([whether to support systemd appmachineid])
|
||||
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 -- 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])
|
||||
])
|
||||
|
||||
################################################################################
|
||||
dnl -- Support override for systemd-run path if they need to (NixOS builds)
|
||||
AC_ARG_WITH(systemd-run,
|
||||
@@ -1084,67 +1096,64 @@ AC_MSG_RESULT([$SYSTEMD_RUN_CMD])
|
||||
################################################################################
|
||||
|
||||
dnl -- Enable blkid wiping functionality
|
||||
AC_ARG_ENABLE(blkid_wiping,
|
||||
AS_HELP_STRING([--disable-blkid_wiping],
|
||||
[disable libblkid detection of signatures when wiping and use native code instead]),
|
||||
BLKID_WIPING=$enableval, BLKID_WIPING="maybe")
|
||||
|
||||
# TODO: possibly detect right version of blkid with BLKID_SUBLKS_FSINFO support
|
||||
# so lvresize can check detected flag here
|
||||
#
|
||||
DEFAULT_USE_BLKID_WIPING=0
|
||||
PKG_CHECK_EXISTS([blkid >= 2.24], [HAVE_BLKID="yes"], [HAVE_BLKID="no"])
|
||||
|
||||
AS_IF([test "$HAVE_BLKID" = "yes"], [
|
||||
PKG_CHECK_MODULES([BLKID], [blkid >= 2.24], [
|
||||
|
||||
AC_CACHE_CHECK([for blkid.h defines BLKID_SUBLKS_FSINFO.],
|
||||
[ac_cv_have_blkid_sublks_fsinfo],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <blkid/blkid.h>
|
||||
#ifndef BLKID_SUBLKS_FSINFO
|
||||
#error BLKID_SUBLKS_FSINFO is missing
|
||||
#endif])],
|
||||
[ac_cv_have_blkid_sublks_fsinfo="yes"], [ac_cv_have_blkid_sublks_fsinfo="no"])])
|
||||
|
||||
AC_IF_YES(ac_cv_have_blkid_sublks_fsinfo,
|
||||
AC_DEFINE(HAVE_BLKID_SUBLKS_FSINFO, 1,
|
||||
[Define if blkid.h has BLKID_SUBLKS_FSINFO]))
|
||||
])
|
||||
])
|
||||
AC_ARG_ENABLE(blkid_wiping,
|
||||
AS_HELP_STRING([--disable-blkid_wiping],
|
||||
[disable libblkid detection of signatures when wiping and use native code instead]),
|
||||
BLKID_WIPING=$enableval,
|
||||
[AS_IF([test "$with_blkid" = "yes"], [BLKID_WIPING="maybe"], [BLKID_WIPING="no"])])
|
||||
|
||||
AS_IF([test "$BLKID_WIPING" != "no"], [
|
||||
AS_IF([test "$HAVE_BLKID" = "yes"], [
|
||||
BLKID_WIPING="yes"
|
||||
BLKID_PC="blkid"
|
||||
DEFAULT_USE_BLKID_WIPING=1
|
||||
BLKID_STATIC_LIBS=$("$PKG_CONFIG" --static --libs blkid)
|
||||
AC_DEFINE([BLKID_WIPING_SUPPORT], 1, [Define to 1 to use libblkid detection of signatures when wiping.])
|
||||
], [
|
||||
AS_IF([test "$BLKID_WIPING" = "maybe"], [
|
||||
BLKID_WIPING=no
|
||||
], [
|
||||
AC_MSG_ERROR([bailing out... blkid library >= 2.24 is required])
|
||||
])
|
||||
])
|
||||
PKG_CHECK_MODULES([BLKID], [blkid >= 2.24], [
|
||||
AC_CACHE_CHECK([for blkid.h defines BLKID_SUBLKS_FSINFO.],
|
||||
[ac_cv_have_blkid_sublks_fsinfo],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <blkid/blkid.h>
|
||||
#ifndef BLKID_SUBLKS_FSINFO
|
||||
#error BLKID_SUBLKS_FSINFO is missing
|
||||
#endif
|
||||
])], [ac_cv_have_blkid_sublks_fsinfo="yes"], [ac_cv_have_blkid_sublks_fsinfo="no"])])
|
||||
|
||||
AC_IF_YES(ac_cv_have_blkid_sublks_fsinfo,
|
||||
AC_DEFINE(HAVE_BLKID_SUBLKS_FSINFO, 1,
|
||||
[Define if blkid.h has BLKID_SUBLKS_FSINFO]))
|
||||
|
||||
AS_IF([test "$with_blkid" = "no"], [BLKID_WIPING="error"], [
|
||||
BLKID_WIPING="yes"
|
||||
BLKID_PC="blkid"
|
||||
DEFAULT_USE_BLKID_WIPING=1
|
||||
# pkg_config --static does not really work ATM...
|
||||
BLKID_STATIC_LIBS=$("$PKG_CONFIG" --static --libs blkid)
|
||||
AC_DEFINE([BLKID_WIPING_SUPPORT], 1, [Define to 1 to use libblkid detection of signatures when wiping.])
|
||||
])
|
||||
], [AS_IF([test "$BLKID_WIPING" = "yes"], [BLKID_WIPING="error"], [BLKID_WIPING="no"])])
|
||||
])
|
||||
|
||||
AS_IF([test "$BLKID_WIPING" = "error"],
|
||||
[AC_MSG_ERROR([--enable-blkid_wiping requires blkid library >= 2.24. (--with-blkid=$with_blkid)])])
|
||||
|
||||
AC_MSG_CHECKING([whether to enable libblkid detection of signatures when wiping])
|
||||
AC_MSG_RESULT([$BLKID_WIPING])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_USE_BLKID_WIPING, [$DEFAULT_USE_BLKID_WIPING],
|
||||
[Use blkid wiping by default.])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable udev synchronisation
|
||||
AC_MSG_CHECKING([whether to enable synchronisation with udev processing])
|
||||
dnl -- Enable udev synchronization
|
||||
AC_MSG_CHECKING([whether to enable synchronization with udev processing])
|
||||
AC_ARG_ENABLE(udev_sync,
|
||||
AS_HELP_STRING([--enable-udev_sync],
|
||||
[enable synchronisation with udev processing]),
|
||||
[enable synchronization with udev processing]),
|
||||
UDEV_SYNC=$enableval, UDEV_SYNC="no")
|
||||
AC_MSG_RESULT([$UDEV_SYNC])
|
||||
AS_IF([test "$UDEV_SYNC" = "yes" && test "$with_udev" = "no"],
|
||||
[AC_MSG_ERROR([--enable-udev_sync requires udev >= 143. (--with-udev=$with_udev)])])
|
||||
|
||||
AS_IF([test "$UDEV_SYNC" = "yes"], [
|
||||
PKG_CHECK_MODULES(UDEV, libudev >= 143, [UDEV_PC="libudev"])
|
||||
UDEV_STATIC_LIBS=$("$PKG_CONFIG" --static --libs libudev)
|
||||
AC_DEFINE([UDEV_SYNC_SUPPORT], 1, [Define to 1 to enable synchronisation with udev processing.])
|
||||
AC_DEFINE([UDEV_SYNC_SUPPORT], 1, [Define to 1 to enable synchronization with udev processing.])
|
||||
|
||||
AC_CHECK_LIB(udev, udev_device_get_is_initialized, AC_DEFINE([HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED], 1,
|
||||
[Define to 1 if udev_device_get_is_initialized is available.]))
|
||||
@@ -1152,10 +1161,10 @@ AS_IF([test "$UDEV_SYNC" = "yes"], [
|
||||
])
|
||||
|
||||
dnl -- Enable udev rules
|
||||
AC_MSG_CHECKING([whether to enable installation of udev rules required for synchronisation])
|
||||
AC_MSG_CHECKING([whether to enable installation of udev rules required for synchronization])
|
||||
AC_ARG_ENABLE(udev_rules,
|
||||
AS_HELP_STRING([--enable-udev_rules],
|
||||
[install rule files needed for udev synchronisation]),
|
||||
[install rule files needed for udev synchronization]),
|
||||
UDEV_RULES=$enableval, UDEV_RULES=$UDEV_SYNC)
|
||||
AC_MSG_RESULT([$UDEV_RULES])
|
||||
|
||||
@@ -1210,16 +1219,6 @@ AS_IF([test "$ODIRECT" = "yes"], [
|
||||
AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
|
||||
])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable cmdlib
|
||||
AC_MSG_CHECKING([whether to compile liblvm2cmd.so])
|
||||
AC_ARG_ENABLE(cmdlib,
|
||||
AS_HELP_STRING([--enable-cmdlib], [build shared command library]),
|
||||
CMDLIB=$enableval, CMDLIB="no")
|
||||
AC_MSG_RESULT([$CMDLIB])
|
||||
AC_SUBST([LVM2CMD_LIB])
|
||||
AS_IF([test "$CMDLIB" = "yes"], [LVM2CMD_LIB="-llvm2cmd"], [LVM2CMD_LIB=])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable D-Bus service
|
||||
AC_MSG_CHECKING([whether to include Python D-Bus support])
|
||||
@@ -1227,8 +1226,29 @@ AC_ARG_ENABLE(dbus-service,
|
||||
AS_HELP_STRING([--enable-dbus-service], [install D-Bus support]),
|
||||
BUILD_LVMDBUSD=$enableval, BUILD_LVMDBUSD="no")
|
||||
AC_MSG_RESULT([$BUILD_LVMDBUSD])
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "no" && test "$BUILD_LVMDBUSD" = "yes"],
|
||||
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications.])])
|
||||
|
||||
################################################################################
|
||||
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 "$NOTIFYDBUS_SUPPORT" = "maybe"],
|
||||
[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_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])
|
||||
])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable Python dbus library
|
||||
@@ -1302,15 +1322,28 @@ AC_MSG_RESULT([$BUILD_DMEVENTD])
|
||||
|
||||
dnl -- dmeventd currently requires internal mirror support
|
||||
AS_IF([test "$BUILD_DMEVENTD" = "yes"], [
|
||||
AS_IF([test "$MIRRORS" != "internal"], [
|
||||
AC_MSG_ERROR([--enable-dmeventd currently requires --with-mirrors=internal])
|
||||
])
|
||||
AS_IF([test "$CMDLIB" = "no"], [
|
||||
AC_MSG_ERROR([--enable-dmeventd requires --enable-cmdlib to be used as well])
|
||||
])
|
||||
AS_IF([test "$MIRRORS" != "internal"],
|
||||
[AC_MSG_ERROR([--enable-dmeventd currently requires --with-mirrors=internal])])
|
||||
AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable cmdlib
|
||||
AC_ARG_ENABLE(cmdlib, [AS_HELP_STRING([--enable-cmdlib], [build shared command library])],
|
||||
CMDLIB=$enableval, CMDLIB="maybe")
|
||||
|
||||
AS_IF([test "$BUILD_DMEVENTD" = "yes"],
|
||||
[AS_IF([test "$CMDLIB" = "no"],
|
||||
[AC_MSG_ERROR([--enable-dmeventd requires --enable-cmdlib to be used as well])],
|
||||
[CMDLIB="yes"])])
|
||||
|
||||
AS_IF([test "$CMDLIB" != "yes"], [CMDLIB="no" LVM2CMD_LIB=], [LVM2CMD_LIB="-llvm2cmd"])
|
||||
|
||||
AC_MSG_CHECKING([whether to compile liblvm2cmd.so])
|
||||
AC_MSG_RESULT([$CMDLIB])
|
||||
|
||||
AS_IF([test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"],
|
||||
[AC_MSG_ERROR([--enable-cmdlib requires dynamic linking.])])
|
||||
|
||||
AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
|
||||
])
|
||||
|
||||
################################################################################
|
||||
dnl -- Check dmfilemapd
|
||||
@@ -1322,8 +1355,7 @@ AC_MSG_RESULT([$BUILD_DMFILEMAPD])
|
||||
|
||||
dnl -- dmfilemapd requires FIEMAP
|
||||
AS_IF([test "$BUILD_DMFILEMAPD" = "yes"],
|
||||
[AC_CHECK_HEADER([linux/fiemap.h], [],
|
||||
,[AC_MSG_ERROR(--enable-dmfilemapd requires fiemap.h)])
|
||||
[AC_CHECK_HEADER([linux/fiemap.h], [], [AC_MSG_ERROR(--enable-dmfilemapd requires fiemap.h)])
|
||||
AC_DEFINE([DMFILEMAPD], 1, [Define to 1 to enable the device-mapper filemap daemon.])])
|
||||
|
||||
################################################################################
|
||||
@@ -1596,6 +1628,17 @@ AC_ARG_WITH(tmpfilesdir,
|
||||
AS_HELP_STRING([--with-tmpfilesdir=DIR],
|
||||
[install configuration files for management of volatile files and directories in DIR [PREFIX/lib/tmpfiles.d]]),
|
||||
tmpfilesdir=$withval, tmpfilesdir='${prefix}/lib/tmpfiles.d')
|
||||
|
||||
################################################################################
|
||||
dnl - Where to look for modules.builtin file for a kernel - most typically in /lib/modules/
|
||||
AC_MSG_CHECKING([for kernel modules directory])
|
||||
AC_ARG_WITH(modulesdir,
|
||||
AS_HELP_STRING([--with-modulesdir=DIR],
|
||||
[Dir to look for file `uname -r`/modules.builtin [/lib/modules]]),
|
||||
[modulesdir=$withval], [modulesdir="/lib/modules"])
|
||||
AC_DEFINE_UNQUOTED(MODULES_PATH, ["$modulesdir"], [The path to kernel modules.])
|
||||
AC_MSG_RESULT([$modulesdir])
|
||||
|
||||
################################################################################
|
||||
dnl -- Ensure additional headers required
|
||||
AS_IF([test "$READLINE" = "yes"], [
|
||||
@@ -1686,12 +1729,19 @@ AC_ARG_WITH(dmeventd-path,
|
||||
[dmeventd path [EPREFIX/sbin/dmeventd]]),
|
||||
DMEVENTD_PATH=$withval,
|
||||
DMEVENTD_PATH="$SBINDIR/dmeventd")
|
||||
AC_ARG_WITH(dmeventd-exit-on-path,
|
||||
AS_HELP_STRING([--with-dmeventd-exit-on-path=PATH],
|
||||
[Default path to exit-on file in dmeventd [/run/nologin]]),
|
||||
DEFAULT_DMEVENTD_EXIT_ON_PATH=$withval,
|
||||
DEFAULT_DMEVENTD_EXIT_ON_PATH="/run/nologin")
|
||||
|
||||
AS_IF([test "$BUILD_DMEVENTD" = "yes"], [
|
||||
AC_DEFINE_UNQUOTED(DMEVENTD_PIDFILE, ["$DMEVENTD_PIDFILE"],
|
||||
[Path to dmeventd pidfile.])
|
||||
AC_DEFINE_UNQUOTED(DMEVENTD_PATH, ["$DMEVENTD_PATH"],
|
||||
[Path to dmeventd binary.])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_DMEVENTD_EXIT_ON_PATH, ["$DEFAULT_DMEVENTD_EXIT_ON_PATH"],
|
||||
[Path to exit-on dmeventd file.])
|
||||
])
|
||||
|
||||
################################################################################
|
||||
@@ -1746,6 +1796,9 @@ AC_MSG_RESULT([$DEFAULT_LOCK_DIR])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_LOCK_DIR, ["$DEFAULT_LOCK_DIR"],
|
||||
[Name of default locking directory.])
|
||||
|
||||
# No --with configure setting, but store in the main configure.h
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_PROC_DIR, ["/proc"], [Path to /proc.])
|
||||
|
||||
################################################################################
|
||||
dnl -- which kernel interface to use (ioctl only)
|
||||
AC_MSG_CHECKING([for kernel interface choice])
|
||||
@@ -1825,9 +1878,12 @@ AC_SUBST(DEFAULT_ARCHIVE_SUBDIR)
|
||||
AC_SUBST(DEFAULT_BACKUP_SUBDIR)
|
||||
AC_SUBST(DEFAULT_CACHE_SUBDIR)
|
||||
AC_SUBST(DEFAULT_DM_RUN_DIR)
|
||||
AC_SUBST(DEFAULT_DMEVENTD_EXIT_ON_PATH)
|
||||
AC_SUBST(DEFAULT_EVENT_ACTIVATION)
|
||||
AC_SUBST(DEFAULT_LOCK_DIR)
|
||||
AC_SUBST(DEFAULT_MIRROR_SEGTYPE)
|
||||
AC_SUBST(DEFAULT_PID_DIR)
|
||||
AC_SUBST(DEFAULT_PROC_DIR)
|
||||
AC_SUBST(DEFAULT_PROFILE_SUBDIR)
|
||||
AC_SUBST(DEFAULT_RAID10_SEGTYPE)
|
||||
AC_SUBST(DEFAULT_RUN_DIR)
|
||||
@@ -1853,6 +1909,7 @@ AC_SUBST(LDDEPS)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LIB_SUFFIX)
|
||||
AC_SUBST(localedir)
|
||||
AC_SUBST(LVM2CMD_LIB)
|
||||
AC_SUBST(LVMIMPORTVDO)
|
||||
AC_SUBST(LVMIMPORTVDO_PATH)
|
||||
AC_SUBST(LVMLOCKD_PIDFILE)
|
||||
@@ -1884,6 +1941,7 @@ AC_SUBST(SBINDIR)
|
||||
AC_SUBST(SELINUX_LIBS)
|
||||
AC_SUBST(SELINUX_PC)
|
||||
AC_SUBST(SELINUX_STATIC_LIBS)
|
||||
AC_SUBST(SHARED_LINK)
|
||||
AC_SUBST(SILENT_RULES)
|
||||
AC_SUBST(SNAPSHOTS)
|
||||
AC_SUBST(STATICDIR)
|
||||
@@ -1917,6 +1975,7 @@ AC_SUBST(kerneldir)
|
||||
AC_SUBST(kernelvsn)
|
||||
AC_SUBST(libexecdir)
|
||||
AC_SUBST(missingkernel)
|
||||
AC_SUBST(modulesdir)
|
||||
AC_SUBST(systemdsystemunitdir)
|
||||
AC_SUBST(systemdutildir)
|
||||
AC_SUBST(tmpdir)
|
||||
@@ -2013,3 +2072,6 @@ AS_IF([test -n "$LVM_NEEDS_LIBAIO_WARN"],
|
||||
|
||||
AS_IF([test "$ODIRECT" != "yes"],
|
||||
[AC_MSG_WARN([O_DIRECT disabled: low-memory pvmove may lock up])])
|
||||
|
||||
AS_IF([test "$BUILD_LVMDBUSD" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
|
||||
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications!])])
|
||||
|
@@ -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'):
|
||||
@@ -70,7 +70,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
|
||||
|
@@ -32,12 +32,12 @@ CFLAGS += $(CPG_CFLAGS) $(EXTRA_EXEC_CFLAGS)
|
||||
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
|
||||
cmirrord: $(OBJECTS)
|
||||
@echo " [CC] $@"
|
||||
$(SHOW) " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
||||
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
|
||||
|
||||
install_cluster: $(TARGETS)
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_PROGRAM) -D $< $(usrsbindir)/$(<F)
|
||||
|
||||
install: install_cluster
|
||||
|
@@ -43,14 +43,14 @@ static void usage (FILE *dest)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int foreground_mode = 0;
|
||||
struct option longopts[] = {
|
||||
static const struct option _long_options[] = {
|
||||
{ "foreground", no_argument, NULL, 'f' },
|
||||
{ "help" , no_argument, NULL, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt_long (argc, argv, "fh", longopts, NULL)) != -1) {
|
||||
while ((opt = getopt_long (argc, argv, "fh", _long_options, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
foreground_mode = 1;
|
||||
|
@@ -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) {
|
||||
@@ -1091,6 +1091,7 @@ static void cpg_message_callback(cpg_handle_t handle, const struct cpg_name *gna
|
||||
(rq->u_rq.request_type != DM_ULOG_RESUME) &&
|
||||
(rq->u_rq.request_type != DM_ULOG_CLEAR_REGION) &&
|
||||
(rq->u_rq.request_type != DM_ULOG_CHECKPOINT_READY)) {
|
||||
/* coverity[suspicious_sizeof] allocation is using varargs data @end */
|
||||
tmp_rq = malloc(DM_ULOG_REQUEST_SIZE);
|
||||
if (!tmp_rq) {
|
||||
/*
|
||||
@@ -1340,6 +1341,7 @@ static void cpg_join_callback(struct clog_cpg *match,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* coverity[suspicious_sizeof] allocation is using varargs data @end */
|
||||
rq = malloc(DM_ULOG_REQUEST_SIZE);
|
||||
if (!rq) {
|
||||
LOG_ERROR("cpg_config_callback: "
|
||||
@@ -1632,7 +1634,7 @@ int create_cluster_cpg(char *uuid, uint64_t luid)
|
||||
|
||||
size = ((strlen(uuid) + 1) > CPG_MAX_NAME_LENGTH) ?
|
||||
CPG_MAX_NAME_LENGTH : (strlen(uuid) + 1);
|
||||
(void) dm_strncpy(new->name.value, uuid, size);
|
||||
dm_strncpy(new->name.value, uuid, size);
|
||||
new->name.length = (uint32_t)size;
|
||||
new->luid = luid;
|
||||
|
||||
|
@@ -67,7 +67,7 @@ struct log_c {
|
||||
uint32_t recoverer;
|
||||
uint64_t recovering_region; /* -1 means not recovering */
|
||||
uint64_t skip_bit_warning; /* used to warn if region skipped */
|
||||
int sync_search;
|
||||
unsigned sync_search;
|
||||
|
||||
int resume_override;
|
||||
|
||||
@@ -220,7 +220,7 @@ static int rw_log(struct log_c *lc, int do_write)
|
||||
if (r < 0)
|
||||
LOG_ERROR("[%s] rw_log: read failure: %s",
|
||||
SHORT_UUID(lc->uuid), strerror(errno));
|
||||
if (r != lc->disk_size)
|
||||
if ((unsigned) r != lc->disk_size)
|
||||
return -EIO; /* Failed disk read */
|
||||
return 0;
|
||||
}
|
||||
@@ -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)) {
|
||||
@@ -292,13 +292,13 @@ static int write_log(struct log_c *lc)
|
||||
}
|
||||
|
||||
/* FIXME Rewrite this function taking advantage of the udev changes (where in use) to improve its efficiency! */
|
||||
static int find_disk_path(char *major_minor_str, char *path_rtn, int *unlink_path __attribute__((unused)))
|
||||
static int find_disk_path(char *major_minor_str, char *path_rtn, size_t sz, int *unlink_path __attribute__((unused)))
|
||||
{
|
||||
int r;
|
||||
DIR *dp;
|
||||
struct dirent *dep;
|
||||
struct stat statbuf;
|
||||
int major, minor;
|
||||
unsigned major, minor;
|
||||
|
||||
if (!strstr(major_minor_str, ":")) {
|
||||
r = stat(major_minor_str, &statbuf);
|
||||
@@ -306,7 +306,7 @@ static int find_disk_path(char *major_minor_str, char *path_rtn, int *unlink_pat
|
||||
return -errno;
|
||||
if (!S_ISBLK(statbuf.st_mode))
|
||||
return -EINVAL;
|
||||
sprintf(path_rtn, "%s", major_minor_str);
|
||||
dm_strncpy(path_rtn, major_minor_str, sz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ static int find_disk_path(char *major_minor_str, char *path_rtn, int *unlink_pat
|
||||
* wanted.
|
||||
*/
|
||||
|
||||
sprintf(path_rtn, "/dev/mapper/%s", dep->d_name);
|
||||
snprintf(path_rtn, sz, "/dev/mapper/%s", dep->d_name);
|
||||
if (stat(path_rtn, &statbuf) < 0) {
|
||||
LOG_DBG("Unable to stat %s", path_rtn);
|
||||
continue;
|
||||
@@ -394,7 +394,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = find_disk_path(argv[0], disk_path, &unlink_path);
|
||||
r = find_disk_path(argv[0], disk_path, sizeof(disk_path), &unlink_path);
|
||||
if (r) {
|
||||
LOG_ERROR("Unable to find path to device %s", argv[0]);
|
||||
goto fail;
|
||||
@@ -452,7 +452,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
|
||||
lc->skip_bit_warning = region_count;
|
||||
lc->disk_fd = -1;
|
||||
lc->log_dev_failed = 0;
|
||||
if (!dm_strncpy(lc->uuid, uuid, DM_UUID_LEN)) {
|
||||
if (!_dm_strncpy(lc->uuid, uuid, DM_UUID_LEN)) {
|
||||
LOG_ERROR("Cannot use too long UUID %s.", uuid);
|
||||
r = -EINVAL;
|
||||
goto fail;
|
||||
@@ -927,7 +927,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 +1018,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.
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#define _LVM_CLOG_FUNCTIONS_H
|
||||
|
||||
#include "libdm/libdevmapper.h"
|
||||
#include "libdm/dm-tools/util.h"
|
||||
#include "libdm/misc/dm-log-userspace.h"
|
||||
#include "cluster.h"
|
||||
|
||||
|
@@ -266,7 +266,7 @@ static int do_local_work(void *data __attribute__((unused)))
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
break;
|
||||
}
|
||||
/* ELSE, fall through */
|
||||
/* ELSE */ /* fall through */
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_FLUSH:
|
||||
case DM_ULOG_MARK_REGION:
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
#include "logging.h"
|
||||
|
||||
const char *__rq_types_off_by_one[] = {
|
||||
const char * const __rq_types_off_by_one[] = {
|
||||
"DM_ULOG_CTR",
|
||||
"DM_ULOG_DTR",
|
||||
"DM_ULOG_PRESUSPEND",
|
||||
|
@@ -20,7 +20,7 @@
|
||||
/* SHORT_UUID - print last 8 chars of a string */
|
||||
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
|
||||
|
||||
extern const char *__rq_types_off_by_one[];
|
||||
extern const char * const __rq_types_off_by_one[];
|
||||
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
|
||||
|
||||
extern int log_tabbing;
|
||||
|
@@ -70,12 +70,12 @@ plugins.device-mapper: $(LIB_SHARED)
|
||||
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
|
||||
|
||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||
@echo " [CC] $@"
|
||||
$(SHOW) " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
|
||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS)
|
||||
|
||||
dmeventd.static: $(LIB_STATIC) dmeventd.o
|
||||
@echo " [CC] $@"
|
||||
$(SHOW) " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(STATIC_LDFLAGS) -static dmeventd.o \
|
||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
|
||||
|
||||
@@ -84,27 +84,27 @@ ifeq ("@PKGCONFIG@", "yes")
|
||||
endif
|
||||
|
||||
install_include: $(srcdir)/libdevmapper-event.h
|
||||
@echo " [INSTALL] $(<F)"
|
||||
$(SHOW) " [INSTALL] $(<F)"
|
||||
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
|
||||
|
||||
install_pkgconfig: libdevmapper-event.pc
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
|
||||
|
||||
install_lib_dynamic: install_lib_shared
|
||||
|
||||
install_lib_static: $(LIB_STATIC)
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
|
||||
|
||||
install_lib: $(INSTALL_LIB_TARGETS)
|
||||
|
||||
install_dmeventd_dynamic: dmeventd
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
||||
install_dmeventd_static: dmeventd.static
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
|
||||
|
||||
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
|
||||
|
@@ -23,12 +23,12 @@
|
||||
#include "libdm/misc/dm-logging.h"
|
||||
#include "base/memory/zalloc.h"
|
||||
|
||||
#include "libdaemon/server/daemon-stray.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <signal.h>
|
||||
#include <arpa/inet.h> /* for htonl, ntohl */
|
||||
@@ -92,12 +92,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;
|
||||
|
||||
static int _debug_level = 0;
|
||||
static int _use_syslog = 1;
|
||||
static int _systemd_activation = 0;
|
||||
static int _foreground = 0;
|
||||
static int _restart = 0;
|
||||
static time_t _idle_since = 0;
|
||||
static const char *_exit_on = DEFAULT_DMEVENTD_EXIT_ON_PATH;
|
||||
static char **_initial_registrations = 0;
|
||||
|
||||
/* FIXME Make configurable at runtime */
|
||||
@@ -202,9 +200,9 @@ struct message_data {
|
||||
char *dso_name; /* Name of DSO. */
|
||||
char *device_uuid; /* Mapped device path. */
|
||||
char *events_str; /* Events string as fetched from message. */
|
||||
enum dm_event_mask events_field; /* Events bitfield. */
|
||||
char *timeout_str;
|
||||
unsigned events_field; /* Events bitfield. */
|
||||
uint32_t timeout_secs;
|
||||
char *timeout_str;
|
||||
struct dm_event_daemon_message *msg; /* Pointer to message buffer. */
|
||||
};
|
||||
|
||||
@@ -238,7 +236,7 @@ struct thread_status {
|
||||
int status; /* See DM_THREAD_{REGISTERING,RUNNING,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 */
|
||||
time_t next_time;
|
||||
@@ -429,7 +427,7 @@ 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 */
|
||||
/* runs ioctl and may register lvm2 plugin */
|
||||
thread->processing = 1;
|
||||
thread->status = DM_THREAD_REGISTERING;
|
||||
|
||||
@@ -522,7 +520,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))) {
|
||||
@@ -723,12 +721,18 @@ static int _get_status(struct message_data *message_data)
|
||||
static int _get_parameters(struct message_data *message_data) {
|
||||
struct dm_event_daemon_message *msg = message_data->msg;
|
||||
int size;
|
||||
char idle_buf[32] = "";
|
||||
|
||||
if (_idle_since)
|
||||
(void)dm_snprintf(idle_buf, sizeof(idle_buf), " idle=%lu", (long unsigned) (time(NULL) - _idle_since));
|
||||
|
||||
free(msg->data);
|
||||
if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s",
|
||||
if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s exit_on=\"%s\"%s",
|
||||
message_data->id, getpid(),
|
||||
_foreground ? "no" : "yes",
|
||||
_systemd_activation ? "systemd" : "direct")) < 0) {
|
||||
_systemd_activation ? "systemd" : "direct",
|
||||
_exit_on,
|
||||
idle_buf)) < 0) {
|
||||
stack;
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -987,6 +991,7 @@ static void _monitor_unregister(void *arg)
|
||||
DEBUGLOG("Unregistering monitor for %s.", thread->device.name);
|
||||
_unregister_for_timeout(thread);
|
||||
|
||||
/* coverity[missing_lock] no missing lock here */
|
||||
if ((thread->status != DM_THREAD_REGISTERING) &&
|
||||
!_do_unregister_device(thread))
|
||||
log_error("%s: %s unregister failed.", __func__,
|
||||
@@ -997,6 +1002,8 @@ static void _monitor_unregister(void *arg)
|
||||
_lock_mutex();
|
||||
thread->status = DM_THREAD_DONE; /* Last access to thread memory! */
|
||||
_unlock_mutex();
|
||||
if (_exit_now) /* Exit is already in-progress, wake-up sleeping select() */
|
||||
kill(getpid(), SIGINT);
|
||||
}
|
||||
|
||||
/* Device monitoring thread. */
|
||||
@@ -1043,9 +1050,9 @@ static void *_monitor_thread(void *arg)
|
||||
_unlock_mutex();
|
||||
|
||||
_do_process_event(thread);
|
||||
thread->current_events = 0; /* Current events processed */
|
||||
|
||||
_lock_mutex();
|
||||
thread->current_events = 0; /* Current events processed */
|
||||
thread->processing = 0;
|
||||
|
||||
/*
|
||||
@@ -1161,6 +1168,36 @@ static int _unregister_for_event(struct message_data *message_data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _unregister_all_threads(void)
|
||||
{
|
||||
struct thread_status *thread, *tmp;
|
||||
|
||||
_lock_mutex();
|
||||
|
||||
dm_list_iterate_items_safe(thread, tmp, &_thread_registry)
|
||||
_update_events(thread, 0);
|
||||
|
||||
_unlock_mutex();
|
||||
}
|
||||
|
||||
static void _wait_for_new_pid(void)
|
||||
{
|
||||
unsigned long st_ino = 0;
|
||||
struct stat st;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 400000; ++i) {
|
||||
if (lstat(DMEVENTD_PIDFILE, &st) == 0) {
|
||||
if (!st_ino)
|
||||
st_ino = st.st_ino;
|
||||
else if (st_ino != st.st_ino)
|
||||
break; /* different pidfile */
|
||||
} else if (errno == ENOENT)
|
||||
break; /* pidfile is removed */
|
||||
usleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Register for an event.
|
||||
*
|
||||
@@ -1404,7 +1441,8 @@ static int _open_fifo(const char *path)
|
||||
} else if (!S_ISFIFO(st.st_mode) || st.st_uid ||
|
||||
(st.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
|
||||
log_warn("WARNING: %s has wrong attributes: Replacing.", path);
|
||||
if (unlink(path)) {
|
||||
/* coverity[toctou] don't care, path is going to be recreated */
|
||||
if (unlink(path) && (errno != ENOENT)) {
|
||||
log_sys_error("unlink", path);
|
||||
return -1;
|
||||
}
|
||||
@@ -1412,6 +1450,7 @@ static int _open_fifo(const char *path)
|
||||
|
||||
/* Create fifo. */
|
||||
(void) dm_prepare_selinux_context(path, S_IFIFO);
|
||||
/* coverity[toctou] revalidating things again */
|
||||
if ((mkfifo(path, 0600) == -1) && errno != EEXIST) {
|
||||
log_sys_error("mkfifo", path);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
@@ -1640,7 +1679,7 @@ static int _do_process_request(struct dm_event_daemon_message *msg)
|
||||
} else
|
||||
ret = _handle_request(msg, &message_data);
|
||||
|
||||
msg->cmd = ret;
|
||||
msg->cmd = (uint32_t)ret;
|
||||
if (!msg->data)
|
||||
msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
|
||||
|
||||
@@ -1677,9 +1716,9 @@ static void _process_request(struct dm_event_fifos *fifos)
|
||||
free(msg.data);
|
||||
|
||||
if (cmd == DM_EVENT_CMD_DIE) {
|
||||
if (unlink(DMEVENTD_PIDFILE))
|
||||
log_sys_error("unlink", DMEVENTD_PIDFILE);
|
||||
_exit(0);
|
||||
_unregister_all_threads();
|
||||
_exit_now = DM_SCHEDULED_EXIT;
|
||||
log_info("dmeventd exiting for restart.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1726,7 +1765,7 @@ static void _cleanup_unused_threads(void)
|
||||
DEBUGLOG("Destroying Thr %x.", (int)thread->thread);
|
||||
|
||||
if (pthread_join(thread->thread, NULL))
|
||||
log_sys_error("pthread_join", "");
|
||||
log_sys_debug("pthread_join", "");
|
||||
|
||||
_free_thread_status(thread);
|
||||
_lock_mutex();
|
||||
@@ -1757,7 +1796,7 @@ static void _init_thread_signals(void)
|
||||
sigdelset(&my_sigset, SIGQUIT);
|
||||
|
||||
if (pthread_sigmask(SIG_BLOCK, &my_sigset, NULL))
|
||||
log_sys_error("pthread_sigmask", "SIG_BLOCK");
|
||||
log_sys_debug("pthread_sigmask", "SIG_BLOCK");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1769,7 +1808,8 @@ static void _init_thread_signals(void)
|
||||
*/
|
||||
static void _exit_handler(int sig __attribute__((unused)))
|
||||
{
|
||||
_exit_now = DM_SIGNALED_EXIT;
|
||||
if (!_exit_now)
|
||||
_exit_now = DM_SIGNALED_EXIT;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -1785,7 +1825,7 @@ static int _set_oom_adj(const char *oom_adj_path, int val)
|
||||
fprintf(fp, "%i", val);
|
||||
|
||||
if (dm_fclose(fp))
|
||||
log_sys_error("fclose", oom_adj_path);
|
||||
log_sys_debug("fclose", oom_adj_path);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1799,11 +1839,11 @@ static int _protect_against_oom_killer(void)
|
||||
|
||||
if (stat(OOM_ADJ_FILE, &st) == -1) {
|
||||
if (errno != ENOENT)
|
||||
log_sys_error("stat", OOM_ADJ_FILE);
|
||||
log_sys_debug("stat", OOM_ADJ_FILE);
|
||||
|
||||
/* Try old oom_adj interface as a fallback */
|
||||
if (stat(OOM_ADJ_FILE_OLD, &st) == -1) {
|
||||
log_sys_error("stat", OOM_ADJ_FILE_OLD);
|
||||
log_sys_debug("stat", OOM_ADJ_FILE_OLD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1891,26 +1931,30 @@ out:
|
||||
|
||||
static void _remove_files_on_exit(void)
|
||||
{
|
||||
if (unlink(DMEVENTD_PIDFILE))
|
||||
log_sys_error("unlink", DMEVENTD_PIDFILE);
|
||||
if (unlink(DMEVENTD_PIDFILE) && (errno != ENOENT))
|
||||
log_sys_debug("unlink", DMEVENTD_PIDFILE);
|
||||
|
||||
if (!_systemd_activation) {
|
||||
if (unlink(DM_EVENT_FIFO_CLIENT))
|
||||
log_sys_error("unlink", DM_EVENT_FIFO_CLIENT);
|
||||
if (unlink(DM_EVENT_FIFO_CLIENT) && (errno != ENOENT))
|
||||
log_sys_debug("unlink", DM_EVENT_FIFO_CLIENT);
|
||||
|
||||
if (unlink(DM_EVENT_FIFO_SERVER))
|
||||
log_sys_error("unlink", DM_EVENT_FIFO_SERVER);
|
||||
if (unlink(DM_EVENT_FIFO_SERVER) && (errno != ENOENT))
|
||||
log_sys_debug("unlink", DM_EVENT_FIFO_SERVER);
|
||||
}
|
||||
}
|
||||
|
||||
static void _daemonize(void)
|
||||
{
|
||||
int child_status;
|
||||
int fd;
|
||||
int child_status, null_fd;
|
||||
pid_t pid;
|
||||
struct rlimit rlim;
|
||||
struct timeval tval;
|
||||
sigset_t my_sigset;
|
||||
struct custom_fds custom_fds = {
|
||||
/* Do not close fds preloaded by systemd! */
|
||||
.out = (_systemd_activation) ? SD_FD_FIFO_SERVER : -1,
|
||||
.err = -1,
|
||||
.report = (_systemd_activation) ? SD_FD_FIFO_CLIENT : -1,
|
||||
};
|
||||
|
||||
sigemptyset(&my_sigset);
|
||||
if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
|
||||
@@ -1954,33 +1998,28 @@ static void _daemonize(void)
|
||||
if (chdir("/"))
|
||||
exit(EXIT_CHDIR_FAILURE);
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
|
||||
fd = 256; /* just have to guess */
|
||||
else
|
||||
fd = rlim.rlim_cur;
|
||||
daemon_close_stray_fds("dmeventd", 0, -1, &custom_fds);
|
||||
|
||||
for (--fd; fd >= 0; fd--) {
|
||||
#ifdef __linux__
|
||||
/* Do not close fds preloaded by systemd! */
|
||||
if (_systemd_activation &&
|
||||
(fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT))
|
||||
continue;
|
||||
#endif
|
||||
(void) close(fd);
|
||||
}
|
||||
|
||||
if ((open("/dev/null", O_RDONLY) < 0) ||
|
||||
(open("/dev/null", O_WRONLY) < 0) ||
|
||||
(open("/dev/null", O_WRONLY) < 0))
|
||||
if ((null_fd = open("/dev/null", O_RDWR)) < 0)
|
||||
exit(EXIT_DESC_OPEN_FAILURE);
|
||||
|
||||
if ((dup2(null_fd, STDIN_FILENO) == -1) ||
|
||||
(dup2(null_fd, STDOUT_FILENO) == -1) ||
|
||||
(dup2(null_fd, STDERR_FILENO) == -1))
|
||||
exit(EXIT_DESC_OPEN_FAILURE);
|
||||
|
||||
if ((null_fd > STDERR_FILENO) && close(null_fd))
|
||||
exit(EXIT_DESC_CLOSE_FAILURE);
|
||||
|
||||
setsid();
|
||||
|
||||
/* coverity[leaked_handle] 'null_fd' handle is not leaking */
|
||||
}
|
||||
|
||||
static int _reinstate_registrations(struct dm_event_fifos *fifos)
|
||||
{
|
||||
static const char _failed_parsing_msg[] = "Failed to parse existing event registration.\n";
|
||||
static const char *_delim = " ";
|
||||
static const char _delim[] = " ";
|
||||
struct dm_event_daemon_message msg = { 0 };
|
||||
char *endp, *dso_name, *dev_name, *mask, *timeout;
|
||||
unsigned long mask_value, timeout_value;
|
||||
@@ -2030,28 +2069,94 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _restart_dmeventd(void)
|
||||
static int _info_dmeventd(const char *name, struct dm_event_fifos *fifos)
|
||||
{
|
||||
struct dm_event_daemon_message msg = { 0 };
|
||||
int i, count = 0;
|
||||
char *line;
|
||||
int version;
|
||||
int ret = 0;
|
||||
|
||||
if (!dm_daemon_is_running(DMEVENTD_PIDFILE)) {
|
||||
fprintf(stderr, "No running dmeventd instance for status query.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the list of registrations from the running daemon. */
|
||||
if (!init_fifos(fifos)) {
|
||||
fprintf(stderr, "Could not initiate communication with existing dmeventd.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_event_get_version(fifos, &version)) {
|
||||
fprintf(stderr, "Could not communicate with existing dmeventd.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (version < 1) {
|
||||
fprintf(stderr, "The running dmeventd instance is too old.\n"
|
||||
"Protocol version %d (required: 1). Action cancelled.\n", version);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0)) {
|
||||
fprintf(stderr, "Failed to acquire status from existing dmeventd.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
line = strchr(msg.data, ' ') + 1;
|
||||
for (i = 0; msg.data[i]; ++i)
|
||||
if (msg.data[i] == ';') {
|
||||
msg.data[i] = 0;
|
||||
if (!count)
|
||||
printf("%s is monitoring:\n", name);
|
||||
printf("%s\n", line);
|
||||
line = msg.data + i + 1;
|
||||
++count;
|
||||
}
|
||||
|
||||
free(msg.data);
|
||||
|
||||
if (!count)
|
||||
printf("%s does not monitor any device.\n", name);
|
||||
|
||||
if (version >= 2) {
|
||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
|
||||
fprintf(stderr, "Failed to acquire parameters from existing dmeventd.\n");
|
||||
goto out;
|
||||
}
|
||||
printf("%s internal status: %s\n", name, msg.data);
|
||||
free(msg.data);
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
out:
|
||||
fini_fifos(fifos);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return 0 - fail, 1 - success, 2 - continue */
|
||||
static int _restart_dmeventd(struct dm_event_fifos *fifos)
|
||||
{
|
||||
struct dm_event_fifos fifos = {
|
||||
.client = -1,
|
||||
.server = -1,
|
||||
/* FIXME Make these either configurable or depend directly on dmeventd_path */
|
||||
.client_path = DM_EVENT_FIFO_CLIENT,
|
||||
.server_path = DM_EVENT_FIFO_SERVER
|
||||
};
|
||||
struct dm_event_daemon_message msg = { 0 };
|
||||
int i, count = 0;
|
||||
char *message;
|
||||
int version;
|
||||
const char *e;
|
||||
|
||||
/* Get the list of registrations from the running daemon. */
|
||||
if (!init_fifos(&fifos)) {
|
||||
fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (!dm_daemon_is_running(DMEVENTD_PIDFILE)) {
|
||||
fprintf(stderr, "WARNING: Could not find running dmeventd associated with pid file %s.\n", DMEVENTD_PIDFILE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_event_get_version(&fifos, &version)) {
|
||||
/* Get the list of registrations from the running daemon. */
|
||||
if (!init_fifos(fifos)) {
|
||||
fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_event_get_version(fifos, &version)) {
|
||||
fprintf(stderr, "WARNING: Could not communicate with existing dmeventd.\n");
|
||||
goto bad;
|
||||
}
|
||||
@@ -2063,7 +2168,7 @@ static void _restart_dmeventd(void)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0))
|
||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0))
|
||||
goto bad;
|
||||
|
||||
message = strchr(msg.data, ' ') + 1;
|
||||
@@ -2087,7 +2192,7 @@ static void _restart_dmeventd(void)
|
||||
}
|
||||
|
||||
if (version >= 2) {
|
||||
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
|
||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
|
||||
fprintf(stderr, "Failed to acquire parameters from old dmeventd.\n");
|
||||
goto bad;
|
||||
}
|
||||
@@ -2107,7 +2212,7 @@ static void _restart_dmeventd(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
|
||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
|
||||
fprintf(stderr, "Old dmeventd refused to die.\n");
|
||||
goto bad;
|
||||
}
|
||||
@@ -2116,43 +2221,41 @@ static void _restart_dmeventd(void)
|
||||
((e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) && strcmp(e, "1")))
|
||||
_systemd_activation = 1;
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
if ((access(DMEVENTD_PIDFILE, F_OK) == -1) && (errno == ENOENT))
|
||||
break;
|
||||
usleep(10);
|
||||
}
|
||||
fini_fifos(fifos);
|
||||
|
||||
if (!_systemd_activation) {
|
||||
fini_fifos(&fifos);
|
||||
return;
|
||||
}
|
||||
/* Give a few seconds dmeventd to finish */
|
||||
_wait_for_new_pid();
|
||||
|
||||
if (!_systemd_activation)
|
||||
return 2; // continue with dmeventd start up
|
||||
|
||||
/* Reopen fifos. */
|
||||
fini_fifos(&fifos);
|
||||
if (!init_fifos(&fifos)) {
|
||||
if (!init_fifos(fifos)) {
|
||||
fprintf(stderr, "Could not initiate communication with new instance of dmeventd.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_reinstate_registrations(&fifos)) {
|
||||
if (!_reinstate_registrations(fifos)) {
|
||||
fprintf(stderr, "Failed to reinstate monitoring with new instance of dmeventd.\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
fini_fifos(&fifos);
|
||||
exit(EXIT_SUCCESS);
|
||||
fini_fifos(fifos);
|
||||
return 1;
|
||||
bad:
|
||||
fini_fifos(&fifos);
|
||||
exit(EXIT_FAILURE);
|
||||
fini_fifos(fifos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _usage(char *prog, FILE *file)
|
||||
{
|
||||
fprintf(file, "Usage:\n"
|
||||
"%s [-d [-d [-d]]] [-f] [-h] [-l] [-R] [-V] [-?]\n\n"
|
||||
"%s [-d [-d [-d]]] [-e path] [-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"
|
||||
" -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"
|
||||
@@ -2162,6 +2265,10 @@ static void _usage(char *prog, FILE *file)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
signed char opt;
|
||||
int debug_level = 0;
|
||||
int info = 0;
|
||||
int restart = 0;
|
||||
int use_syslog = 1;
|
||||
struct dm_event_fifos fifos = {
|
||||
.client = -1,
|
||||
.server = -1,
|
||||
@@ -2169,39 +2276,58 @@ int main(int argc, char *argv[])
|
||||
.server_path = DM_EVENT_FIFO_SERVER
|
||||
};
|
||||
time_t now, idle_exit_timeout = DMEVENTD_IDLE_EXIT_TIMEOUT;
|
||||
opterr = 0;
|
||||
optind = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "?fhVdlR")) != EOF) {
|
||||
optopt = optind = opterr = 0;
|
||||
optarg = (char*) "";
|
||||
while ((opt = getopt(argc, argv, ":?e:fhiVdlR")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
_usage(argv[0], stdout);
|
||||
exit(EXIT_SUCCESS);
|
||||
return EXIT_SUCCESS;
|
||||
case '?':
|
||||
_usage(argv[0], stderr);
|
||||
exit(EXIT_SUCCESS);
|
||||
return EXIT_SUCCESS;
|
||||
case 'i':
|
||||
info++;
|
||||
break;
|
||||
case 'R':
|
||||
_restart++;
|
||||
restart++;
|
||||
break;
|
||||
case 'e':
|
||||
if (strchr(optarg, '"')) {
|
||||
fprintf(stderr, "dmeventd: option -e does not accept path \"%s\" with '\"' character.\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
_exit_on=optarg;
|
||||
break;
|
||||
case 'f':
|
||||
_foreground++;
|
||||
break;
|
||||
case 'd':
|
||||
_debug_level++;
|
||||
debug_level++;
|
||||
break;
|
||||
case 'l':
|
||||
_use_syslog = 0;
|
||||
use_syslog = 0;
|
||||
break;
|
||||
case 'V':
|
||||
printf("dmeventd version: %s\n", DM_LIB_VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
return EXIT_SUCCESS;
|
||||
case ':':
|
||||
fprintf(stderr, "dmeventd: option -%c requires an argument.\n", optopt);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_foreground && !_use_syslog) {
|
||||
printf("WARNING: Ignoring logging to stdout, needs options -f\n");
|
||||
_use_syslog = 1;
|
||||
if (info) {
|
||||
_foreground = 1;
|
||||
use_syslog = 0;
|
||||
}
|
||||
|
||||
if (!_foreground && !use_syslog) {
|
||||
printf("WARNING: Ignoring logging to stdout, needs options -f\n");
|
||||
use_syslog = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch to C locale to avoid reading large locale-archive file
|
||||
* used by some glibc (on some distributions it takes over 100MB).
|
||||
@@ -2210,21 +2336,29 @@ int main(int argc, char *argv[])
|
||||
if (setenv("LC_ALL", "C", 1))
|
||||
perror("Cannot set LC_ALL to C");
|
||||
|
||||
if (_restart)
|
||||
_restart_dmeventd();
|
||||
if (info)
|
||||
return _info_dmeventd(argv[0], &fifos) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
|
||||
#ifdef __linux__
|
||||
_systemd_activation = _systemd_handover(&fifos);
|
||||
#endif
|
||||
|
||||
dm_log_with_errno_init(_libdm_log);
|
||||
|
||||
if (restart) {
|
||||
dm_event_log_set(debug_level, 0);
|
||||
|
||||
if ((restart = _restart_dmeventd(&fifos)) < 2)
|
||||
return restart ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!_foreground)
|
||||
_daemonize();
|
||||
|
||||
if (_use_syslog)
|
||||
if (use_syslog)
|
||||
openlog("dmeventd", LOG_PID, LOG_DAEMON);
|
||||
|
||||
dm_event_log_set(_debug_level, _use_syslog);
|
||||
dm_log_with_errno_init(_libdm_log);
|
||||
dm_event_log_set(debug_level, use_syslog);
|
||||
|
||||
(void) dm_prepare_selinux_context(DMEVENTD_PIDFILE, S_IFREG);
|
||||
if (dm_create_lockfile(DMEVENTD_PIDFILE) == 0)
|
||||
@@ -2285,15 +2419,28 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_exit_now == DM_SIGNALED_EXIT) {
|
||||
_exit_now = DM_SCHEDULED_EXIT;
|
||||
/*
|
||||
* When '_exit_now' is set, signal has been received,
|
||||
* but can not simply exit unless all
|
||||
* threads are done processing.
|
||||
*/
|
||||
log_info("dmeventd received break, scheduling exit.");
|
||||
}
|
||||
} else
|
||||
switch (_exit_now) {
|
||||
case DM_SIGNALED_EXIT:
|
||||
_exit_now = DM_SCHEDULED_EXIT;
|
||||
/*
|
||||
* When '_exit_now' is set, signal has been received,
|
||||
* but can not simply exit unless all
|
||||
* threads are done processing.
|
||||
*/
|
||||
log_info("dmeventd received break, scheduling exit.");
|
||||
/* fall through */
|
||||
case DM_SCHEDULED_EXIT:
|
||||
/* While exit is scheduled, check for exit_on file */
|
||||
DEBUGLOG("Checking exit on file \"%s\".", _exit_on);
|
||||
if (_exit_on[0] && (access(_exit_on, F_OK) == 0)) {
|
||||
log_info("dmeventd detected exit on file %s, unregistering all monitored devices.",
|
||||
_exit_on);
|
||||
_unregister_all_threads();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
_process_request(&fifos);
|
||||
_cleanup_unused_threads();
|
||||
}
|
||||
@@ -2303,11 +2450,11 @@ int main(int argc, char *argv[])
|
||||
log_notice("dmeventd shutting down.");
|
||||
|
||||
if (fifos.client >= 0 && close(fifos.client))
|
||||
log_sys_error("client close", fifos.client_path);
|
||||
log_sys_debug("client close", fifos.client_path);
|
||||
if (fifos.server >= 0 && close(fifos.server))
|
||||
log_sys_error("server close", fifos.server_path);
|
||||
log_sys_debug("server close", fifos.server_path);
|
||||
|
||||
if (_use_syslog)
|
||||
if (use_syslog)
|
||||
closelog();
|
||||
|
||||
_exit_dm_lib();
|
||||
|
@@ -68,7 +68,7 @@ struct dm_event_fifos {
|
||||
int daemon_talk(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg, int cmd,
|
||||
const char *dso_name, const char *dev_name,
|
||||
enum dm_event_mask evmask, uint32_t timeout);
|
||||
unsigned evmask, uint32_t timeout);
|
||||
int init_fifos(struct dm_event_fifos *fifos);
|
||||
void fini_fifos(struct dm_event_fifos *fifos);
|
||||
int dm_event_get_version(struct dm_event_fifos *fifos, int *version);
|
||||
|
@@ -352,7 +352,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
|
||||
int daemon_talk(struct dm_event_fifos *fifos,
|
||||
struct dm_event_daemon_message *msg, int cmd,
|
||||
const char *dso_name, const char *dev_name,
|
||||
enum dm_event_mask evmask, uint32_t timeout)
|
||||
unsigned evmask, uint32_t timeout)
|
||||
{
|
||||
int msg_size;
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
@@ -400,25 +400,16 @@ int daemon_talk(struct dm_event_fifos *fifos,
|
||||
return (int32_t) msg->cmd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* start_daemon
|
||||
* Check for usable client fifo file
|
||||
*
|
||||
* This function forks off a process (dmeventd) that will handle
|
||||
* the events. I am currently test opening one of the fifos to
|
||||
* ensure that the daemon is running and listening... I thought
|
||||
* this would be less expensive than fork/exec'ing every time.
|
||||
* Perhaps there is an even quicker/better way (no, checking the
|
||||
* lock file is _not_ a better way).
|
||||
*
|
||||
* Returns: 1 on success, 0 otherwise
|
||||
* Returns: 2 client path does not exists, dmeventd should be restarted
|
||||
* 1 on success, 0 otherwise
|
||||
*/
|
||||
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
{
|
||||
int pid, ret = 0;
|
||||
int status;
|
||||
struct stat statbuf;
|
||||
char default_dmeventd_path[] = DMEVENTD_PATH;
|
||||
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
|
||||
|
||||
/*
|
||||
* FIXME Explicitly verify the code's requirement that client_path is secure:
|
||||
@@ -429,7 +420,7 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
if ((lstat(fifos->client_path, &statbuf) < 0)) {
|
||||
if (errno == ENOENT)
|
||||
/* Jump ahead if fifo does not already exist. */
|
||||
goto start_server;
|
||||
return 2;
|
||||
else {
|
||||
log_sys_error("stat", fifos->client_path);
|
||||
return 0;
|
||||
@@ -455,12 +446,14 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
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;
|
||||
}
|
||||
|
||||
/* server is running and listening */
|
||||
if (close(fifos->client))
|
||||
log_sys_debug("close", fifos->client_path);
|
||||
fifos->client = -1;
|
||||
return 1;
|
||||
}
|
||||
if (errno != ENXIO && errno != ENOENT) {
|
||||
@@ -469,9 +462,36 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
return 0;
|
||||
}
|
||||
|
||||
start_server:
|
||||
/* server is not running */
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* start_daemon
|
||||
*
|
||||
* This function forks off a process (dmeventd) that will handle
|
||||
* the events. I am currently test opening one of the fifos to
|
||||
* ensure that the daemon is running and listening... I thought
|
||||
* this would be less expensive than fork/exec'ing every time.
|
||||
* Perhaps there is an even quicker/better way (no, checking the
|
||||
* lock file is _not_ a better way).
|
||||
*
|
||||
* Returns: 1 on success, 0 otherwise
|
||||
*/
|
||||
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char default_dmeventd_path[] = DMEVENTD_PATH;
|
||||
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
|
||||
int pid, ret = 0;
|
||||
int status;
|
||||
|
||||
switch (_check_for_usable_fifos(dmeventd_path, fifos)) {
|
||||
case 0: return_0;
|
||||
case 1: return 1; /* Already running dmeventd */
|
||||
}
|
||||
|
||||
/* server is not running */
|
||||
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
|
||||
log_sys_error("stat", args[0]);
|
||||
return 0;
|
||||
@@ -492,8 +512,17 @@ start_server:
|
||||
strerror(errno));
|
||||
else if (WEXITSTATUS(status))
|
||||
log_error("Unable to start dmeventd.");
|
||||
else
|
||||
ret = 1;
|
||||
else {
|
||||
/* Loop here till forked dmeventd is serving fifos */
|
||||
for (ret = 100; ret > 0; --ret)
|
||||
switch (_check_for_usable_fifos(dmeventd_path, fifos)) {
|
||||
case 0: return_0;
|
||||
case 1: return 1;
|
||||
case 2: usleep(1000); break;
|
||||
}
|
||||
/* ret == 0 */
|
||||
log_error("Dmeventd is not serving fifos.");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -513,7 +542,7 @@ int init_fifos(struct dm_event_fifos *fifos)
|
||||
/* Lock out anyone else trying to do communication with the daemon. */
|
||||
if (flock(fifos->server, LOCK_EX) < 0) {
|
||||
log_sys_error("flock", fifos->server_path);
|
||||
goto bad;
|
||||
goto bad_no_unlock;
|
||||
}
|
||||
|
||||
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
|
||||
@@ -524,6 +553,9 @@ int init_fifos(struct dm_event_fifos *fifos)
|
||||
|
||||
return 1;
|
||||
bad:
|
||||
if (flock(fifos->server, LOCK_UN))
|
||||
log_sys_debug("flock unlock", fifos->server_path);
|
||||
bad_no_unlock:
|
||||
if (close(fifos->server))
|
||||
log_sys_debug("close", fifos->server_path);
|
||||
fifos->server = -1;
|
||||
@@ -552,6 +584,8 @@ void fini_fifos(struct dm_event_fifos *fifos)
|
||||
if (close(fifos->server))
|
||||
log_sys_debug("close", fifos->server_path);
|
||||
}
|
||||
|
||||
fifos->client = fifos->server = -1;
|
||||
}
|
||||
|
||||
/* Get uuid of a device */
|
||||
@@ -720,7 +754,7 @@ static char *_fetch_string(char **src, const int delimiter)
|
||||
|
||||
/* Parse a device message from the daemon. */
|
||||
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
|
||||
char **uuid, enum dm_event_mask *evmask)
|
||||
char **uuid, unsigned *evmask)
|
||||
{
|
||||
char *id;
|
||||
char *p = msg->data;
|
||||
@@ -745,7 +779,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
||||
int ret = 0;
|
||||
const char *uuid = NULL;
|
||||
char *reply_dso = NULL, *reply_uuid = NULL;
|
||||
enum dm_event_mask reply_mask = 0;
|
||||
unsigned reply_mask = 0;
|
||||
struct dm_task *dmt = NULL;
|
||||
struct dm_event_daemon_message msg = { 0 };
|
||||
struct dm_info info;
|
||||
@@ -844,6 +878,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
||||
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
|
||||
char *p;
|
||||
struct dm_event_daemon_message msg = { 0 };
|
||||
int ret = 0;
|
||||
|
||||
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
|
||||
return 0;
|
||||
@@ -851,13 +886,17 @@ int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
|
||||
*version = 0;
|
||||
|
||||
if (!p || !(p = strchr(p, ' '))) /* Message ID */
|
||||
return 0;
|
||||
goto out;
|
||||
if (!(p = strchr(p + 1, ' '))) /* HELLO */
|
||||
return 0;
|
||||
goto out;
|
||||
if ((p = strchr(p + 1, ' '))) /* HELLO, once more */
|
||||
*version = atoi(p);
|
||||
|
||||
return 1;
|
||||
ret = 1;
|
||||
out:
|
||||
free(msg.data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dm_event_log_set(int debug_log_level, int use_syslog)
|
||||
@@ -872,11 +911,11 @@ void dm_event_log(const char *subsys, int level, const char *file,
|
||||
{
|
||||
static int _abort_on_internal_errors = -1;
|
||||
static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static time_t start = 0;
|
||||
static long long _start = 0;
|
||||
const char *indent = "";
|
||||
FILE *stream = log_stderr(level) ? stderr : stdout;
|
||||
int prio;
|
||||
time_t now;
|
||||
long long now, now_nsec;
|
||||
int log_with_debug = 0;
|
||||
|
||||
if (subsys[0] == '#') {
|
||||
@@ -923,17 +962,28 @@ void dm_event_log(const char *subsys, int level, const char *file,
|
||||
if (_use_syslog) {
|
||||
vsyslog(prio, format, ap);
|
||||
} else {
|
||||
now = time(NULL);
|
||||
if (!start)
|
||||
start = now;
|
||||
now -= start;
|
||||
if (_debug_level)
|
||||
fprintf(stream, "[%2lld:%02lld] %8x:%-6s%s",
|
||||
(long long)now / 60, (long long)now % 60,
|
||||
if (_debug_level) {
|
||||
#define _NSEC_PER_SEC (1000000000LL)
|
||||
#ifdef HAVE_REALTIME
|
||||
struct timespec mono_time = { 0 };
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &mono_time) == 0)
|
||||
now = mono_time.tv_sec * _NSEC_PER_SEC + mono_time.tv_nsec;
|
||||
else
|
||||
#endif
|
||||
now = time(NULL) * _NSEC_PER_SEC;
|
||||
|
||||
if (!_start)
|
||||
_start = now;
|
||||
now -= _start;
|
||||
now_nsec = now %_NSEC_PER_SEC;
|
||||
now /= _NSEC_PER_SEC;
|
||||
fprintf(stream, "[%2lld:%02lld.%06lld] %8x:%-6s%s",
|
||||
now / 60, now % 60, now_nsec / 1000,
|
||||
// TODO: Maybe use shorter ID
|
||||
// ((int)(pthread_self()) >> 6) & 0xffff,
|
||||
(int)pthread_self(), subsys,
|
||||
(_debug_level > 3) ? "" : indent);
|
||||
}
|
||||
if (_debug_level > 3)
|
||||
fprintf(stream, "%28s:%4d %s", file, line, indent);
|
||||
vfprintf(stream, _(format), ap);
|
||||
@@ -957,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;
|
||||
|
@@ -41,7 +41,7 @@ enum dm_event_mask {
|
||||
|
||||
DM_EVENT_STATUS_MASK = 0xFF0000,
|
||||
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
|
||||
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
|
||||
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occurred */
|
||||
|
||||
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
|
||||
};
|
||||
@@ -109,7 +109,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;
|
||||
@@ -123,6 +123,7 @@ struct dm_pool *dmeventd_lvm2_pool(void)
|
||||
|
||||
int dmeventd_lvm2_run(const char *cmdline)
|
||||
{
|
||||
/* coverity[missing_lock] no locking for run part */
|
||||
return (lvm2_run(_lvm_handle, cmdline) == LVM2_COMMAND_SUCCEEDED);
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
*/
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -245,7 +245,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,7 +379,7 @@ 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->pid = -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
|
||||
*/
|
||||
@@ -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;
|
||||
|
@@ -51,18 +51,14 @@ include $(top_builddir)/make.tmpl
|
||||
|
||||
.PHONY: install_lvmdbusd
|
||||
|
||||
all:
|
||||
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
|
||||
|
||||
install_lvmdbusd: $(LVMDBUSD)
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_DIR) $(sbindir)
|
||||
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
|
||||
$(Q) $(INSTALL_DIR) $(lvmdbusdir)
|
||||
$(Q) $(INSTALL_DIR) $(lvmdbusdir) $(lvmdbusdir)/__pycache__
|
||||
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(lvmdbusdir))
|
||||
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(lvmdbusdir)
|
||||
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbuspydir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
|
||||
$(Q) $(CHMOD) 755 $(lvmdbusdir)/__pycache__
|
||||
$(Q) $(CHMOD) 444 $(lvmdbusdir)/__pycache__/*.py[co]
|
||||
|
||||
install_lvm2: install_lvmdbusd
|
||||
|
@@ -50,6 +50,8 @@ worker_q = queue.Queue()
|
||||
# Main event loop
|
||||
loop = None
|
||||
|
||||
G_LOOP_TMO = 0.5
|
||||
|
||||
# Used to instruct the daemon if we should ignore SIGTERM
|
||||
ignore_sigterm = False
|
||||
|
||||
|
@@ -136,7 +136,7 @@ def call_lvm(command, debug=False, line_cb=None,
|
||||
while True and cfg.run.value != 0:
|
||||
try:
|
||||
rd_fd = [process.stdout.fileno(), process.stderr.fileno()]
|
||||
ready = select.select(rd_fd, [], [], 2)
|
||||
ready = select.select(rd_fd, [], [], cfg.G_LOOP_TMO)
|
||||
|
||||
for r in ready[0]:
|
||||
if r == process.stdout.fileno():
|
||||
|
@@ -183,9 +183,9 @@ class StateUpdate(object):
|
||||
obj.deferred = False
|
||||
|
||||
if len(queued_requests) == 0 and wait:
|
||||
# Note: If we don't have anything for 2 seconds we will
|
||||
# Note: If we don't have anything for N seconds we will
|
||||
# get a queue.Empty exception raised here
|
||||
queued_requests.append(obj.queue.get(block=True, timeout=2))
|
||||
queued_requests.append(obj.queue.get(block=True, timeout=cfg.G_LOOP_TMO))
|
||||
|
||||
# Ok we have one or the deferred queue has some,
|
||||
# check if any others and grab them too
|
||||
|
@@ -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)
|
||||
|
4
daemons/lvmdbusd/lvm_shell_proxy.py.in
Executable file → Normal file
4
daemons/lvmdbusd/lvm_shell_proxy.py.in
Executable file → Normal file
@@ -66,7 +66,7 @@ class LVMShellProxy(object):
|
||||
self.parent_stdout_fd,
|
||||
self.report_stream.fileno(),
|
||||
self.parent_stderr_fd]
|
||||
ready = select.select(rd_fd, [], [], 2)
|
||||
ready = select.select(rd_fd, [], [], cfg.G_LOOP_TMO)
|
||||
|
||||
for r in ready[0]:
|
||||
if r == self.parent_stdout_fd:
|
||||
@@ -154,6 +154,8 @@ class LVMShellProxy(object):
|
||||
|
||||
# If any env variables contain LVM we will propagate them too
|
||||
for k, v in os.environ.items():
|
||||
if "PATH" in k:
|
||||
local_env[k] = v
|
||||
if "LVM" in k:
|
||||
local_env[k] = v
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -41,7 +41,7 @@ def process_request():
|
||||
while cfg.run.value != 0:
|
||||
# noinspection PyBroadException
|
||||
try:
|
||||
req = cfg.worker_q.get(True, 5)
|
||||
req = cfg.worker_q.get(True, cfg.G_LOOP_TMO)
|
||||
log_debug(
|
||||
"Method start: %s with args %s (callback = %s)" %
|
||||
(str(req.method), str(req.arguments), str(req.cb)))
|
||||
@@ -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)
|
||||
|
||||
|
@@ -543,7 +543,7 @@ def round_size(size_bytes):
|
||||
return size_bytes + bs - remainder
|
||||
|
||||
|
||||
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_\/%'
|
||||
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_/%'
|
||||
_ALLOWABLE_CH_SET = set(_ALLOWABLE_CH)
|
||||
|
||||
_ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+'
|
||||
@@ -778,6 +778,7 @@ class LockFile(object):
|
||||
|
||||
def __enter__(self):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(self.lock_file), exist_ok=True)
|
||||
self.fd = os.open(self.lock_file, os.O_CREAT | os.O_RDWR, stat.S_IRUSR | stat.S_IWUSR)
|
||||
|
||||
# Get and set the close on exec and lock the file
|
||||
|
@@ -51,24 +51,25 @@ LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||
|
||||
ifneq (,$(firstword $(LIBSYSTEMD_LIBS)))
|
||||
CFLAGS += $(LIBSYSTEMD_CFLAGS) -DUSE_SD_NOTIFY
|
||||
DEFS += -DUSE_SD_NOTIFY
|
||||
CFLAGS += $(LIBSYSTEMD_CFLAGS)
|
||||
LIBS += $(LIBSYSTEMD_LIBS)
|
||||
endif
|
||||
|
||||
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
|
||||
@echo " [CC] $@"
|
||||
$(SHOW) " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LOCK_LIBS) $(LIBS)
|
||||
|
||||
lvmlockctl: lvmlockctl.o $(INTERNAL_LIBS)
|
||||
@echo " [CC] $@"
|
||||
$(SHOW) " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
|
||||
|
||||
install_lvmlockd: lvmlockd
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
||||
install_lvmlockctl: lvmlockctl
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
||||
install_lvm2: install_lvmlockd install_lvmlockctl
|
||||
|
@@ -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;
|
||||
@@ -264,19 +264,19 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
|
||||
static void format_info_line(char *line, char *r_name, char *r_type)
|
||||
{
|
||||
if (!strncmp(line, "info=structs ", strlen("info=structs "))) {
|
||||
if (!strncmp(line, "info=structs ", sizeof("info=structs ") - 1)) {
|
||||
/* only print this in the raw info dump */
|
||||
|
||||
} else if (!strncmp(line, "info=client ", strlen("info=client "))) {
|
||||
} else if (!strncmp(line, "info=client ", sizeof("info=client ") - 1)) {
|
||||
save_client_info(line);
|
||||
|
||||
} else if (!strncmp(line, "info=ls ", strlen("info=ls "))) {
|
||||
} else if (!strncmp(line, "info=ls ", sizeof("info=ls ") - 1)) {
|
||||
format_info_ls(line);
|
||||
|
||||
} else if (!strncmp(line, "info=ls_action ", strlen("info=ls_action "))) {
|
||||
} else if (!strncmp(line, "info=ls_action ", sizeof("info=ls_action ") - 1)) {
|
||||
format_info_ls_action(line);
|
||||
|
||||
} else if (!strncmp(line, "info=r ", strlen("info=r "))) {
|
||||
} else if (!strncmp(line, "info=r ", sizeof("info=r ") - 1)) {
|
||||
/*
|
||||
* r_name/r_type are reset when a new resource is found.
|
||||
* They are reused for the lock and action lines that
|
||||
@@ -286,11 +286,11 @@ static void format_info_line(char *line, char *r_name, char *r_type)
|
||||
memset(r_type, 0, MAX_NAME+1);
|
||||
format_info_r(line, r_name, r_type);
|
||||
|
||||
} else if (!strncmp(line, "info=lk ", strlen("info=lk "))) {
|
||||
} else if (!strncmp(line, "info=lk ", sizeof("info=lk ") - 1)) {
|
||||
/* will use info from previous r */
|
||||
format_info_lk(line, r_name, r_type);
|
||||
|
||||
} else if (!strncmp(line, "info=r_action ", strlen("info=r_action "))) {
|
||||
} else if (!strncmp(line, "info=r_action ", sizeof("info=r_action ") - 1)) {
|
||||
/* will use info from previous r */
|
||||
format_info_r_action(line, r_name, r_type);
|
||||
} else {
|
||||
@@ -940,7 +940,7 @@ static int read_options(int argc, char *argv[])
|
||||
int option_index = 0;
|
||||
int c;
|
||||
|
||||
static struct option long_options[] = {
|
||||
static const struct option _long_options[] = {
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"quit", no_argument, 0, 'q' },
|
||||
{"info", no_argument, 0, 'i' },
|
||||
@@ -962,7 +962,7 @@ static int read_options(int argc, char *argv[])
|
||||
}
|
||||
|
||||
while (1) {
|
||||
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", long_options, &option_index);
|
||||
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", _long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
|
@@ -16,9 +16,12 @@
|
||||
#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 daemon_handle lvmlockd_open(const char *sock)
|
||||
static inline __attribute__((always_inline))
|
||||
daemon_handle lvmlockd_open(const char *sock)
|
||||
{
|
||||
daemon_info lvmlockd_info = {
|
||||
.path = "lvmlockd",
|
||||
@@ -51,5 +54,8 @@ 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
|
||||
|
||||
#endif /* _LVM_LVMLOCKD_CLIENT_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -96,7 +96,6 @@ static int check_args_version(char *vg_args)
|
||||
|
||||
static int read_cluster_name(char *clustername)
|
||||
{
|
||||
static const char close_error_msg[] = "read_cluster_name: close_error %d";
|
||||
char *n;
|
||||
int fd;
|
||||
int rv;
|
||||
@@ -115,18 +114,19 @@ static int read_cluster_name(char *clustername)
|
||||
rv = read(fd, clustername, MAX_ARGS);
|
||||
if (rv < 0) {
|
||||
log_error("read_cluster_name: cluster name read error %d, check dlm_controld", fd);
|
||||
if (close(fd))
|
||||
log_error(close_error_msg, fd);
|
||||
return rv;
|
||||
goto out;
|
||||
}
|
||||
clustername[rv] = 0;
|
||||
|
||||
n = strstr(clustername, "\n");
|
||||
if (n)
|
||||
*n = '\0';
|
||||
rv = 0;
|
||||
out:
|
||||
if (close(fd))
|
||||
log_error(close_error_msg, fd);
|
||||
return 0;
|
||||
log_error("read_cluster_name: close_error %d", fd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define MAX_VERSION 16
|
||||
@@ -226,14 +226,14 @@ static int get_local_nodeid(void)
|
||||
{
|
||||
struct dirent *de;
|
||||
DIR *ls_dir;
|
||||
char ls_comms_path[PATH_MAX];
|
||||
char ls_comms_path[PATH_MAX] = { 0 };
|
||||
char path[PATH_MAX] = { 0 };
|
||||
FILE *file;
|
||||
char line[LOCK_LINE_MAX];
|
||||
char *str1, *str2;
|
||||
int rv = -1, val;
|
||||
|
||||
memset(ls_comms_path, 0, sizeof(ls_comms_path));
|
||||
snprintf(ls_comms_path, PATH_MAX, "%s",DLM_COMMS_PATH);
|
||||
snprintf(ls_comms_path, sizeof(ls_comms_path), "%s", DLM_COMMS_PATH);
|
||||
|
||||
if (!(ls_dir = opendir(ls_comms_path)))
|
||||
return -ECONNREFUSED;
|
||||
@@ -241,31 +241,31 @@ static int get_local_nodeid(void)
|
||||
while ((de = readdir(ls_dir))) {
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
memset(ls_comms_path, 0, sizeof(ls_comms_path));
|
||||
snprintf(ls_comms_path, PATH_MAX, "%s/%s/local",
|
||||
DLM_COMMS_PATH, de->d_name);
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s/local",
|
||||
DLM_COMMS_PATH, de->d_name);
|
||||
|
||||
if (!(file = fopen(ls_comms_path, "r")))
|
||||
continue;
|
||||
str1 = fgets(line, LOCK_LINE_MAX, file);
|
||||
fclose(file);
|
||||
|
||||
str1 = fgets(line, sizeof(line), file);
|
||||
if (fclose(file))
|
||||
log_sys_debug("fclose", path);
|
||||
if (str1) {
|
||||
rv = sscanf(line, "%d", &val);
|
||||
if ((rv == 1) && (val == 1 )) {
|
||||
memset(ls_comms_path, 0, sizeof(ls_comms_path));
|
||||
snprintf(ls_comms_path, PATH_MAX, "%s/%s/nodeid",
|
||||
DLM_COMMS_PATH, de->d_name);
|
||||
snprintf(path, sizeof(path), "%s/%s/nodeid",
|
||||
DLM_COMMS_PATH, de->d_name);
|
||||
|
||||
if (!(file = fopen(ls_comms_path, "r")))
|
||||
if (!(file = fopen(path, "r")))
|
||||
continue;
|
||||
str2 = fgets(line, LOCK_LINE_MAX, file);
|
||||
fclose(file);
|
||||
|
||||
str2 = fgets(line, sizeof(line), file);
|
||||
if (fclose(file))
|
||||
log_sys_debug("fclose", path);
|
||||
if (str2) {
|
||||
rv = sscanf(line, "%d", &val);
|
||||
if (rv == 1) {
|
||||
closedir(ls_dir);
|
||||
if (closedir(ls_dir))
|
||||
log_sys_debug("closedir", ls_comms_path);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@@ -274,7 +274,8 @@ static int get_local_nodeid(void)
|
||||
}
|
||||
|
||||
if (closedir(ls_dir))
|
||||
log_error("get_local_nodeid closedir error");
|
||||
log_sys_debug("closedir", ls_comms_path);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -304,20 +305,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;
|
||||
@@ -385,7 +393,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:
|
||||
@@ -409,7 +417,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);
|
||||
@@ -464,7 +472,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;
|
||||
@@ -473,29 +481,29 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
* dlm returns 0 for success, -EAGAIN if an orphan is
|
||||
* found with another mode, and -ENOENT if no orphan.
|
||||
*
|
||||
* cast/bast/param are (void *)1 because the kernel
|
||||
* cast/bast/param are (void (*)(void*))1 because the kernel
|
||||
* returns errors if some are null.
|
||||
*/
|
||||
|
||||
rv = dlm_ls_lockx(lmd->dh, mode, lksb, flags,
|
||||
r->name, strlen(r->name), 0,
|
||||
(void *)1, (void *)1, (void *)1,
|
||||
(void (*)(void*))1, (void (*)(void*))1, (void (*)(void*))1,
|
||||
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;
|
||||
}
|
||||
@@ -525,7 +533,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;
|
||||
@@ -535,7 +543,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. */
|
||||
@@ -564,7 +578,7 @@ 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) {
|
||||
@@ -584,7 +598,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;
|
||||
}
|
||||
@@ -597,17 +611,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;
|
||||
@@ -636,11 +650,11 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
|
||||
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
|
||||
struct dlm_lksb *lksb = &rdd->lksb;
|
||||
uint32_t mode;
|
||||
int mode;
|
||||
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;
|
||||
@@ -654,14 +668,16 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
rdd->vb->r_version = cpu_to_le32(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;
|
||||
}
|
||||
|
||||
mode = to_dlm_mode(ld_mode);
|
||||
|
||||
if ((mode = to_dlm_mode(ld_mode)) < 0) {
|
||||
log_error("lm_convert_dlm invalid mode %d", ld_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
|
||||
@@ -670,11 +686,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;
|
||||
@@ -724,7 +740,7 @@ 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),
|
||||
@@ -733,12 +749,12 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
le16_to_cpu(vb_next.flags),
|
||||
le32_to_cpu(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)
|
||||
@@ -748,7 +764,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;
|
||||
}
|
||||
|
||||
@@ -783,7 +799,6 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
|
||||
int lm_hosts_dlm(struct lockspace *ls, int notify)
|
||||
{
|
||||
static const char closedir_err_msg[] = "lm_hosts_dlm: closedir failed";
|
||||
char ls_nodes_path[PATH_MAX];
|
||||
struct dirent *de;
|
||||
DIR *ls_dir;
|
||||
@@ -806,7 +821,7 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
|
||||
}
|
||||
|
||||
if (closedir(ls_dir))
|
||||
log_error(closedir_err_msg);
|
||||
log_error("lm_hosts_dlm: closedir failed");
|
||||
|
||||
if (!count) {
|
||||
log_error("lm_hosts_dlm found no nodes in %s", ls_nodes_path);
|
||||
@@ -823,10 +838,10 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
|
||||
|
||||
int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
|
||||
{
|
||||
static const char closedir_err_msg[] = "lm_get_lockspace_dlm: closedir failed";
|
||||
struct lockspace *ls;
|
||||
struct dirent *de;
|
||||
DIR *ls_dir;
|
||||
int ret = 0;
|
||||
|
||||
if (!(ls_dir = opendir(DLM_LOCKSPACES_PATH)))
|
||||
return -ECONNREFUSED;
|
||||
@@ -839,20 +854,20 @@ int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
|
||||
continue;
|
||||
|
||||
if (!(ls = alloc_lockspace())) {
|
||||
if (closedir(ls_dir))
|
||||
log_error(closedir_err_msg);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ls->lm_type = LD_LM_DLM;
|
||||
strncpy(ls->name, de->d_name, MAX_NAME);
|
||||
strncpy(ls->vg_name, ls->name + strlen(LVM_LS_PREFIX), MAX_NAME);
|
||||
dm_strncpy(ls->name, de->d_name, sizeof(ls->name));
|
||||
dm_strncpy(ls->vg_name, ls->name + strlen(LVM_LS_PREFIX), sizeof(ls->vg_name));
|
||||
list_add_tail(&ls->list, ls_rejoin);
|
||||
}
|
||||
|
||||
out:
|
||||
if (closedir(ls_dir))
|
||||
log_error(closedir_err_msg);
|
||||
return 0;
|
||||
log_error("lm_get_lockspace_dlm: closedir failed");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lm_is_running_dlm(void)
|
||||
@@ -882,7 +897,7 @@ int lm_refresh_lv_start_dlm(struct action *act)
|
||||
int rv;
|
||||
|
||||
/* split /dev/vgname/lvname into vgname and lvname strings */
|
||||
strncpy(path, act->path, PATH_MAX-1);
|
||||
dm_strncpy(path, act->path, sizeof(path));
|
||||
|
||||
/* skip past dev */
|
||||
if (!(p = strchr(path + 1, '/')))
|
||||
|
@@ -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];
|
||||
@@ -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;
|
||||
|
@@ -107,11 +107,12 @@ 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 */
|
||||
|
||||
/*
|
||||
* Number of times to repeat a lock request after
|
||||
@@ -131,6 +132,7 @@ struct action {
|
||||
uint32_t flags; /* LD_AF_ */
|
||||
uint32_t version;
|
||||
uint64_t host_id;
|
||||
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 +141,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];
|
||||
@@ -190,8 +193,6 @@ struct lockspace {
|
||||
void *lm_data;
|
||||
uint64_t host_id;
|
||||
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 */
|
||||
@@ -363,6 +364,8 @@ void log_level(int level, const char *fmt, ...) __attribute__((format(printf, 2
|
||||
#define log_debug(fmt, args...) log_level(LOG_DEBUG, fmt, ##args)
|
||||
#define log_error(fmt, args...) log_level(LOG_ERR, fmt, ##args)
|
||||
#define log_warn(fmt, args...) log_level(LOG_WARNING, fmt, ##args)
|
||||
#define log_sys_debug(x, y) \
|
||||
log_debug("%s: %s failed: %s", y, x, strerror(errno))
|
||||
|
||||
struct lockspace *alloc_lockspace(void);
|
||||
int lockspaces_empty(void);
|
||||
@@ -391,11 +394,11 @@ 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_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,
|
||||
@@ -425,7 +428,7 @@ static inline int lm_prepare_lockspace_dlm(struct lockspace *ls)
|
||||
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)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -441,7 +444,7 @@ static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -502,15 +505,16 @@ 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);
|
||||
int lm_init_lv_sanlock(struct lockspace *ls, char *lv_name, char *vg_args, char *lv_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_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok);
|
||||
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
|
||||
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,
|
||||
int adopt_only, int adopt_ok);
|
||||
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,
|
||||
@@ -523,7 +527,7 @@ 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);
|
||||
|
||||
static inline int lm_support_sanlock(void)
|
||||
{
|
||||
@@ -532,12 +536,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)
|
||||
{
|
||||
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 *lv_name, char *vg_args, char *lv_args)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -557,7 +561,7 @@ static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
|
||||
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)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -568,7 +572,8 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
|
||||
}
|
||||
|
||||
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,
|
||||
int adopt_only, int adopt_ok)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -625,7 +630,7 @@ 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;
|
||||
}
|
||||
@@ -642,11 +647,11 @@ 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_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,
|
||||
@@ -679,7 +684,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,7 +696,7 @@ static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
|
||||
|
||||
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
@@ -32,11 +32,11 @@ LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||
|
||||
lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
|
||||
@echo " [CC] $@"
|
||||
$(SHOW) " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
|
||||
|
||||
install_lvmpolld: lvmpolld
|
||||
@echo " [INSTALL] $<"
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
|
||||
|
||||
install_lvm2: install_lvmpolld
|
||||
|
@@ -19,7 +19,7 @@
|
||||
|
||||
#define MIN_ARGV_SIZE 8
|
||||
|
||||
static const char *const polling_ops[] = {
|
||||
static const char *const _polling_ops[] = {
|
||||
[PVMOVE] = LVMPD_REQ_PVMOVE,
|
||||
[CONVERT] = LVMPD_REQ_CONVERT,
|
||||
[MERGE] = LVMPD_REQ_MERGE,
|
||||
@@ -28,7 +28,7 @@ static const char *const polling_ops[] = {
|
||||
|
||||
const char *polling_op(enum poll_type type)
|
||||
{
|
||||
return type < POLL_TYPE_MAX ? polling_ops[type] : "<undefined>";
|
||||
return type < POLL_TYPE_MAX ? _polling_ops[type] : "<undefined>";
|
||||
}
|
||||
|
||||
static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *ind)
|
||||
@@ -81,7 +81,7 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary,
|
||||
|
||||
/* one of: "convert", "pvmove", "merge", "merge_thin" */
|
||||
if (!add_to_cmd_arr(&cmd_argv, "--polloperation", &i) ||
|
||||
!add_to_cmd_arr(&cmd_argv, polling_ops[pdlv->type], &i))
|
||||
!add_to_cmd_arr(&cmd_argv, _polling_ops[pdlv->type], &i))
|
||||
goto err;
|
||||
|
||||
/* vg/lv name */
|
||||
|
@@ -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)
|
||||
@@ -781,7 +781,7 @@ struct log_line_baton {
|
||||
const char *prefix;
|
||||
};
|
||||
|
||||
daemon_handle _lvmpolld = { .error = 0 };
|
||||
static daemon_handle _lvmpolld = { .error = 0 };
|
||||
|
||||
static daemon_handle _lvmpolld_open(const char *socket)
|
||||
{
|
||||
@@ -867,14 +867,14 @@ enum action_index {
|
||||
ACTION_MAX /* keep at the end */
|
||||
};
|
||||
|
||||
static const action_fn_t actions[ACTION_MAX] = { [ACTION_DUMP] = action_dump };
|
||||
|
||||
static int _make_action(enum action_index idx, void *args)
|
||||
{
|
||||
return idx < ACTION_MAX ? actions[idx](args) : 0;
|
||||
static const action_fn_t _actions[ACTION_MAX] = { [ACTION_DUMP] = action_dump };
|
||||
|
||||
return idx < ACTION_MAX ? _actions[idx](args) : 0;
|
||||
}
|
||||
|
||||
static int _lvmpolld_client(const char *socket, unsigned action)
|
||||
static int _lvmpolld_client(const char *socket, enum action_index action)
|
||||
{
|
||||
int r;
|
||||
|
||||
@@ -892,10 +892,9 @@ static int _lvmpolld_client(const char *socket, unsigned action)
|
||||
return r ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static int action_idx = ACTION_MAX;
|
||||
static struct option long_options[] = {
|
||||
static const struct option _long_options[] = {
|
||||
/* Have actions always at the beginning of the array. */
|
||||
{"dump", no_argument, &action_idx, ACTION_DUMP }, /* or an option_index ? */
|
||||
{"dump", no_argument, 0, ACTION_DUMP }, /* or an option_index ? */
|
||||
|
||||
/* other options */
|
||||
{"binary", required_argument, 0, 'B' },
|
||||
@@ -914,7 +913,7 @@ int main(int argc, char *argv[])
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
int client = 0, server = 0;
|
||||
unsigned action = ACTION_MAX;
|
||||
enum action_index action = ACTION_MAX;
|
||||
struct timespec timeout;
|
||||
daemon_idle di = { .ptimeout = &timeout };
|
||||
struct lvmpolld_state ls = { .log_config = "" };
|
||||
@@ -930,16 +929,16 @@ int main(int argc, char *argv[])
|
||||
.socket_path = getenv("LVM_LVMPOLLD_SOCKET") ?: LVMPOLLD_SOCKET,
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "fhVl:p:s:B:t:", long_options, &option_index)) != -1) {
|
||||
while ((opt = getopt_long(argc, argv, "fhVl:p:s:B:t:", _long_options, &option_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 0 :
|
||||
if (action < ACTION_MAX) {
|
||||
if (action != ACTION_MAX) {
|
||||
fprintf(stderr, "Can't perform more actions. Action already requested: %s\n",
|
||||
long_options[action].name);
|
||||
_long_options[action].name);
|
||||
_usage(argv[0], stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
action = action_idx;
|
||||
action = ACTION_DUMP;
|
||||
client = 1;
|
||||
break;
|
||||
case '?':
|
||||
|
@@ -273,12 +273,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 +290,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 */
|
||||
|
@@ -45,18 +45,18 @@ struct lvmpolld_lv {
|
||||
* accessing following vars doesn't
|
||||
* require struct lvmpolld_lv lock
|
||||
*/
|
||||
struct lvmpolld_state *const ls;
|
||||
const enum poll_type type;
|
||||
const char *const lvid;
|
||||
const char *const lvmpolld_id;
|
||||
const char *const devicesfile;
|
||||
const char *const lvname; /* full vg/lv name */
|
||||
const unsigned pdtimeout; /* in seconds */
|
||||
const char *const sinterval;
|
||||
const char *const lvm_system_dir_env;
|
||||
struct lvmpolld_store *const pdst;
|
||||
const char *const *cmdargv;
|
||||
const char *const *cmdenvp;
|
||||
struct lvmpolld_state *ls;
|
||||
enum poll_type type;
|
||||
const char *lvid;
|
||||
const char *lvmpolld_id;
|
||||
const char *devicesfile;
|
||||
const char *lvname; /* full vg/lv name */
|
||||
unsigned pdtimeout; /* in seconds */
|
||||
const char *sinterval;
|
||||
const char *lvm_system_dir_env;
|
||||
struct lvmpolld_store *pdst;
|
||||
const char **cmdargv;
|
||||
const char **cmdenvp;
|
||||
|
||||
/* only used by write */
|
||||
pid_t cmd_pid;
|
||||
@@ -66,9 +66,9 @@ struct lvmpolld_lv {
|
||||
|
||||
/* block of shared variables protected by lock */
|
||||
struct lvmpolld_cmd_stat cmd_state;
|
||||
unsigned init_rq_count; /* for debuging purposes only */
|
||||
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);
|
||||
|
@@ -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
|
||||
|
@@ -44,10 +44,10 @@ CLEAN_TARGETS += $(DEVICE_MAPPER_DEPENDS) $(DEVICE_MAPPER_OBJECTS) \
|
||||
#$(DEVICE_MAPPER_OBJECTS): INCLUDES+=$(VDO_INCLUDES)
|
||||
|
||||
$(DEVICE_MAPPER_TARGET): $(DEVICE_MAPPER_OBJECTS)
|
||||
@echo " [AR] $@"
|
||||
$(SHOW) " [AR] $@"
|
||||
$(Q) $(RM) $@
|
||||
$(Q) $(AR) rsv $@ $(DEVICE_MAPPER_OBJECTS) > /dev/null
|
||||
|
||||
ifeq ("$(DEPENDS)","yes")
|
||||
ifeq ("$(USE_TRACKING)","yes")
|
||||
-include $(DEVICE_MAPPER_DEPENDS)
|
||||
endif
|
||||
|
@@ -175,12 +175,11 @@ struct dm_names {
|
||||
|
||||
struct dm_active_device {
|
||||
struct dm_list list;
|
||||
int major;
|
||||
int 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 {
|
||||
@@ -230,13 +229,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(struct dm_list *devs_list, const char *uuid,
|
||||
const struct dm_active_device **dev);
|
||||
/* Release all associated memory with list of active DM devices */
|
||||
void dm_device_list_destroy(struct dm_list **devs_list);
|
||||
|
||||
@@ -312,15 +304,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 */
|
||||
@@ -549,7 +541,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.
|
||||
@@ -592,7 +584,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,
|
||||
@@ -706,7 +698,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);
|
||||
|
||||
@@ -893,7 +885,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,
|
||||
@@ -916,7 +908,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];
|
||||
@@ -953,7 +945,7 @@ struct dm_config_node;
|
||||
*
|
||||
* policy_settings {
|
||||
* migration_threshold=2048
|
||||
* sequention_threashold=100
|
||||
* sequential_threshold=100
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
@@ -1031,6 +1023,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;
|
||||
@@ -1039,6 +1032,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,
|
||||
@@ -1100,7 +1094,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)
|
||||
*/
|
||||
@@ -1166,7 +1160,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))
|
||||
@@ -1875,6 +1869,7 @@ const void *dm_report_value_cache_get(struct dm_report *rh, const char *name);
|
||||
#define DM_REPORT_OUTPUT_FIELD_UNQUOTED 0x00000010
|
||||
#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS 0x00000020
|
||||
#define DM_REPORT_OUTPUT_MULTIPLE_TIMES 0x00000040
|
||||
#define DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS 0x00000080
|
||||
|
||||
struct dm_report *dm_report_init(uint32_t *report_types,
|
||||
const struct dm_report_object_type *types,
|
||||
@@ -2063,7 +2058,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);
|
||||
|
||||
/*
|
||||
@@ -2126,7 +2121,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).
|
||||
@@ -2172,7 +2167,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).
|
||||
*/
|
||||
@@ -2243,7 +2238,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
|
||||
int dm_cookie_supported(void);
|
||||
|
||||
/*
|
||||
* Udev synchronisation functions.
|
||||
* Udev synchronization functions.
|
||||
*/
|
||||
void dm_udev_set_sync_support(int sync_with_udev);
|
||||
int dm_udev_get_sync_support(void);
|
||||
|
@@ -87,10 +87,8 @@ static int _version_checked = 0;
|
||||
static int _version_ok = 1;
|
||||
static unsigned _ioctl_buffer_double_factor = 0;
|
||||
|
||||
const int _dm_compat = 0;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static struct cmd_data _cmd_data_v4[] = {
|
||||
static const struct cmd_data _cmd_data_v4[] = {
|
||||
{"create", DM_DEV_CREATE, {4, 0, 0}},
|
||||
{"reload", DM_TABLE_LOAD, {4, 0, 0}},
|
||||
{"remove", DM_DEV_REMOVE, {4, 0, 0}},
|
||||
@@ -200,6 +198,7 @@ static int _get_proc_number(const char *file, const char *name,
|
||||
char *line = NULL;
|
||||
size_t len;
|
||||
uint32_t num;
|
||||
unsigned blocksection = (strcmp(file, PROC_DEVICES) == 0) ? 0 : 1;
|
||||
|
||||
if (!(fl = fopen(file, "r"))) {
|
||||
log_sys_error("fopen", file);
|
||||
@@ -207,7 +206,9 @@ static int _get_proc_number(const char *file, const char *name,
|
||||
}
|
||||
|
||||
while (getline(&line, &len, fl) != -1) {
|
||||
if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
|
||||
if (!blocksection && (line[0] == 'B'))
|
||||
blocksection = 1;
|
||||
else if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
|
||||
if (!strcmp(name, nm)) {
|
||||
if (number) {
|
||||
*number = num;
|
||||
@@ -247,6 +248,16 @@ static int _control_device_number(uint32_t *major, uint32_t *minor)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _control_unlink(const char *control)
|
||||
{
|
||||
if (unlink(control) && (errno != ENOENT)) {
|
||||
log_sys_error("unlink", control);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if it exists on returning; 0 if it doesn't; -1 if it's wrong.
|
||||
*/
|
||||
@@ -262,10 +273,7 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
|
||||
|
||||
if (!S_ISCHR(buf.st_mode)) {
|
||||
log_verbose("%s: Wrong inode type", control);
|
||||
if (!unlink(control))
|
||||
return 0;
|
||||
log_sys_error("unlink", control);
|
||||
return -1;
|
||||
return _control_unlink(control);
|
||||
}
|
||||
|
||||
if (major && buf.st_rdev != MKDEV(major, minor)) {
|
||||
@@ -273,10 +281,7 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
|
||||
"(%u, %u)", control,
|
||||
MAJOR(buf.st_mode), MINOR(buf.st_mode),
|
||||
major, minor);
|
||||
if (!unlink(control))
|
||||
return 0;
|
||||
log_sys_error("unlink", control);
|
||||
return -1;
|
||||
return _control_unlink(control);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -404,7 +409,7 @@ static void _close_control_fd(void)
|
||||
{
|
||||
if (_control_fd != -1) {
|
||||
if (close(_control_fd) < 0)
|
||||
log_sys_error("close", "_control_fd");
|
||||
log_sys_debug("close", "_control_fd");
|
||||
_control_fd = -1;
|
||||
}
|
||||
}
|
||||
@@ -593,23 +598,9 @@ int dm_check_version(void)
|
||||
|
||||
_version_checked = 1;
|
||||
|
||||
if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
|
||||
if (_check_version(dmversion, sizeof(dmversion), 0))
|
||||
return 1;
|
||||
|
||||
if (!_dm_compat)
|
||||
goto_bad;
|
||||
|
||||
log_verbose("device-mapper ioctl protocol version %u failed. "
|
||||
"Trying protocol version 1.", _dm_version);
|
||||
_dm_version = 1;
|
||||
if (_check_version(dmversion, sizeof(dmversion), 0)) {
|
||||
log_verbose("Using device-mapper ioctl protocol version 1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
compat = "(compat)";
|
||||
|
||||
bad:
|
||||
dm_get_library_version(libversion, sizeof(libversion));
|
||||
|
||||
log_error("Incompatible libdevmapper %s%s and kernel driver %s.",
|
||||
@@ -668,7 +659,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;
|
||||
@@ -757,6 +748,11 @@ uint32_t dm_task_get_read_ahead(const struct dm_task *dmt, uint32_t *read_ahead)
|
||||
|
||||
struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
|
||||
{
|
||||
if (!dmt) {
|
||||
log_error(INTERNAL_ERROR "Missing dm_task.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (struct dm_deps *) (((char *) dmt->dmi.v4) +
|
||||
dmt->dmi.v4->data_start);
|
||||
}
|
||||
@@ -786,19 +782,12 @@ 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;
|
||||
};
|
||||
|
||||
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;
|
||||
@@ -819,12 +808,12 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
|
||||
} while (next);
|
||||
}
|
||||
|
||||
if (!(devs = malloc(sizeof(*devs) + (cnt ? cnt * sizeof(*dm_dev) + (char*)names1 - (char*)names + 256 : 0))))
|
||||
/* buffer for devs + sorted ptrs + dm_devs + aligned strings */
|
||||
if (!(devs = malloc(sizeof(*devs) + cnt * (2 * sizeof(void*) + sizeof(*dm_dev)) +
|
||||
(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 */
|
||||
@@ -832,27 +821,22 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
|
||||
goto out; /* nothing else to do */
|
||||
}
|
||||
|
||||
dm_dev = (struct dm_active_device *) (devs + 1);
|
||||
/* Shift position where to store individual dm_devs */
|
||||
dm_dev = (struct dm_active_device *) ((long*) (devs + 1) + cnt);
|
||||
|
||||
do {
|
||||
names = (struct dm_names *)((char *) names + next);
|
||||
|
||||
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);
|
||||
@@ -861,55 +845,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) %d:%d 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;
|
||||
*devs_list = devs;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid,
|
||||
const struct dm_active_device **dev)
|
||||
{
|
||||
struct dm_device_list *devs = (struct dm_device_list *) devs_list;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1256,7 +1214,7 @@ static int _lookup_dev_name(uint64_t dev, char *buf, size_t len)
|
||||
do {
|
||||
names = (struct dm_names *)((char *) names + next);
|
||||
if (names->dev == dev) {
|
||||
strncpy(buf, names->name, len);
|
||||
memccpy(buf, names->name, 0, len);
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
@@ -1425,12 +1383,10 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
/* FIXME Until resume ioctl supplies name, use dev_name for readahead */
|
||||
if (DEV_NAME(dmt) && (dmt->type != DM_DEVICE_RESUME || dmt->minor < 0 ||
|
||||
dmt->major < 0))
|
||||
/* coverity[buffer_size_warning] */
|
||||
strncpy(dmi->name, DEV_NAME(dmt), sizeof(dmi->name));
|
||||
memccpy(dmi->name, DEV_NAME(dmt), 0, sizeof(dmi->name));
|
||||
|
||||
if (DEV_UUID(dmt))
|
||||
/* coverity[buffer_size_warning] */
|
||||
strncpy(dmi->uuid, DEV_UUID(dmt), sizeof(dmi->uuid));
|
||||
memccpy(dmi->uuid, DEV_UUID(dmt), 0, sizeof(dmi->uuid));
|
||||
|
||||
if (dmt->type == DM_DEVICE_SUSPEND)
|
||||
dmi->flags |= DM_SUSPEND_FLAG;
|
||||
@@ -1620,7 +1576,7 @@ static int _check_uevent_generated(struct dm_ioctl *dmi)
|
||||
static int _create_and_load_v4(struct dm_task *dmt)
|
||||
{
|
||||
struct dm_task *task;
|
||||
int r;
|
||||
int r, ioctl_errno = 0;
|
||||
uint32_t cookie;
|
||||
|
||||
/* Use new task struct to create the device */
|
||||
@@ -1646,8 +1602,10 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
task->cookie_set = dmt->cookie_set;
|
||||
task->add_node = dmt->add_node;
|
||||
|
||||
if (!dm_task_run(task))
|
||||
if (!dm_task_run(task)) {
|
||||
ioctl_errno = task->ioctl_errno;
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
dm_task_destroy(task);
|
||||
|
||||
@@ -1673,6 +1631,8 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
task->ima_measurement = dmt->ima_measurement;
|
||||
|
||||
r = dm_task_run(task);
|
||||
if (!r)
|
||||
ioctl_errno = task->ioctl_errno;
|
||||
|
||||
task->head = NULL;
|
||||
task->tail = NULL;
|
||||
@@ -1690,6 +1650,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
dmt->uuid = NULL;
|
||||
free(dmt->mangled_uuid);
|
||||
dmt->mangled_uuid = NULL;
|
||||
/* coverity[double_free] recursive function call */
|
||||
_dm_task_free_targets(dmt);
|
||||
|
||||
if (dm_task_run(dmt))
|
||||
@@ -1701,6 +1662,7 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
dmt->uuid = NULL;
|
||||
free(dmt->mangled_uuid);
|
||||
dmt->mangled_uuid = NULL;
|
||||
/* coverity[double_free] recursive function call */
|
||||
_dm_task_free_targets(dmt);
|
||||
|
||||
/*
|
||||
@@ -1719,12 +1681,18 @@ static int _create_and_load_v4(struct dm_task *dmt)
|
||||
if (!dm_task_run(dmt))
|
||||
log_error("Failed to revert device creation.");
|
||||
|
||||
if (ioctl_errno != 0)
|
||||
dmt->ioctl_errno = ioctl_errno;
|
||||
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
dm_task_destroy(task);
|
||||
_udev_complete(dmt);
|
||||
|
||||
if (ioctl_errno != 0)
|
||||
dmt->ioctl_errno = ioctl_errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2066,7 +2034,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
/*
|
||||
* Prevent udev vs. libdevmapper race when processing nodes
|
||||
* and symlinks. This can happen when the udev rules are
|
||||
* installed and udev synchronisation code is enabled in
|
||||
* installed and udev synchronization code is enabled in
|
||||
* libdevmapper but the software using libdevmapper does not
|
||||
* make use of it (by not calling dm_task_set_cookie before).
|
||||
* We need to instruct the udev rules not to be applied at
|
||||
@@ -2076,7 +2044,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
|
||||
if (!dmt->cookie_set && dm_udev_get_sync_support()) {
|
||||
log_debug_activation("Cookie value is not set while trying to call %s "
|
||||
"ioctl. Please, consider using libdevmapper's udev "
|
||||
"synchronisation interface or disable it explicitly "
|
||||
"synchronization interface or disable it explicitly "
|
||||
"by calling dm_udev_set_sync_support(0).",
|
||||
dmt->type == DM_DEVICE_RESUME ? "DM_DEVICE_RESUME" :
|
||||
dmt->type == DM_DEVICE_REMOVE ? "DM_DEVICE_REMOVE" :
|
||||
|
@@ -79,7 +79,7 @@ struct dm_task {
|
||||
};
|
||||
|
||||
struct cmd_data {
|
||||
const char *name;
|
||||
const char name[16];
|
||||
const unsigned cmd;
|
||||
const int version[3];
|
||||
};
|
||||
|
@@ -537,7 +537,8 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
|
||||
}
|
||||
|
||||
if (str[i] == '\\' && str[i+1] == 'x') {
|
||||
if (!sscanf(&str[i+2], "%2x%s", &code, str_rest)) {
|
||||
if (!sscanf(&str[i+2], "%2x%" DM_TO_STRING(DM_NAME_LEN) "s",
|
||||
&code, str_rest)) {
|
||||
log_debug_activation("Hex encoding mismatch detected in %s \"%s\" "
|
||||
"while trying to unmangle it.", str_name, str);
|
||||
goto out;
|
||||
@@ -1060,9 +1061,8 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
if (info.st_rdev == dev)
|
||||
return 1;
|
||||
|
||||
if (unlink(path) < 0) {
|
||||
log_error("Unable to unlink device node for '%s'",
|
||||
dev_name);
|
||||
if (unlink(path) && (errno != ENOENT)) {
|
||||
log_sys_error("unlink", path);
|
||||
return 0;
|
||||
}
|
||||
} else if (_warn_if_op_needed(warn_if_udev_failed))
|
||||
@@ -1106,8 +1106,8 @@ static int _rm_dev_node(const char *dev_name, int warn_if_udev_failed)
|
||||
"Falling back to direct node removal.", path);
|
||||
|
||||
/* udev may already have deleted the node. Ignore ENOENT. */
|
||||
if (unlink(path) < 0 && errno != ENOENT) {
|
||||
log_error("Unable to unlink device node for '%s'", dev_name);
|
||||
if (unlink(path) && (errno != ENOENT)) {
|
||||
log_sys_error("unlink", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1451,9 +1451,10 @@ struct node_op_parms {
|
||||
|
||||
static void _store_str(char **pos, char **ptr, const char *str)
|
||||
{
|
||||
strcpy(*pos, str);
|
||||
size_t len = strlen(str) + 1;
|
||||
memcpy(*pos, str, len);
|
||||
*ptr = *pos;
|
||||
*pos += strlen(*ptr) + 1;
|
||||
*pos += len;
|
||||
}
|
||||
|
||||
static void _del_node_op(struct node_op_parms *nop)
|
||||
@@ -1703,15 +1704,17 @@ const char *dm_sysfs_dir(void)
|
||||
*/
|
||||
int dm_set_uuid_prefix(const char *uuid_prefix)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (!uuid_prefix)
|
||||
return_0;
|
||||
|
||||
if (strlen(uuid_prefix) > DM_MAX_UUID_PREFIX_LEN) {
|
||||
if ((len = strlen(uuid_prefix)) > DM_MAX_UUID_PREFIX_LEN) {
|
||||
log_error("New uuid prefix %s too long.", uuid_prefix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(_default_uuid_prefix, uuid_prefix);
|
||||
memcpy(_default_uuid_prefix, uuid_prefix, len + 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1740,6 +1743,9 @@ static void _unmangle_mountinfo_string(const char *src, char *buf)
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
/* coverity[+tainted_string_sanitize_content:arg-0] */
|
||||
static int _sanitize_line(const char *line) { return 1; }
|
||||
|
||||
/* Parse one line of mountinfo and unmangled target line */
|
||||
static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min, char *buf)
|
||||
{
|
||||
@@ -1790,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)
|
||||
@@ -1810,7 +1816,8 @@ int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
|
||||
}
|
||||
|
||||
while (!feof(minfo) && fgets(buffer, sizeof(buffer), minfo))
|
||||
if (!_mountinfo_parse_line(buffer, &maj, &min, target) ||
|
||||
if (!_sanitize_line(buffer) ||
|
||||
!_mountinfo_parse_line(buffer, &maj, &min, target) ||
|
||||
!read_fn(buffer, maj, min, target, cb_data)) {
|
||||
stack;
|
||||
r = 0;
|
||||
@@ -1954,7 +1961,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") ||
|
||||
@@ -2311,7 +2318,7 @@ static int _check_semaphore_is_supported(void)
|
||||
|
||||
if (maxid < 0) {
|
||||
log_warn("Kernel not configured for semaphores (System V IPC). "
|
||||
"Not using udev synchronisation code.");
|
||||
"Not using udev synchronization code.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2334,7 +2341,7 @@ static int _check_udev_is_running(void)
|
||||
|
||||
if (!(r = udev_queue_get_udev_is_active(udev_queue)))
|
||||
log_debug_activation("Udev is not running. "
|
||||
"Not using udev synchronisation code.");
|
||||
"Not using udev synchronization code.");
|
||||
|
||||
udev_queue_unref(udev_queue);
|
||||
udev_unref(udev);
|
||||
@@ -2409,7 +2416,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;
|
||||
@@ -2430,20 +2437,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;
|
||||
}
|
||||
@@ -2453,23 +2460,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;
|
||||
@@ -2477,9 +2482,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;
|
||||
}
|
||||
|
||||
@@ -2556,7 +2564,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);
|
||||
@@ -2564,9 +2572,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;
|
||||
}
|
||||
|
||||
|
@@ -70,12 +70,11 @@ 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);
|
||||
|
||||
static const int _sep = '/';
|
||||
|
||||
#define MAX_INDENT 32
|
||||
|
||||
#define match(t) do {\
|
||||
@@ -86,14 +85,19 @@ static const int _sep = '/';
|
||||
} \
|
||||
} 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 != *b)
|
||||
return 0;
|
||||
if (!*str)
|
||||
return 0;
|
||||
++str;
|
||||
++b;
|
||||
}
|
||||
|
||||
return !(*str || (b != e));
|
||||
return !*str; /* token is matching for \0 end */
|
||||
}
|
||||
|
||||
struct dm_config_tree *dm_config_create(void)
|
||||
@@ -177,19 +181,18 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
|
||||
{
|
||||
/* TODO? if (start == end) return 1; */
|
||||
|
||||
struct parser *p;
|
||||
if (!(p = dm_pool_zalloc(cft->mem, sizeof(*p))))
|
||||
return_0;
|
||||
struct parser p = {
|
||||
.mem = cft->mem,
|
||||
.tb = start,
|
||||
.te = start,
|
||||
.fb = start,
|
||||
.fe = end,
|
||||
.line = 1,
|
||||
.no_dup_node_check = no_dup_node_check
|
||||
};
|
||||
|
||||
p->mem = cft->mem;
|
||||
p->fb = start;
|
||||
p->fe = end;
|
||||
p->tb = p->te = p->fb;
|
||||
p->line = 1;
|
||||
p->no_dup_node_check = no_dup_node_check;
|
||||
|
||||
_get_token(p, TOK_SECTION_E);
|
||||
if (!(cft->root = _file(p)))
|
||||
_get_token(&p, TOK_SECTION_E);
|
||||
if (!(cft->root = _file(&p)))
|
||||
return_0;
|
||||
|
||||
cft->root = _config_reverse(cft->root);
|
||||
@@ -470,23 +473,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;
|
||||
}
|
||||
@@ -508,10 +521,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;
|
||||
@@ -526,17 +538,18 @@ static struct dm_config_node *_find_or_make_node(struct dm_pool *mem,
|
||||
const char *path,
|
||||
int no_dup_node_check)
|
||||
{
|
||||
const int sep = '/';
|
||||
const char *e;
|
||||
struct dm_config_node *cn = parent ? parent->child : NULL;
|
||||
struct dm_config_node *cn_found = NULL;
|
||||
|
||||
while (cn || mem) {
|
||||
/* trim any leading slashes */
|
||||
while (*path && (*path == _sep))
|
||||
while (*path && (*path == sep))
|
||||
path++;
|
||||
|
||||
/* find the end of this segment */
|
||||
for (e = path; *e && (*e != _sep); e++) ;
|
||||
for (e = path; *e && (*e != sep); e++) ;
|
||||
|
||||
/* hunt for the node */
|
||||
cn_found = NULL;
|
||||
@@ -671,16 +684,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 */
|
||||
@@ -701,6 +712,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 */
|
||||
@@ -712,31 +725,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:
|
||||
@@ -744,6 +757,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;
|
||||
}
|
||||
|
||||
@@ -885,16 +904,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;
|
||||
}
|
||||
|
||||
@@ -910,9 +932,46 @@ 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);
|
||||
if (str_len)
|
||||
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);
|
||||
if (key_len)
|
||||
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)
|
||||
@@ -1329,19 +1388,19 @@ 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)))) {
|
||||
|
||||
}
|
||||
} 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;
|
||||
@@ -1358,16 +1417,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))) ||
|
||||
@@ -1387,14 +1441,11 @@ struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const c
|
||||
{
|
||||
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;
|
||||
|
||||
|
@@ -171,7 +171,7 @@ struct load_segment {
|
||||
uint32_t region_size; /* Mirror + raid */
|
||||
unsigned clustered; /* Mirror */
|
||||
unsigned mirror_area_count; /* Mirror */
|
||||
uint32_t flags; /* Mirror + raid + Cache */
|
||||
uint64_t flags; /* Mirror + Raid + Cache */
|
||||
char *uuid; /* Clustered mirror log */
|
||||
|
||||
const char *policy_name; /* 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 */
|
||||
@@ -348,7 +348,7 @@ struct dm_tree {
|
||||
int retry_remove; /* 1 retries remove if not successful */
|
||||
uint32_t cookie;
|
||||
char buf[DM_NAME_LEN + 32]; /* print buffer for device_name (major:minor) */
|
||||
const char **optional_uuid_suffixes; /* uuid suffixes ignored when matching */
|
||||
const char * const *optional_uuid_suffixes; /* uuid suffixes ignored when matching */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -590,6 +590,7 @@ void dm_tree_set_optional_uuid_suffixes(struct dm_tree *dtree, const char **opti
|
||||
dtree->optional_uuid_suffixes = optional_uuid_suffixes;
|
||||
}
|
||||
|
||||
static const char *_node_name(struct dm_tree_node *dnode);
|
||||
static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
|
||||
const char *uuid)
|
||||
{
|
||||
@@ -597,28 +598,26 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
|
||||
const char *default_uuid_prefix;
|
||||
size_t default_uuid_prefix_len;
|
||||
const char *suffix, *suffix_position;
|
||||
char uuid_without_suffix[DM_UUID_LEN];
|
||||
char uuid_without_suffix[DM_UUID_LEN + 1];
|
||||
unsigned i = 0;
|
||||
const char **suffix_list = dtree->optional_uuid_suffixes;
|
||||
const char * const *suffix_list = dtree->optional_uuid_suffixes;
|
||||
|
||||
if ((node = dm_hash_lookup(dtree->uuids, uuid))) {
|
||||
log_debug("Matched uuid %s in deptree.", uuid);
|
||||
log_debug_activation("Matched uuid %s %s in deptree.", uuid, _node_name(node));
|
||||
return node;
|
||||
}
|
||||
|
||||
default_uuid_prefix = dm_uuid_prefix();
|
||||
default_uuid_prefix_len = strlen(default_uuid_prefix);
|
||||
|
||||
if (suffix_list && (suffix_position = strrchr(uuid, '-'))) {
|
||||
while ((suffix = suffix_list[i++])) {
|
||||
if (strcmp(suffix_position + 1, suffix))
|
||||
continue;
|
||||
|
||||
(void) strncpy(uuid_without_suffix, uuid, sizeof(uuid_without_suffix));
|
||||
dm_strncpy(uuid_without_suffix, uuid, sizeof(uuid_without_suffix));
|
||||
uuid_without_suffix[suffix_position - uuid] = '\0';
|
||||
|
||||
if ((node = dm_hash_lookup(dtree->uuids, uuid_without_suffix))) {
|
||||
log_debug("Matched uuid %s (missing suffix -%s) in deptree.", uuid_without_suffix, suffix);
|
||||
log_debug_activation("Matched uuid %s %s (missing suffix -%s) in deptree.",
|
||||
uuid_without_suffix, _node_name(node), suffix);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -626,15 +625,17 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
|
||||
};
|
||||
}
|
||||
|
||||
if (strncmp(uuid, default_uuid_prefix, default_uuid_prefix_len))
|
||||
return NULL;
|
||||
default_uuid_prefix = dm_uuid_prefix();
|
||||
default_uuid_prefix_len = strlen(default_uuid_prefix);
|
||||
|
||||
if ((node = dm_hash_lookup(dtree->uuids, uuid + default_uuid_prefix_len))) {
|
||||
log_debug("Matched uuid %s (missing prefix) in deptree.", uuid + default_uuid_prefix_len);
|
||||
if ((strncmp(uuid, default_uuid_prefix, default_uuid_prefix_len) == 0) &&
|
||||
(node = dm_hash_lookup(dtree->uuids, uuid + default_uuid_prefix_len))) {
|
||||
log_debug_activation("Matched uuid %s %s (missing prefix) in deptree.",
|
||||
uuid + default_uuid_prefix_len, _node_name(node));
|
||||
return node;
|
||||
}
|
||||
|
||||
log_debug("Not matched uuid %s in deptree.", uuid);
|
||||
log_debug_activation("Not matched uuid %s in deptree.", uuid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -967,7 +968,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;
|
||||
|
||||
@@ -1815,7 +1816,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
|
||||
@@ -2181,7 +2182,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.
|
||||
*/
|
||||
@@ -2273,7 +2274,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;\
|
||||
@@ -2867,6 +2868,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,
|
||||
@@ -2886,7 +2889,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);
|
||||
@@ -2903,6 +2906,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;
|
||||
|
||||
@@ -2964,7 +2970,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))) {
|
||||
@@ -3376,7 +3382,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;
|
||||
|
||||
@@ -3812,7 +3818,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,
|
||||
@@ -3863,7 +3869,7 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
|
||||
{
|
||||
struct dm_config_node *cn;
|
||||
struct load_segment *seg;
|
||||
static const uint64_t _modemask =
|
||||
const uint64_t modemask =
|
||||
DM_CACHE_FEATURE_PASSTHROUGH |
|
||||
DM_CACHE_FEATURE_WRITETHROUGH |
|
||||
DM_CACHE_FEATURE_WRITEBACK;
|
||||
@@ -3875,12 +3881,12 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (feature_flags & _modemask) {
|
||||
switch (feature_flags & modemask) {
|
||||
case DM_CACHE_FEATURE_PASSTHROUGH:
|
||||
case DM_CACHE_FEATURE_WRITEBACK:
|
||||
if (strcmp(policy_name, "cleaner") == 0) {
|
||||
/* Enforce writethrough mode for cleaner policy */
|
||||
feature_flags = ~_modemask;
|
||||
feature_flags = ~modemask;
|
||||
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
|
||||
}
|
||||
/* Fall through */
|
||||
@@ -4076,7 +4082,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;
|
||||
}
|
||||
|
||||
@@ -4363,6 +4369,12 @@ int dm_tree_node_set_thin_external_origin(struct dm_tree_node *node,
|
||||
|
||||
seg->external = external;
|
||||
|
||||
if (!external->info.minor) {
|
||||
log_debug_activation("Delaying resume for new external origin %s.",
|
||||
external->name);
|
||||
external->props.delay_resume_if_new = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -223,7 +223,6 @@ retry_fcntl:
|
||||
}
|
||||
|
||||
/* coverity[leaked_handle] intentional leak of fd handle here */
|
||||
|
||||
return 1;
|
||||
|
||||
fail_close_unlink:
|
||||
|
@@ -153,7 +153,7 @@ struct op_def {
|
||||
* shorter one if one is a prefix of another!
|
||||
* (e.g. =~ comes before =)
|
||||
*/
|
||||
static struct op_def _op_cmp[] = {
|
||||
static const struct op_def _op_cmp[] = {
|
||||
{ "=~", FLD_CMP_REGEX, "Matching regular expression. [regex]" },
|
||||
{ "!~", FLD_CMP_REGEX|FLD_CMP_NOT, "Not matching regular expression. [regex]" },
|
||||
{ "=", FLD_CMP_EQUAL, "Equal to. [number, size, percent, string, string list, time]" },
|
||||
@@ -187,7 +187,7 @@ static struct op_def _op_cmp[] = {
|
||||
#define SEL_LIST_SUBSET_LS 0x00040000
|
||||
#define SEL_LIST_SUBSET_LE 0x00080000
|
||||
|
||||
static struct op_def _op_log[] = {
|
||||
static const struct op_def _op_log[] = {
|
||||
{ "&&", SEL_AND, "All fields must match" },
|
||||
{ ",", SEL_AND, "All fields must match" },
|
||||
{ "||", SEL_OR, "At least one field must match" },
|
||||
@@ -459,7 +459,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"
|
||||
@@ -796,11 +796,11 @@ static const char *_get_field_type_name(unsigned field_type)
|
||||
static size_t _get_longest_field_id_len(const struct dm_report_field_type *fields)
|
||||
{
|
||||
uint32_t f;
|
||||
size_t id_len = 0;
|
||||
size_t l, id_len = 0;
|
||||
|
||||
for (f = 0; fields[f].report_fn; f++)
|
||||
if (strlen(fields[f].id) > id_len)
|
||||
id_len = strlen(fields[f].id);
|
||||
if ((l = strlen(fields[f].id)) > id_len)
|
||||
id_len = l;
|
||||
|
||||
return id_len;
|
||||
}
|
||||
@@ -811,16 +811,17 @@ static void _display_fields_more(struct dm_report *rh,
|
||||
int display_field_types)
|
||||
{
|
||||
uint32_t f;
|
||||
size_t l;
|
||||
const struct dm_report_object_type *type;
|
||||
const char *desc, *last_desc = "";
|
||||
|
||||
for (f = 0; fields[f].report_fn; f++)
|
||||
if (strlen(fields[f].id) > id_len)
|
||||
id_len = strlen(fields[f].id);
|
||||
if ((l = strlen(fields[f].id)) > id_len)
|
||||
id_len = l;
|
||||
|
||||
for (type = rh->types; type->data_fn; type++)
|
||||
if (strlen(type->prefix) + 3 > id_len)
|
||||
id_len = strlen(type->prefix) + 3;
|
||||
if ((l = strlen(type->prefix) + 3) > id_len)
|
||||
id_len = l;
|
||||
|
||||
for (f = 0; fields[f].report_fn; f++) {
|
||||
if (!(type = _find_type(rh, fields[f].type))) {
|
||||
@@ -964,16 +965,13 @@ static int _get_canonical_field_name(const char *field,
|
||||
* Both names are always null-terminated.
|
||||
*/
|
||||
static int _is_same_field(const char *canonical_name1, const char *canonical_name2,
|
||||
const char *prefix)
|
||||
const char *prefix, size_t prefix_len)
|
||||
{
|
||||
size_t prefix_len;
|
||||
|
||||
/* Exact match? */
|
||||
if (!strcasecmp(canonical_name1, canonical_name2))
|
||||
return 1;
|
||||
|
||||
/* Match including prefix? */
|
||||
prefix_len = strlen(prefix) - 1;
|
||||
if (!strncasecmp(prefix, canonical_name1, prefix_len) &&
|
||||
!strcasecmp(canonical_name1 + prefix_len, canonical_name2))
|
||||
return 1;
|
||||
@@ -1049,6 +1047,7 @@ static int _get_field(struct dm_report *rh, const char *field, size_t flen,
|
||||
{
|
||||
char field_canon[DM_REPORT_FIELD_TYPE_ID_LEN];
|
||||
uint32_t f;
|
||||
size_t prefix_len;
|
||||
|
||||
if (!flen)
|
||||
return 0;
|
||||
@@ -1056,8 +1055,9 @@ static int _get_field(struct dm_report *rh, const char *field, size_t flen,
|
||||
if (!_get_canonical_field_name(field, flen, field_canon, sizeof(field_canon), NULL))
|
||||
return_0;
|
||||
|
||||
prefix_len = strlen(rh->field_prefix) - 1;
|
||||
for (f = 0; _implicit_report_fields[f].report_fn; f++) {
|
||||
if (_is_same_field(_implicit_report_fields[f].id, field_canon, rh->field_prefix)) {
|
||||
if (_is_same_field(_implicit_report_fields[f].id, field_canon, rh->field_prefix, prefix_len)) {
|
||||
*f_ret = f;
|
||||
*implicit = 1;
|
||||
return 1;
|
||||
@@ -1065,7 +1065,7 @@ static int _get_field(struct dm_report *rh, const char *field, size_t flen,
|
||||
}
|
||||
|
||||
for (f = 0; rh->fields[f].report_fn; f++) {
|
||||
if (_is_same_field(rh->canonical_field_ids[f], field_canon, rh->field_prefix)) {
|
||||
if (_is_same_field(rh->canonical_field_ids[f], field_canon, rh->field_prefix, prefix_len)) {
|
||||
*f_ret = f;
|
||||
*implicit = 0;
|
||||
return 1;
|
||||
@@ -1146,7 +1146,7 @@ static int _add_sort_key(struct dm_report *rh, uint32_t field_num, int implicit,
|
||||
static int _key_match(struct dm_report *rh, const char *key, size_t len,
|
||||
unsigned report_type_only)
|
||||
{
|
||||
char key_canon[DM_REPORT_FIELD_TYPE_ID_LEN];
|
||||
int implicit;
|
||||
uint32_t f;
|
||||
uint32_t flags;
|
||||
|
||||
@@ -1169,16 +1169,8 @@ static int _key_match(struct dm_report *rh, const char *key, size_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_get_canonical_field_name(key, len, key_canon, sizeof(key_canon), NULL))
|
||||
return_0;
|
||||
|
||||
for (f = 0; _implicit_report_fields[f].report_fn; f++)
|
||||
if (_is_same_field(_implicit_report_fields[f].id, key_canon, rh->field_prefix))
|
||||
return _add_sort_key(rh, f, 1, flags, report_type_only);
|
||||
|
||||
for (f = 0; rh->fields[f].report_fn; f++)
|
||||
if (_is_same_field(rh->canonical_field_ids[f], key_canon, rh->field_prefix))
|
||||
return _add_sort_key(rh, f, 0, flags, report_type_only);
|
||||
if (_get_field(rh, key, len, &f, &implicit))
|
||||
return _add_sort_key(rh, f, implicit, flags, report_type_only);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1404,7 +1396,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);
|
||||
|
||||
@@ -1461,9 +1453,14 @@ static void *_report_get_field_data(struct dm_report *rh,
|
||||
const struct dm_report_field_type *fields = fp->implicit ? _implicit_report_fields
|
||||
: rh->fields;
|
||||
|
||||
char *ret = fp->type->data_fn(object);
|
||||
char *ret;
|
||||
|
||||
if (!ret)
|
||||
if (!object) {
|
||||
log_error(INTERNAL_ERROR "_report_get_field_data: missing object.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(ret = fp->type->data_fn(object)))
|
||||
return NULL;
|
||||
|
||||
return (void *)(ret + fields[fp->field_num].offset);
|
||||
@@ -2264,7 +2261,7 @@ static const char * _skip_space(const char *s)
|
||||
return s;
|
||||
}
|
||||
|
||||
static int _tok_op(struct op_def *t, const char *s, const char **end,
|
||||
static int _tok_op(const struct op_def *t, const char *s, const char **end,
|
||||
uint32_t expect)
|
||||
{
|
||||
size_t len;
|
||||
@@ -2433,7 +2430,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);
|
||||
}
|
||||
@@ -2505,7 +2502,7 @@ float dm_percent_to_float(dm_percent_t percent)
|
||||
|
||||
float dm_percent_to_round_float(dm_percent_t percent, unsigned digits)
|
||||
{
|
||||
static const float power10[] = {
|
||||
const float power10[] = {
|
||||
1.f, .1f, .01f, .001f, .0001f, .00001f, .000001f,
|
||||
.0000001f, .00000001f, .000000001f,
|
||||
.0000000001f
|
||||
@@ -2571,12 +2568,12 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
|
||||
const struct dm_report_reserved_value *iter;
|
||||
const struct dm_report_field_reserved_value *field_res;
|
||||
const struct dm_report_field_type *field;
|
||||
static uint32_t supported_reserved_types = DM_REPORT_FIELD_TYPE_NUMBER |
|
||||
const uint32_t supported_reserved_types = DM_REPORT_FIELD_TYPE_NUMBER |
|
||||
DM_REPORT_FIELD_TYPE_SIZE |
|
||||
DM_REPORT_FIELD_TYPE_PERCENT |
|
||||
DM_REPORT_FIELD_TYPE_STRING |
|
||||
DM_REPORT_FIELD_TYPE_TIME;
|
||||
static uint32_t supported_reserved_types_with_range = DM_REPORT_FIELD_RESERVED_VALUE_RANGE |
|
||||
const uint32_t supported_reserved_types_with_range = DM_REPORT_FIELD_RESERVED_VALUE_RANGE |
|
||||
DM_REPORT_FIELD_TYPE_NUMBER |
|
||||
DM_REPORT_FIELD_TYPE_SIZE |
|
||||
DM_REPORT_FIELD_TYPE_PERCENT |
|
||||
@@ -2592,7 +2589,8 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
|
||||
if (iter->type & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
if (!(iter->type & supported_reserved_types) ||
|
||||
((iter->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE) &&
|
||||
!(iter->type & supported_reserved_types_with_range))) {
|
||||
!(iter->type & (supported_reserved_types_with_range &
|
||||
~DM_REPORT_FIELD_RESERVED_VALUE_RANGE)))) {
|
||||
log_error(INTERNAL_ERROR "_check_reserved_values_supported: "
|
||||
"global reserved value for type 0x%x not supported",
|
||||
iter->type);
|
||||
@@ -2602,8 +2600,9 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
|
||||
field_res = (const struct dm_report_field_reserved_value *) iter->value;
|
||||
field = &fields[field_res->field_num];
|
||||
if (!(field->flags & supported_reserved_types) ||
|
||||
((iter->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE) &&
|
||||
!(iter->type & supported_reserved_types_with_range))) {
|
||||
((field->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE) &&
|
||||
!(field->type & (supported_reserved_types_with_range &
|
||||
~DM_REPORT_FIELD_RESERVED_VALUE_RANGE)))) {
|
||||
log_error(INTERNAL_ERROR "_check_reserved_values_supported: "
|
||||
"field-specific reserved value of type 0x%x for "
|
||||
"field %s not supported",
|
||||
@@ -2843,7 +2842,7 @@ struct time_value {
|
||||
time_t t2;
|
||||
};
|
||||
|
||||
static const char *_out_of_range_msg = "Field selection value %s out of supported range for field %s.";
|
||||
static const char _out_of_range_msg[] = "Field selection value %s out of supported range for field %s.";
|
||||
|
||||
/*
|
||||
* Standard formatted date and time - ISO8601.
|
||||
@@ -2868,7 +2867,7 @@ static const char *_out_of_range_msg = "Field selection value %s out of supporte
|
||||
#define DELIM_DATE '-'
|
||||
#define DELIM_TIME ':'
|
||||
|
||||
static int _days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
static const int _days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
static int _is_leap_year(long year)
|
||||
{
|
||||
@@ -2893,7 +2892,6 @@ typedef enum {
|
||||
|
||||
static char *_get_date(char *str, struct tm *tm, time_range_t *range)
|
||||
{
|
||||
static const char incorrect_date_format_msg[] = "Incorrect date format.";
|
||||
time_range_t tmp_range = RANGE_NONE;
|
||||
long n1, n2 = -1, n3 = -1;
|
||||
char *s = str, *end;
|
||||
@@ -2939,19 +2937,15 @@ static char *_get_date(char *str, struct tm *tm, time_range_t *range)
|
||||
n3 = n1 % 100;
|
||||
n2 = (n1 / 100) % 100;
|
||||
n1 = n1 / 10000;
|
||||
} else {
|
||||
log_error(incorrect_date_format_msg);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
goto_bad;
|
||||
} else {
|
||||
if (len == 7) {
|
||||
tmp_range = RANGE_MONTH;
|
||||
/* YYYY-MM */
|
||||
n3 = 1;
|
||||
} else {
|
||||
log_error(incorrect_date_format_msg);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
goto_bad;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2974,11 +2968,15 @@ static char *_get_date(char *str, struct tm *tm, time_range_t *range)
|
||||
*range = tmp_range;
|
||||
|
||||
return (char *) _skip_space(end);
|
||||
|
||||
bad:
|
||||
log_error("Incorrect date format.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *_get_time(char *str, struct tm *tm, time_range_t *range)
|
||||
{
|
||||
static const char incorrect_time_format_msg[] = "Incorrect time format.";
|
||||
time_range_t tmp_range = RANGE_NONE;
|
||||
long n1, n2 = -1, n3 = -1;
|
||||
char *s = str, *end;
|
||||
@@ -3026,19 +3024,15 @@ static char *_get_time(char *str, struct tm *tm, time_range_t *range)
|
||||
n3 = n1 % 100;
|
||||
n2 = (n1 / 100) % 100;
|
||||
n1 = n1 / 10000;
|
||||
} else {
|
||||
log_error(incorrect_time_format_msg);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
goto_bad;
|
||||
} else {
|
||||
if (len == 5) {
|
||||
/* HH:MM */
|
||||
tmp_range = RANGE_MINUTE;
|
||||
n3 = 0;
|
||||
} else {
|
||||
log_error(incorrect_time_format_msg);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
goto_bad;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3069,6 +3063,11 @@ static char *_get_time(char *str, struct tm *tm, time_range_t *range)
|
||||
*range = tmp_range;
|
||||
|
||||
return (char *) _skip_space(end);
|
||||
|
||||
bad:
|
||||
log_error("Incorrect time format.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The offset is always an absolute offset against GMT! */
|
||||
@@ -3497,7 +3496,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;
|
||||
@@ -3517,7 +3516,6 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
struct reserved_value_wrapper *rvw,
|
||||
void *custom)
|
||||
{
|
||||
static const char *_field_selection_value_alloc_failed_msg = "dm_report: struct field_selection_value allocation failed for selection field %s";
|
||||
const struct dm_report_field_type *fields = implicit ? _implicit_report_fields
|
||||
: rh->fields;
|
||||
struct field_properties *fp, *found = NULL;
|
||||
@@ -3565,8 +3563,8 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
}
|
||||
|
||||
if (!(fs->value = dm_pool_zalloc(rh->selection->mem, sizeof(struct field_selection_value)))) {
|
||||
log_error(_field_selection_value_alloc_failed_msg, field_id);
|
||||
goto error;
|
||||
stack;
|
||||
goto error_field_id;
|
||||
}
|
||||
|
||||
if (((rvw->reserved && (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)) ||
|
||||
@@ -3574,8 +3572,8 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
custom && ((struct time_value *) custom)->range))
|
||||
&&
|
||||
!(fs->value->next = dm_pool_zalloc(rh->selection->mem, sizeof(struct field_selection_value)))) {
|
||||
log_error(_field_selection_value_alloc_failed_msg, field_id);
|
||||
goto error;
|
||||
stack;
|
||||
goto error_field_id;
|
||||
}
|
||||
|
||||
fs->fp = found;
|
||||
@@ -3724,8 +3722,12 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
}
|
||||
|
||||
return fs;
|
||||
error_field_id:
|
||||
log_error("dm_report: struct field_selection_value allocation failed for selection field %s",
|
||||
field_id);
|
||||
goto error;
|
||||
bad:
|
||||
log_error(INTERNAL_ERROR "Forbiden NULL custom detected.");
|
||||
log_error(INTERNAL_ERROR "Forbidden NULL custom detected.");
|
||||
error:
|
||||
dm_pool_free(rh->selection->mem, fs);
|
||||
|
||||
@@ -3752,7 +3754,7 @@ static struct selection_node *_alloc_selection_node(struct dm_pool *mem, uint32_
|
||||
static void _display_selection_help(struct dm_report *rh)
|
||||
{
|
||||
static const char _grow_object_failed_msg[] = "_display_selection_help: dm_pool_grow_object failed";
|
||||
struct op_def *t;
|
||||
const struct op_def *t;
|
||||
const struct dm_report_reserved_value *rv;
|
||||
size_t len_all, len_final = 0;
|
||||
const char **rvs;
|
||||
@@ -4023,7 +4025,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,
|
||||
@@ -4105,7 +4107,7 @@ static int _alloc_rh_selection(struct dm_report *rh)
|
||||
static int _report_set_selection(struct dm_report *rh, const char *selection, int add_new_fields)
|
||||
{
|
||||
struct selection_node *root = NULL;
|
||||
const char *fin, *next;
|
||||
const char *fin = NULL, *next;
|
||||
|
||||
if (rh->selection) {
|
||||
if (rh->selection->selection_root)
|
||||
@@ -4125,7 +4127,7 @@ static int _report_set_selection(struct dm_report *rh, const char *selection, in
|
||||
if (!(root = _alloc_selection_node(rh->selection->mem, SEL_OR)))
|
||||
return 0;
|
||||
|
||||
if (!_parse_or_ex(rh, selection, &fin, root))
|
||||
if (!_parse_or_ex(rh, selection, &fin, root) || !fin)
|
||||
goto_bad;
|
||||
|
||||
next = _skip_space(fin);
|
||||
@@ -4263,7 +4265,9 @@ static int _report_headings(struct dm_report *rh)
|
||||
|
||||
fields = fp->implicit ? _implicit_report_fields : rh->fields;
|
||||
|
||||
heading = fields[fp->field_num].heading;
|
||||
heading = rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS ?
|
||||
fields[fp->field_num].id : fields[fp->field_num].heading;
|
||||
|
||||
if (rh->flags & DM_REPORT_OUTPUT_ALIGNED) {
|
||||
if (dm_snprintf(buf, buf_size, "%-*.*s",
|
||||
fp->width, fp->width, heading) < 0) {
|
||||
@@ -4315,6 +4319,7 @@ static void _recalculate_fields(struct dm_report *rh)
|
||||
struct row *row;
|
||||
struct dm_report_field *field;
|
||||
int len;
|
||||
int id_len;
|
||||
|
||||
dm_list_iterate_items(row, &rh->rows) {
|
||||
dm_list_iterate_items(field, &row->fields) {
|
||||
@@ -4329,6 +4334,12 @@ static void _recalculate_fields(struct dm_report *rh)
|
||||
field->props->width = len;
|
||||
|
||||
}
|
||||
|
||||
if (rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS) {
|
||||
id_len = (int) strlen(rh->fields[field->props->field_num].id);
|
||||
if (field->props->width < id_len)
|
||||
field->props->width = id_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4415,8 +4426,9 @@ static int _sort_rows(struct dm_report *rh)
|
||||
qsort(rows, count, sizeof(**rows), _row_compare);
|
||||
|
||||
dm_list_init(&rh->rows);
|
||||
while (count--)
|
||||
dm_list_add_h(&rh->rows, &(*rows)[count]->list);
|
||||
|
||||
while (count > 0)
|
||||
dm_list_add_h(&rh->rows, &(*rows)[--count]->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -4740,10 +4752,13 @@ static int _output_as_rows(struct dm_report *rh)
|
||||
struct field_properties *fp;
|
||||
struct dm_report_field *field;
|
||||
struct row *row;
|
||||
const char *heading;
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -4758,7 +4773,10 @@ static int _output_as_rows(struct dm_report *rh)
|
||||
}
|
||||
|
||||
if ((rh->flags & DM_REPORT_OUTPUT_HEADINGS)) {
|
||||
if (!dm_pool_grow_object(rh->mem, fields[fp->field_num].heading, 0)) {
|
||||
heading = rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS ?
|
||||
fields[fp->field_num].id : fields[fp->field_num].heading;
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, heading, 0)) {
|
||||
log_error("dm_report: Failed to extend row for field name");
|
||||
goto bad;
|
||||
}
|
||||
@@ -4798,12 +4816,36 @@ static int _output_as_rows(struct dm_report *rh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dm_list *_get_last_displayed_rowh(struct dm_report *rh)
|
||||
{
|
||||
struct dm_list *rowh;
|
||||
struct row *row;
|
||||
|
||||
/*
|
||||
* We need to find 'last displayed row', not just 'last row'.
|
||||
*
|
||||
* This is because the report may be marked with
|
||||
* DM_REPORT_OUTPUT_MULTIPLE_TIMES flag. In that case, the report
|
||||
* may be used more than once and with different selection
|
||||
* criteria each time. Therefore, such report may also contain
|
||||
* rows which we do not display on output with current selection
|
||||
* criteria.
|
||||
*/
|
||||
for (rowh = dm_list_last(&rh->rows); rowh; rowh = dm_list_prev(&rh->rows, rowh)) {
|
||||
row = dm_list_item(rowh, struct row);
|
||||
if (_should_display_row(row))
|
||||
return rowh;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _output_as_columns(struct dm_report *rh)
|
||||
{
|
||||
struct dm_list *fh, *rowh, *ftmp, *rtmp;
|
||||
struct row *row = NULL;
|
||||
struct dm_report_field *field;
|
||||
struct dm_list *last_row;
|
||||
struct dm_list *last_rowh;
|
||||
int do_field_delim;
|
||||
char *line;
|
||||
|
||||
@@ -4812,7 +4854,7 @@ static int _output_as_columns(struct dm_report *rh)
|
||||
_report_headings(rh);
|
||||
|
||||
/* Print and clear buffer */
|
||||
last_row = dm_list_last(&rh->rows);
|
||||
last_rowh = _get_last_displayed_rowh(rh);
|
||||
dm_list_iterate_safe(rowh, rtmp, &rh->rows) {
|
||||
row = dm_list_item(rowh, struct row);
|
||||
|
||||
@@ -4866,7 +4908,7 @@ static int _output_as_columns(struct dm_report *rh)
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
}
|
||||
if (rowh != last_row &&
|
||||
if (rowh != last_rowh &&
|
||||
!dm_pool_grow_object(rh->mem, JSON_SEPARATOR, 0)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
goto bad;
|
||||
@@ -5063,7 +5105,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;
|
||||
}
|
||||
|
||||
|
@@ -192,7 +192,7 @@ int dm_asprintf(char **result, const char *format, ...)
|
||||
}
|
||||
|
||||
/*
|
||||
* Count occurences of 'c' in 'str' until we reach a null char.
|
||||
* Count occurrences of 'c' in 'str' until we reach a null char.
|
||||
*
|
||||
* Returns:
|
||||
* len - incremented for each char we encounter.
|
||||
@@ -385,7 +385,7 @@ char *dm_build_dm_uuid(struct dm_pool *mem, const char *uuid_prefix, const char
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(dmuuid, "%s%s%s%s", uuid_prefix, lvid, (*layer) ? "-" : "", layer);
|
||||
snprintf(dmuuid, len, "%s%s%s%s", uuid_prefix, lvid, (*layer) ? "-" : "", layer);
|
||||
|
||||
return dmuuid;
|
||||
}
|
||||
@@ -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;
|
||||
sprintf(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;
|
||||
}
|
||||
|
||||
|
@@ -106,26 +106,31 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
|
||||
/* Second field holds the device count */
|
||||
msg_fields = "<#devs> ";
|
||||
if (!(p = _skip_fields(params, 1)) || (sscanf(p, "%d", &i) != 1))
|
||||
if (!(pp = _skip_fields(params, 1)) || (sscanf(pp, "%d", &i) != 1) || !(p = _skip_fields(pp, 1)))
|
||||
goto_bad;
|
||||
|
||||
msg_fields = "";
|
||||
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid))))
|
||||
goto_bad;
|
||||
|
||||
if (!(s->raid_type = dm_pool_zalloc(mem, p - params)))
|
||||
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
|
||||
if (!(s->raid_type = dm_pool_strndup(mem, params, pp - params - 1)))
|
||||
goto_bad; /* memory is freed when pool is destroyed */
|
||||
|
||||
if (!(s->dev_health = dm_pool_zalloc(mem, i + 1))) /* Space for health chars */
|
||||
if (!(pp = _skip_fields(p, 1)))
|
||||
goto_bad;
|
||||
|
||||
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
|
||||
if (sscanf(params, "%s %u %s " FMTu64 "/" FMTu64,
|
||||
s->raid_type,
|
||||
&s->dev_count,
|
||||
s->dev_health,
|
||||
&s->insync_regions,
|
||||
&s->total_regions) != 5)
|
||||
/* Raid target can actually report more then 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;
|
||||
|
||||
if (!(s->dev_health = dm_pool_strndup(mem, p, i))) /* health chars */
|
||||
goto_bad;
|
||||
p = pp;
|
||||
|
||||
s->dev_count = i;
|
||||
if (sscanf(p, FMTu64 "/" FMTu64, &s->insync_regions, &s->total_regions) != 2)
|
||||
goto_bad;
|
||||
|
||||
/*
|
||||
@@ -141,13 +146,13 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
msg_fields = "<sync_action> and <mismatch_cnt> ";
|
||||
|
||||
/* Skip pre-1.5.0 params */
|
||||
if (!(p = _skip_fields(params, 4)) || !(pp = _skip_fields(p, 1)))
|
||||
if (!(pp = _skip_fields(params, 4)) || !(p = _skip_fields(pp, 1)))
|
||||
goto_bad;
|
||||
|
||||
if (!(s->sync_action = dm_pool_zalloc(mem, pp - p)))
|
||||
if (!(s->sync_action = dm_pool_strndup(mem, pp, p - pp - 1)))
|
||||
goto_bad;
|
||||
|
||||
if (sscanf(p, "%s " FMTu64, s->sync_action, &s->mismatch_count) != 2)
|
||||
if (sscanf(p, FMTu64, &s->mismatch_count) != 1)
|
||||
goto_bad;
|
||||
|
||||
if (num_fields < 7)
|
||||
@@ -166,23 +171,35 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
if (sscanf(p, FMTu64, &s->data_offset) != 1)
|
||||
goto bad;
|
||||
|
||||
/* <journal_char> - 'A' - active write-through journal device.
|
||||
* - 'a' - active write-back journal device.
|
||||
* - 'D' - dead journal device.
|
||||
* - '-' - no journal device.
|
||||
*/
|
||||
|
||||
out:
|
||||
*status = s;
|
||||
|
||||
if (s->insync_regions == s->total_regions) {
|
||||
/* FIXME: kernel gives misleading info here
|
||||
* Trying to recognize a true state */
|
||||
while (i-- > 0)
|
||||
if (s->dev_health[i] == 'a')
|
||||
a++; /* Count number of 'a' */
|
||||
while (i-- > 0)
|
||||
if (s->dev_health[i] == 'a')
|
||||
a++; /* Count number of 'a' */
|
||||
|
||||
if (a && a < s->dev_count) {
|
||||
/* SOME legs are in 'a' */
|
||||
if (!strcasecmp(s->sync_action, "recover")
|
||||
|| !strcasecmp(s->sync_action, "idle"))
|
||||
/* Kernel may possibly start some action
|
||||
* in near-by future, do not report 100% */
|
||||
s->insync_regions--;
|
||||
if (a) {
|
||||
if ((a < s->dev_count) && /* SOME legs are in 'a' */
|
||||
/* FIXME: kernel gives misleading info here
|
||||
* Trying to recognize a true state */
|
||||
(s->insync_regions == s->total_regions) &&
|
||||
(!strcasecmp(s->sync_action, "recover") ||
|
||||
!strcasecmp(s->sync_action, "idle"))) {
|
||||
/* Kernel may possibly start some action
|
||||
* in near-by future, do not report 100% */
|
||||
s->insync_regions--;
|
||||
}
|
||||
if ((a == s->dev_count) && /* all legs are in 'a' */
|
||||
(!strcasecmp(s->sync_action, "resync") ||
|
||||
!strcasecmp(s->sync_action, "idle"))) {
|
||||
/* Mark 1st. leg in sync */
|
||||
s->dev_health[0] = 'A';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,6 +528,21 @@ int dm_get_status_thin(struct dm_pool *mem, const char *params,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static dm_status_mirror_health_t _get_health(char c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'A': return DM_STATUS_MIRROR_ALIVE;
|
||||
case 'F': return DM_STATUS_MIRROR_FLUSH_FAILED;
|
||||
case 'D': return DM_STATUS_MIRROR_WRITE_FAILED;
|
||||
case 'S': return DM_STATUS_MIRROR_SYNC_FAILED;
|
||||
case 'R': return DM_STATUS_MIRROR_READ_FAILED;
|
||||
default:
|
||||
log_warn("WARNING: Unknown mirror health status char: %c", c);
|
||||
/* fall through */
|
||||
case 'U': return DM_STATUS_MIRROR_UNCLASSIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dm core parms: 0 409600 mirror
|
||||
* Mirror core parms: 2 253:4 253:5 400/400
|
||||
@@ -564,7 +596,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
|
||||
pos += used;
|
||||
|
||||
for (i = 0; i < num_devs ; ++i)
|
||||
s->devs[i].health = pos[i];
|
||||
s->devs[i].health = _get_health(pos[i]);
|
||||
|
||||
if (!(pos = _skip_fields(pos, argc)))
|
||||
goto_out;
|
||||
@@ -609,7 +641,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
|
||||
goto_out;
|
||||
|
||||
for (i = 0; i < s->log_count; ++i)
|
||||
s->logs[i].health = pos[i];
|
||||
s->logs[i].health = _get_health(pos[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -209,7 +209,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
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -81,7 +81,6 @@ struct dm_vdo_target_params {
|
||||
uint32_t block_map_era_length; // format period
|
||||
uint32_t block_map_period; // supported alias
|
||||
};
|
||||
uint32_t check_point_frequency;
|
||||
uint32_t index_memory_size_mb; // format
|
||||
|
||||
uint32_t slab_size_mb; // format
|
||||
|
@@ -128,7 +128,15 @@ struct vdo_volume_geometry {
|
||||
struct vdo_index_config index_config;
|
||||
} __packed;
|
||||
|
||||
/* Decoding mostly only some used stucture members */
|
||||
struct vdo_volume_geometry_4 {
|
||||
uint32_t release_version;
|
||||
uint64_t nonce;
|
||||
uuid_t uuid;
|
||||
struct vdo_volume_region regions[VDO_VOLUME_REGION_COUNT];
|
||||
struct vdo_index_config index_config;
|
||||
} __packed;
|
||||
|
||||
/* Decoding mostly only some used structure members */
|
||||
|
||||
static void _vdo_decode_version(struct vdo_version_number *v)
|
||||
{
|
||||
@@ -146,13 +154,24 @@ static void _vdo_decode_header(struct vdo_header *h)
|
||||
static void _vdo_decode_geometry_region(struct vdo_volume_region *vr)
|
||||
{
|
||||
vr->id = le32_to_cpu(vr->id);
|
||||
vr->start_block = le32_to_cpu(vr->start_block);
|
||||
vr->start_block = le64_to_cpu(vr->start_block);
|
||||
}
|
||||
|
||||
static void _vdo_decode_volume_geometry(struct vdo_volume_geometry *vg)
|
||||
{
|
||||
vg->release_version = le64_to_cpu(vg->release_version);
|
||||
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);
|
||||
_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->bio_offset = 0;
|
||||
vg->regions[VDO_DATA_REGION] = vg_4->regions[VDO_DATA_REGION];
|
||||
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
|
||||
}
|
||||
|
||||
@@ -174,9 +193,8 @@ static void _vdo_decode_pvc(struct vdo_component_41_0 *pvc)
|
||||
bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
{
|
||||
char buffer[4096];
|
||||
int fh, n;
|
||||
int fh;
|
||||
bool r = false;
|
||||
off_t l;
|
||||
struct stat st;
|
||||
uint64_t size;
|
||||
uint64_t regpos;
|
||||
@@ -184,6 +202,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
struct vdo_header h;
|
||||
struct vdo_version_number vn;
|
||||
struct vdo_volume_geometry vg;
|
||||
struct vdo_volume_geometry_4 vg_4;
|
||||
struct vdo_component_41_0 pvc;
|
||||
|
||||
*logical_blocks = 0;
|
||||
@@ -207,7 +226,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
size = st.st_size;
|
||||
}
|
||||
|
||||
if ((n = read(fh, buffer, sizeof(buffer))) < 0) {
|
||||
if (read(fh, buffer, sizeof(buffer)) < 0) {
|
||||
log_sys_debug("read", vdo_path);
|
||||
goto err;
|
||||
}
|
||||
@@ -220,32 +239,42 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
memcpy(&h, buffer + MAGIC_NUMBER_SIZE, sizeof(h));
|
||||
_vdo_decode_header(&h);
|
||||
|
||||
if (h.version.major_version != 5) {
|
||||
if (h.id != 5) {
|
||||
log_debug_activation("Expected geometry VDO block instead of block %u.", h.id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (h.version.major_version) {
|
||||
case 4:
|
||||
memcpy(&vg_4, buffer + MAGIC_NUMBER_SIZE + sizeof(h), sizeof(vg_4));
|
||||
_vdo_decode_volume_geometry_4(&vg, &vg_4);
|
||||
break;
|
||||
case 5:
|
||||
memcpy(&vg, buffer + MAGIC_NUMBER_SIZE + sizeof(h), sizeof(vg));
|
||||
_vdo_decode_volume_geometry(&vg);
|
||||
break;
|
||||
default:
|
||||
log_debug_activation("Unsupported VDO version %u.%u.", h.version.major_version, h.version.minor_version);
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(&vg, buffer + MAGIC_NUMBER_SIZE + sizeof(h), sizeof(vg));
|
||||
_vdo_decode_volume_geometry(&vg);
|
||||
|
||||
regpos = vg.regions[VDO_DATA_REGION].start_block * 4096;
|
||||
regpos = (vg.regions[VDO_DATA_REGION].start_block - vg.bio_offset) * 4096;
|
||||
|
||||
if ((regpos + sizeof(buffer)) > size) {
|
||||
log_debug_activation("File/Device is shorter and can't provide requested VDO volume region at " FMTu64 " > " FMTu64 ".", regpos, size);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((l = lseek(fh, regpos, SEEK_SET)) < 0) {
|
||||
if (lseek(fh, regpos, SEEK_SET) < 0) {
|
||||
log_sys_debug("lseek", vdo_path);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((n = read(fh, buffer, sizeof(buffer))) < 0) {
|
||||
if (read(fh, buffer, sizeof(buffer)) < 0) {
|
||||
log_sys_debug("read", vdo_path);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
memcpy(&vn, buffer + sizeof(struct vdo_geometry_block), sizeof(vn));
|
||||
_vdo_decode_version(&vn);
|
||||
|
||||
|
24
doc/Problems.mdwn
Normal file
24
doc/Problems.mdwn
Normal file
@@ -0,0 +1,24 @@
|
||||
# Common problems
|
||||
|
||||
## Duplicate PVs in the system
|
||||
|
||||
LVM tries to detect the common sources of duplicates, mdadm RAID and multipath,
|
||||
there are cases where duplicate PV appears on the system.
|
||||
|
||||
There are two solutions to this problem:
|
||||
|
||||
* Setting a *global_filter* configuration option.
|
||||
* Using of *devices_file* (See [lvmdevices(8)](https://man7.org/linux/man-pages/man8/lvmdevices.8.html))
|
||||
|
||||
## Device Filtering
|
||||
|
||||
*filter* and *global_filter* are meant to be used in two ways:
|
||||
|
||||
* as an allow list, listing patterns for devices which will be accepted
|
||||
* `a|/dev/sdX|`, and rejecting the rest `r|.*|`,
|
||||
* as a reject list, listing only patterns for devices which will be rejected
|
||||
* `r|/dev/sdX|`,
|
||||
|
||||
Even though there are situations where it works, mixing reject and accept
|
||||
patterns is not recommended.
|
||||
|
34
doc/README.mdwn
Normal file
34
doc/README.mdwn
Normal file
@@ -0,0 +1,34 @@
|
||||
LVM2 Wiki Documentation
|
||||
=======================
|
||||
|
||||
If you are looking for information about LVM2 visit the [[Index]] page,
|
||||
|
||||
There are only some notes about writing stuff under *./doc* here:
|
||||
|
||||
* If possible use [[MarkDown]] for formatting, use *.md* (or *.mdwn*) suffix.
|
||||
* For linking between files, use [[IkiWiki]] syntax `[[FileName]]` or
|
||||
`[[FileName#Anchor]]`, or `[[link text|FileName]]`
|
||||
|
||||
Markdown
|
||||
--------
|
||||
|
||||
* Use `<!-- comment -->` to keep notes, which will not be rendered.
|
||||
* Use `[[TODO]]` for anything what needs attention. This will be accessible
|
||||
through the linked [[TODO]] page.
|
||||
|
||||
IkiWiki
|
||||
-------
|
||||
|
||||
* Install ikiwiki:
|
||||
|
||||
yum install ikiwiki
|
||||
|
||||
* To generate the content, run following in the LVM2 top directory:
|
||||
|
||||
ikiwiki --setup ikiwiki.setup
|
||||
|
||||
Internal Stuff:
|
||||
---------------
|
||||
|
||||
* [[TODO]] Can we have a section which is hidden by default? Like this one?
|
||||
* [[TODO]] Add basic IkiWiki and MarkDown How To.
|
152
doc/index.mdwn
Normal file
152
doc/index.mdwn
Normal file
@@ -0,0 +1,152 @@
|
||||
# LVM - Logical Volume Manager for Linux
|
||||
|
||||
<!--
|
||||
* TODO: Add banner for Important News: Critical Bugs, Important Announcements,...
|
||||
-->
|
||||
|
||||
<!--
|
||||
* TODO: Add a feed for latest articles/release-notes on the right
|
||||
-->
|
||||
|
||||
<!--
|
||||
## About LVM2
|
||||
-->
|
||||
LVM aka LVM2 refers to the userspace toolset that provide logical volume
|
||||
management facilities on linux.
|
||||
<!--
|
||||
It is reasonably backwards-compatible with the
|
||||
original LVM1 toolset.
|
||||
* TODO: Add information about LVM1 metadata format conversion!
|
||||
-->
|
||||
|
||||
LVM offers more flexibility than using partitions, allowing one to
|
||||
|
||||
* grow and, where supported by filesystem, shrink volumes,
|
||||
* create snapshots of existing volumes,
|
||||
* mirror data on multiple disks including RAID levels 5 or 6,
|
||||
* striping data on multiple disks,
|
||||
* create a read or write cache.
|
||||
|
||||
To use LVM2 you need 3 things:
|
||||
|
||||
* [device-mapper](https://sourceware.org/dm/) in your kernel (upstream since long ago)
|
||||
* the userspace device-mapper support library (*libdevmapper*) (part of lvm2)
|
||||
* and the userspace LVM2 tools.
|
||||
|
||||
## Getting LVM
|
||||
|
||||
Most of linux distribution offer packaged LVM tools.
|
||||
Depending on your distribution use
|
||||
|
||||
# RPM based distributions (Fedora):
|
||||
yum install lvm2
|
||||
# DEB based distributions (Debian, Ubuntu):
|
||||
apt-get install lvm2
|
||||
|
||||
Tarballs of the userspace LVM2 source code releases are available from [sourceware.org](https://sourceware.org/pub/lvm2/) [ftp](ftp://sourceware.org/pub/lvm2/).
|
||||
|
||||
List of official [mirror sites](https://sourceware.org/mirrors.html) (including http and rsync protocols).
|
||||
|
||||
### LVM Releases
|
||||
|
||||
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
|
||||
|
||||
[[More releases|release-notes/index]]
|
||||
|
||||
## Getting Started
|
||||
|
||||
<!--
|
||||
TODO: We are missing a lvm(7) man page explaining this, I think it would be a nic addition!
|
||||
And perhaps so would be a lvmtroubleshooting(7) guide.
|
||||
-->
|
||||
Word of warning first! Even though LVM errs on the side of data safety it is a
|
||||
tool with low level access and one may seriously harm their data when used
|
||||
incorrectly!
|
||||
|
||||
|
||||
* 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
|
||||
[pvdisplay(8)](https://man7.org/linux/man-pages/man8/pvdisplay.8.html).
|
||||
|
||||
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 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).
|
||||
|
||||
Make one by running `vgcreate VGNAME /dev/sdX...`, add PVs to existing one by `vgextend VGNAME /dev/sdX`.
|
||||
To use LVM at least one Volume Group must be present on the system.
|
||||
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html), and
|
||||
[vgextend(8)](https://man7.org/linux/man-pages/man8/vgextend.8.html).
|
||||
* Logical Volume (LV) is the block device usually visible to user to be used for file system.
|
||||
List PVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
|
||||
[lvdisplay(8)](https://man7.org/linux/man-pages/man8/lvdisplay.8.html).
|
||||
|
||||
Make one by running `lvcreate [-n LVNAME] -L SIZE VGNAME`, and you are done!
|
||||
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html).
|
||||
|
||||
## Avoiding Problems
|
||||
|
||||
Good start is to avoid using `{--force|-f}` and `{--yes|-y}` options which are
|
||||
often seen on internet discussions.
|
||||
there is a possibility of data loss, LVM tools usually ask, so read the prompts
|
||||
carefully! Using `--yes` removes these safety.
|
||||
Also in some cases where it is too dangerous to proceed, e.g. device is used,
|
||||
LVM refuses to do so, which can be overridden by `--force`.
|
||||
|
||||
Second, when resizing and especially when shrinking LVs it is always a good
|
||||
idea to use `--resizefs` option which ensures the devices are resized in
|
||||
correct order.
|
||||
|
||||
Third, if you still make a mess, never ever run fsck on damaged LV/FS, this is
|
||||
usually the final blow to your data. It is always better to ask first!
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
## Resolving Problems
|
||||
|
||||
* Backup if possible!
|
||||
* Search the problem first, check the list of [[common problems|Problems]]
|
||||
* Never run `fsck` on damaged LV, LV must be recovered first!
|
||||
* When asking for help describe exactly how the system got corrupted. It really
|
||||
does not help trying to cover one's mistakes in such situation, it takes
|
||||
longer to get help and also you are likely to get wrong answer making repair
|
||||
impossible.
|
||||
|
||||
## Reporting Bugs
|
||||
|
||||
* When you find a problem there is often something specific about your system.
|
||||
If the problem is reproducible run the failing command(s) with verbose flag
|
||||
`-vvvv` which gives developers clue where the problem might be.
|
||||
There is a [lvmdump(8)](https://man7.org/linux/man-pages/man8/lvmdump.8.html)
|
||||
tool to help collect data about your system, block devices and LVM setup.
|
||||
* Please report upstream bugs or request features in [Red Hat Bugzilla](https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper)
|
||||
|
||||
<!--
|
||||
TODO:
|
||||
* Add links to other documentation
|
||||
* Add links to git
|
||||
* Add links to mailing lists
|
||||
|
||||
* Resolving problems
|
||||
* Backup if possible!
|
||||
* Newer run fsck! Do the research first!
|
||||
* List of Common issues
|
||||
* Resizing in wrong order
|
||||
* Thin pool running out of space
|
||||
* Configuration - duplicates
|
||||
* Mailing list
|
||||
* IRC?
|
||||
|
||||
* Reporting Bugs
|
||||
* sosreport/lvmdump
|
||||
* BZ
|
||||
|
||||
* Contributing
|
||||
* gitlab MR
|
||||
|
||||
* Add latest articles
|
||||
-->
|
@@ -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
|
||||
|
4
doc/local.css
Normal file
4
doc/local.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.page {
|
||||
max-width: 1280px;
|
||||
margin: auto;
|
||||
}
|
@@ -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.
|
||||
|
||||
|
@@ -51,3 +51,5 @@ In future optional target flags will be given in two situations:
|
||||
|
||||
This decision could well be contentious, so could distro maintainers feel
|
||||
free to comment.
|
||||
|
||||
[[!tag legacy]]
|
||||
|
76
doc/release-notes/2.03.24.mdwn
Normal file
76
doc/release-notes/2.03.24.mdwn
Normal file
@@ -0,0 +1,76 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.24 - Feature and Bug Fix Release"]]
|
||||
|
||||
Version 2.03.24
|
||||
===============
|
||||
|
||||
* **Changes in udev rules, new version of systemd is recommended (256).**
|
||||
* **When using LVs as PVs these are no longer auto activated!**
|
||||
* Allow creating VDO device for thin data when creating thin pool.
|
||||
* More devices can be used as external origin for thin snapshot.
|
||||
* And [[!toggle text="more"]]
|
||||
|
||||
[[!toggleable text="""
|
||||
Features
|
||||
-----------------------
|
||||
|
||||
* Swap properties like hostname, date and time when swapping LVs.
|
||||
* Allow thin snapshot taken of thin volume from another pool as external origin.
|
||||
* Allow chaining of external origins.
|
||||
|
||||
### Changes to device handling
|
||||
|
||||
* **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 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.
|
||||
* When `devices/use_devicesfile` is set to `0` existing file is renamed to
|
||||
*system.devices-unused.YYYYMMDD.HHMMSS* to prevent outdated file to be used
|
||||
on reenabling.
|
||||
|
||||
### Use VDO device for thin pool's data
|
||||
|
||||
New option `--pooldatavdo` during lvcreate or lvconvert allows using VDO as backing device.
|
||||
|
||||
More options (`--compression {y|n}`, `--deduplication {y|n}`,
|
||||
`--vdosettings STRING`) to control the options are supported by these commands.
|
||||
|
||||
Example of converting a *lvol1* to a thin pool with enabled compression and deduplication:
|
||||
|
||||
lvconvert --type thin-pool --pooldatavdo y vg/lvol1
|
||||
|
||||
Changes in command line
|
||||
-----------------------
|
||||
|
||||
* Add *--wipesignature* option controlling signature wiping when converting volume to thin-pool.
|
||||
* Allow *lvcreate --snapshot* without *{-T|--thin}* option when creating snapshot of a thin volume.
|
||||
* Allow *--raidintegrity{,mode,blocksize}* options with implicit RAID1 (i.e. when *-m1* is used on command line)
|
||||
|
||||
./configure options
|
||||
-------------------
|
||||
|
||||
These changes are for packagers:
|
||||
|
||||
* Add `--with-default-event-activation` option controlling default for
|
||||
`global/event_activation`. Default value is unchanged. Useful when creating
|
||||
builds for testing.
|
||||
* Add `--with-modulesdir` option.
|
||||
|
||||
Changes in udev rules
|
||||
---------------------
|
||||
|
||||
**IMPORTANT:** Rework of udev rules in cooperation with systemd is included in this release.
|
||||
|
||||
* `DM_SUSPENDED` and `DM_NOSCAN` are now entirely internal for DM and cannot be used outside of DM rules.
|
||||
* Upper level rules should consume `DM_UDEV_DISABLE_OTHER_RULES_FLAG` rather than `DM_NOSCAN` and `DM_SUSPENDED`.
|
||||
|
||||
Also few more minor improvements:
|
||||
|
||||
* Better handling of `DISK_RO` events and suspended devices
|
||||
|
||||
"""]]
|
||||
|
||||
[[!tag]]
|
||||
[[!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="Tue Nov 21 14:26:07 2023 +0100"]]
|
||||
-->
|
||||
|
9
doc/release-notes/index.mdwn
Normal file
9
doc/release-notes/index.mdwn
Normal file
@@ -0,0 +1,9 @@
|
||||
# LVM Releases
|
||||
|
||||
This list is incomplete, only releases with a release-note are included.
|
||||
|
||||
For releases of legacy branch *2.02* see [[legacy]].
|
||||
|
||||
Too see what's cooking see [[pending]].
|
||||
|
||||
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" rootpage="release-notes"]]
|
8
doc/release-notes/legacy.mdwn
Normal file
8
doc/release-notes/legacy.mdwn
Normal file
@@ -0,0 +1,8 @@
|
||||
# Legacy 2.02 Releases
|
||||
|
||||
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"]]
|
||||
|
3
doc/release-notes/pending.mdwn
Normal file
3
doc/release-notes/pending.mdwn
Normal file
@@ -0,0 +1,3 @@
|
||||
# Pending Release
|
||||
|
||||
[[!inline pages="release-notes/* and !*/template and !*/Discussion and tagged(pending)" rootpage="release-notes"]]
|
52
doc/release-notes/template.mdwn
Normal file
52
doc/release-notes/template.mdwn
Normal file
@@ -0,0 +1,52 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03. - Feature and Bug Fix Release"]]
|
||||
|
||||
Version 2.03.
|
||||
===============
|
||||
|
||||
* List of important/interesting changes
|
||||
* And [[!toggle text="more"]]
|
||||
|
||||
[[!toggleable text="""
|
||||
Features
|
||||
-----------------------
|
||||
|
||||
* List new features worth mentioning here in one line.
|
||||
|
||||
### New Feature Worth a Paragraph or Two
|
||||
|
||||
Write a paragraph or two covering feature where some examples of usage are expected.
|
||||
|
||||
<!--
|
||||
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
|
||||
-----------------------
|
||||
|
||||
Describe important changes in command line tools, especially any changes of behavior, which user must be aware of:
|
||||
|
||||
* New options
|
||||
* Removed options
|
||||
* Use a separate page in *./doc* for larger features worth separate article, or a man page
|
||||
|
||||
Changes in lvm.conf
|
||||
-------------------
|
||||
|
||||
* New options.
|
||||
* Change of defaults.
|
||||
|
||||
./configure options
|
||||
-------------------
|
||||
|
||||
* New options and features the enable.
|
||||
|
||||
"""]]
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag draft pending]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
|
||||
-->
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user