mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-24 16:23:50 +03:00
Compare commits
1133 Commits
dm_v1_02_2
...
old-v2_02_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84b0920fe0 | ||
|
|
a3d7f70d45 | ||
|
|
99b7ce7bf5 | ||
|
|
819e3b9661 | ||
|
|
cac468586a | ||
|
|
afc8c05f7f | ||
|
|
886e528490 | ||
|
|
06691a0794 | ||
|
|
c61da238e1 | ||
|
|
e07419b4ba | ||
|
|
cecc0e9dc8 | ||
|
|
4d4d7c1fb3 | ||
|
|
e50e7ee119 | ||
|
|
0d15d01b45 | ||
|
|
7972728e7c | ||
|
|
d4d430ee80 | ||
|
|
b2155fde1a | ||
|
|
0033b9eeb5 | ||
|
|
3d25b06fbc | ||
|
|
32752bc3dd | ||
|
|
f1fd43b61c | ||
|
|
38fda754a1 | ||
|
|
dc4e40a2f6 | ||
|
|
9abda62c5b | ||
|
|
cd5c37fe1c | ||
|
|
bce8cac1f4 | ||
|
|
4171d0c301 | ||
|
|
2edd956853 | ||
|
|
d77b03d6c9 | ||
|
|
4d5a88661f | ||
|
|
0b9b1ccd0b | ||
|
|
d5ef8e037d | ||
|
|
fd09a32d5e | ||
|
|
afc5de69d4 | ||
|
|
2adec6ef66 | ||
|
|
5829d87313 | ||
|
|
4422423315 | ||
|
|
6c88b6c660 | ||
|
|
ccca1401ae | ||
|
|
39270f9647 | ||
|
|
3b6a147653 | ||
|
|
fd69075a8b | ||
|
|
dfed228991 | ||
|
|
5403c6122c | ||
|
|
ec76533493 | ||
|
|
fbdc356b7c | ||
|
|
709e1afd31 | ||
|
|
217bbd0dcb | ||
|
|
e32f9edc3d | ||
|
|
282029eb45 | ||
|
|
0ae88174b8 | ||
|
|
42fdc445d0 | ||
|
|
48416fcdc1 | ||
|
|
5dab79f1c7 | ||
|
|
cfe2d71862 | ||
|
|
db03ac1596 | ||
|
|
36a1405360 | ||
|
|
85d1fe36e1 | ||
|
|
0148ff5ea2 | ||
|
|
89f096d68e | ||
|
|
db9a15e2fa | ||
|
|
84ae15e8d1 | ||
|
|
f69451140f | ||
|
|
ca897d8d15 | ||
|
|
4cacc0ee7d | ||
|
|
93148f9334 | ||
|
|
9ae2f02842 | ||
|
|
bc63df367d | ||
|
|
3f76b672f2 | ||
|
|
c79f1d5f37 | ||
|
|
db023c4448 | ||
|
|
48f66c5cb4 | ||
|
|
f54cd61ba6 | ||
|
|
011ec46dae | ||
|
|
6c91562aa9 | ||
|
|
a3ce036dc0 | ||
|
|
c82ecd6656 | ||
|
|
7ce37c9842 | ||
|
|
6e4baa664d | ||
|
|
59ffb010c4 | ||
|
|
2edb216b24 | ||
|
|
7835e2a762 | ||
|
|
f8c9d0c018 | ||
|
|
2965b52563 | ||
|
|
05762487ff | ||
|
|
b2380fcc48 | ||
|
|
40ec4f631c | ||
|
|
f9238f838c | ||
|
|
3dd756c2c1 | ||
|
|
a92bdc094d | ||
|
|
9b367aa0a1 | ||
|
|
2201a47d95 | ||
|
|
bdb578fda2 | ||
|
|
6765f24184 | ||
|
|
5ec0df6fe1 | ||
|
|
594fbed146 | ||
|
|
20e2e324e1 | ||
|
|
f33e774f4b | ||
|
|
dbdce70a8e | ||
|
|
b41f609fe4 | ||
|
|
424f396e42 | ||
|
|
b1c01d2ac9 | ||
|
|
fed21338fc | ||
|
|
987fe8b638 | ||
|
|
535c4372ca | ||
|
|
ac1f36ae76 | ||
|
|
b1442a1a97 | ||
|
|
6628e7769e | ||
|
|
5fadbc7f97 | ||
|
|
095026b459 | ||
|
|
496c8d01fa | ||
|
|
63574298ce | ||
|
|
8c1a5f033e | ||
|
|
7e3141512a | ||
|
|
c4510327d4 | ||
|
|
88fc2bb3e1 | ||
|
|
75a6913f4e | ||
|
|
97472070c3 | ||
|
|
5d4fd6055e | ||
|
|
83f4e5b457 | ||
|
|
1523a4953f | ||
|
|
429139be78 | ||
|
|
0307c0366a | ||
|
|
f698db8346 | ||
|
|
b690ccfc20 | ||
|
|
86e97d9f87 | ||
|
|
4a7a570953 | ||
|
|
0b1ce57fd1 | ||
|
|
eb39bfad81 | ||
|
|
77533a2090 | ||
|
|
414bc9cc44 | ||
|
|
180d55d135 | ||
|
|
458baea830 | ||
|
|
aaeec65415 | ||
|
|
3a821c040e | ||
|
|
31fdb438bb | ||
|
|
8db00f063d | ||
|
|
8cca58b800 | ||
|
|
9f2e60598d | ||
|
|
78af10f81b | ||
|
|
025ac59005 | ||
|
|
2b9605e8f5 | ||
|
|
333091a0d3 | ||
|
|
012ff9982c | ||
|
|
887e1d5d61 | ||
|
|
3aca463e7e | ||
|
|
b7255dac54 | ||
|
|
a3158f498f | ||
|
|
95ff997d1d | ||
|
|
80520d4ed7 | ||
|
|
1fbf5728e1 | ||
|
|
216b6b3efd | ||
|
|
557f287005 | ||
|
|
7548112578 | ||
|
|
323685d4c9 | ||
|
|
4900b15a65 | ||
|
|
adc02e52ad | ||
|
|
4bc79321a7 | ||
|
|
c0d270947f | ||
|
|
8b4677dca3 | ||
|
|
44482a809e | ||
|
|
90d8fab02e | ||
|
|
337d248c5d | ||
|
|
62a636c887 | ||
|
|
bbd12ca7aa | ||
|
|
02f858e5c9 | ||
|
|
536a126886 | ||
|
|
2a42fdea85 | ||
|
|
eb77e55fe6 | ||
|
|
edd643b226 | ||
|
|
4f7f3b5a50 | ||
|
|
1b611e7cd8 | ||
|
|
5454ec8f9b | ||
|
|
d2d528d214 | ||
|
|
a00d4b7845 | ||
|
|
0eeefc4c0d | ||
|
|
0d8600ed6d | ||
|
|
35cf511d45 | ||
|
|
b88fe43808 | ||
|
|
9c72fc1d2b | ||
|
|
e176789891 | ||
|
|
5e3369aba3 | ||
|
|
7b0fcd79a0 | ||
|
|
0ed40c04c7 | ||
|
|
7da36611dc | ||
|
|
49aeee3017 | ||
|
|
571cd5a94f | ||
|
|
a044570365 | ||
|
|
c18595ce31 | ||
|
|
a06d6839e1 | ||
|
|
22ba3c7b41 | ||
|
|
e84ecd9e42 | ||
|
|
db5e7962c9 | ||
|
|
4782f379e2 | ||
|
|
8762b5aad4 | ||
|
|
147d76d2aa | ||
|
|
a5aedfee75 | ||
|
|
2a4c743edd | ||
|
|
a9d820ed2f | ||
|
|
fa059a59a8 | ||
|
|
dc8f5ef279 | ||
|
|
e5e30dc73d | ||
|
|
ae94917e76 | ||
|
|
fedb3704f3 | ||
|
|
ea18f8e19b | ||
|
|
cd93b0470b | ||
|
|
4665b5aecf | ||
|
|
1f9b9c6235 | ||
|
|
3f4c43456f | ||
|
|
10a3ba33a5 | ||
|
|
db0beacf02 | ||
|
|
a07023d613 | ||
|
|
900c634af1 | ||
|
|
48d9b570b9 | ||
|
|
207ddca859 | ||
|
|
823b00705e | ||
|
|
4fb0ddedc7 | ||
|
|
31b3571d31 | ||
|
|
ee373a2721 | ||
|
|
685bc7ae83 | ||
|
|
bc6772282f | ||
|
|
d0d0c1e5e5 | ||
|
|
1ed598ada6 | ||
|
|
b003ae7270 | ||
|
|
18a4a3e21c | ||
|
|
72a41480ba | ||
|
|
6e221abda6 | ||
|
|
e7d8b84581 | ||
|
|
7a84430e84 | ||
|
|
7e7274b002 | ||
|
|
e27183d54f | ||
|
|
f49c31ddb2 | ||
|
|
ac959238aa | ||
|
|
563b6561a5 | ||
|
|
bc26690cbf | ||
|
|
4f56896f60 | ||
|
|
5158d34c2d | ||
|
|
5c63f0b7e3 | ||
|
|
1b3fa825f3 | ||
|
|
ef182f4b64 | ||
|
|
b706479c9b | ||
|
|
751c4fe7ef | ||
|
|
d09baef532 | ||
|
|
778244e436 | ||
|
|
f6cf83aebf | ||
|
|
e6901382a6 | ||
|
|
75c22b585e | ||
|
|
5018d3b5cb | ||
|
|
9eeacf2cfc | ||
|
|
9c25d59b82 | ||
|
|
4550133c81 | ||
|
|
8a5921e4bc | ||
|
|
470aa36c91 | ||
|
|
1fbcff5fcc | ||
|
|
6fb06af9ff | ||
|
|
62941d65a9 | ||
|
|
18fe170698 | ||
|
|
c2cd4d5d15 | ||
|
|
69da2ac0c7 | ||
|
|
e08e69719d | ||
|
|
5628024d45 | ||
|
|
9d46d25d03 | ||
|
|
836326f31e | ||
|
|
34fe80f9d9 | ||
|
|
15ae133662 | ||
|
|
c405a5d5b3 | ||
|
|
7acff3b938 | ||
|
|
7099be8f44 | ||
|
|
86e8c36a75 | ||
|
|
bc6fe86faa | ||
|
|
3bcab11310 | ||
|
|
3c8b92675f | ||
|
|
0f19d74cb1 | ||
|
|
d796a2a768 | ||
|
|
f962adbb52 | ||
|
|
3479d0ee30 | ||
|
|
70a0590ece | ||
|
|
8414c57026 | ||
|
|
ae2e7f0603 | ||
|
|
7177c3b393 | ||
|
|
11f40ba93b | ||
|
|
273511037a | ||
|
|
56d64f23bf | ||
|
|
cfbeca5e65 | ||
|
|
aaf9b56084 | ||
|
|
e0a953e27e | ||
|
|
f7c1e5f60d | ||
|
|
84bf81ac31 | ||
|
|
6a67a8c574 | ||
|
|
0fad9eaee4 | ||
|
|
d64d33ed07 | ||
|
|
0e8fdf49d0 | ||
|
|
f147256697 | ||
|
|
dbe275ce72 | ||
|
|
649cd608c1 | ||
|
|
87c63e995b | ||
|
|
cd49c5bf66 | ||
|
|
c3ca9468d1 | ||
|
|
89576aa2c1 | ||
|
|
630dbab749 | ||
|
|
8e95a2a603 | ||
|
|
6a1c94d48d | ||
|
|
578a9a3332 | ||
|
|
122fe8a20d | ||
|
|
d32f607aba | ||
|
|
25d9591416 | ||
|
|
33f41cc68b | ||
|
|
d8bee53822 | ||
|
|
0866f47904 | ||
|
|
d230325569 | ||
|
|
8e7930a604 | ||
|
|
1dde89db69 | ||
|
|
350d0a6495 | ||
|
|
42e922d587 | ||
|
|
57c002f324 | ||
|
|
e5fb684ac1 | ||
|
|
84abdc7b2d | ||
|
|
db79a4a14b | ||
|
|
f1b30c5aff | ||
|
|
4db2593801 | ||
|
|
ad685d2153 | ||
|
|
cf9dd7cf5e | ||
|
|
f10d82dc30 | ||
|
|
5ec942fb2a | ||
|
|
2897cfb556 | ||
|
|
5484869af9 | ||
|
|
90cc3a0f05 | ||
|
|
99e45f71c2 | ||
|
|
488d246ada | ||
|
|
8189910b5a | ||
|
|
de317b8e01 | ||
|
|
436cf94595 | ||
|
|
145c999762 | ||
|
|
c82b46032a | ||
|
|
cf9fa94eaa | ||
|
|
d5139fef22 | ||
|
|
f8964db41c | ||
|
|
052169695c | ||
|
|
f9a8a94fd1 | ||
|
|
880d9bb33f | ||
|
|
68aa3eb1b9 | ||
|
|
39dbb9dad8 | ||
|
|
ac7acf2441 | ||
|
|
87ce5770b7 | ||
|
|
24f3c8c29e | ||
|
|
cf578d50ec | ||
|
|
6c2e4110ad | ||
|
|
01280bbd06 | ||
|
|
0f1b7a527b | ||
|
|
965c7e1200 | ||
|
|
abea4f481c | ||
|
|
71191eae5c | ||
|
|
03d4efc5c0 | ||
|
|
22c38019b2 | ||
|
|
7cd8194c99 | ||
|
|
b4747ad67f | ||
|
|
bb6db55686 | ||
|
|
244cd8f94f | ||
|
|
ba856910e0 | ||
|
|
d00e023894 | ||
|
|
86b4b128a9 | ||
|
|
35bd06a9a0 | ||
|
|
bdc7574fd5 | ||
|
|
a7cac2463c | ||
|
|
474bc8823e | ||
|
|
95f6b0c06e | ||
|
|
dc205333cd | ||
|
|
4de96ea715 | ||
|
|
c94f02648c | ||
|
|
2ba0dd20fb | ||
|
|
389dc22856 | ||
|
|
823c8af1ab | ||
|
|
286562d202 | ||
|
|
b83a1876ba | ||
|
|
ed2a931ae3 | ||
|
|
f77190f477 | ||
|
|
2d3335fa48 | ||
|
|
d52b3fd3fe | ||
|
|
5a945afdc6 | ||
|
|
8b65ad0237 | ||
|
|
6d74246c91 | ||
|
|
9d81c953c3 | ||
|
|
97e41de23f | ||
|
|
d57543b220 | ||
|
|
13cd91bffb | ||
|
|
2d170dfed8 | ||
|
|
744ac0eb81 | ||
|
|
057983ce3e | ||
|
|
aadc34ab4d | ||
|
|
d9c4af46ed | ||
|
|
cdd0024bad | ||
|
|
6e331c523f | ||
|
|
f7712c77b8 | ||
|
|
fd436c316a | ||
|
|
7120f7df54 | ||
|
|
1d30bf8af4 | ||
|
|
40c70e12dd | ||
|
|
31b6eb916f | ||
|
|
09e7a582de | ||
|
|
b8aec00dee | ||
|
|
174f5a3a49 | ||
|
|
758d469679 | ||
|
|
542bdaa740 | ||
|
|
14bd66805e | ||
|
|
01c2d76c54 | ||
|
|
40cd0b1dd2 | ||
|
|
5dad791818 | ||
|
|
3743a6858b | ||
|
|
409a8d3678 | ||
|
|
94084178d9 | ||
|
|
3c80245275 | ||
|
|
16c4b2a572 | ||
|
|
0cf1e72ed1 | ||
|
|
029346d322 | ||
|
|
9e959f9bdd | ||
|
|
3ec8c63e28 | ||
|
|
ceeb1eca9d | ||
|
|
5800560602 | ||
|
|
a840a56e02 | ||
|
|
8704f4e24e | ||
|
|
459a5a5b1f | ||
|
|
afc28c54ac | ||
|
|
6772b45ea6 | ||
|
|
7defd4dab0 | ||
|
|
db326a14b3 | ||
|
|
0abf2e237e | ||
|
|
d3a2b52363 | ||
|
|
de81594179 | ||
|
|
06bdf8b461 | ||
|
|
d784303591 | ||
|
|
52d2c31427 | ||
|
|
9bc8e56458 | ||
|
|
489c728793 | ||
|
|
01eaadfa53 | ||
|
|
dddd2f9202 | ||
|
|
31709134c9 | ||
|
|
456efad714 | ||
|
|
2112fc571a | ||
|
|
0c4379ff0f | ||
|
|
a690b36478 | ||
|
|
6f5ed95f71 | ||
|
|
251ee5f5a2 | ||
|
|
9ab1d88a91 | ||
|
|
5d3d9f57fe | ||
|
|
0889882255 | ||
|
|
2a1f78f95a | ||
|
|
6faaa1a0cc | ||
|
|
77dd12a028 | ||
|
|
6a954445f1 | ||
|
|
9500e898c6 | ||
|
|
c5989d4350 | ||
|
|
8f782be41d | ||
|
|
afcc447a64 | ||
|
|
8cfcba83ae | ||
|
|
a8315726ce | ||
|
|
da668c80b2 | ||
|
|
55455ac21f | ||
|
|
74adacf96a | ||
|
|
a384b41308 | ||
|
|
048a329afc | ||
|
|
3c3d16e794 | ||
|
|
d95b544dfd | ||
|
|
5d9ea7b91b | ||
|
|
500289229a | ||
|
|
21d62387ae | ||
|
|
3bbfb30dcb | ||
|
|
819fbc6ed5 | ||
|
|
53e7c8fa34 | ||
|
|
35d13cad96 | ||
|
|
c190fc702e | ||
|
|
cd0ed7b509 | ||
|
|
24af685db1 | ||
|
|
d7553ded6c | ||
|
|
884d5a7fc8 | ||
|
|
a920074468 | ||
|
|
5ab342e298 | ||
|
|
c99f525821 | ||
|
|
dff004d695 | ||
|
|
6f53e4b536 | ||
|
|
9d3fe84135 | ||
|
|
e5f7ae3878 | ||
|
|
97162d9a53 | ||
|
|
d0b99cb260 | ||
|
|
fa22cc2e20 | ||
|
|
9904255490 | ||
|
|
f75c15b477 | ||
|
|
9404dcab69 | ||
|
|
c4d4403955 | ||
|
|
a0bb2dc907 | ||
|
|
ed774a5691 | ||
|
|
78cedddbde | ||
|
|
3640dc2fa3 | ||
|
|
d3c619e3d3 | ||
|
|
c158759c11 | ||
|
|
b49362420c | ||
|
|
aab76646ee | ||
|
|
259245d412 | ||
|
|
717180a8eb | ||
|
|
12811483be | ||
|
|
822aa2a352 | ||
|
|
9d788d4d9c | ||
|
|
d405cb8dd9 | ||
|
|
5d3e57094a | ||
|
|
e28d3f8cbd | ||
|
|
182494a5b7 | ||
|
|
9487820c32 | ||
|
|
03d00c16f8 | ||
|
|
57a38a00d9 | ||
|
|
779b8679fd | ||
|
|
d0143d6f3e | ||
|
|
7917c3fc15 | ||
|
|
81de913b77 | ||
|
|
0e3798cadb | ||
|
|
7447482608 | ||
|
|
f9b185caa5 | ||
|
|
4761ce4b45 | ||
|
|
9f31af4c20 | ||
|
|
ab448cdb57 | ||
|
|
22c4076818 | ||
|
|
6e8bd97709 | ||
|
|
7dd128a1a8 | ||
|
|
dfd422a386 | ||
|
|
6f434cd94a | ||
|
|
a82f2fec18 | ||
|
|
234115f384 | ||
|
|
c522618a4b | ||
|
|
1c65c56970 | ||
|
|
c6cff13038 | ||
|
|
f25b101161 | ||
|
|
6a866e208f | ||
|
|
11b1e5abd7 | ||
|
|
f44c387988 | ||
|
|
b6629080ee | ||
|
|
4022dd564b | ||
|
|
c848ce66c5 | ||
|
|
26b4c34778 | ||
|
|
7eff83d689 | ||
|
|
125fb7fbdb | ||
|
|
01be5511e5 | ||
|
|
4b45c6e35a | ||
|
|
7f831c1f4d | ||
|
|
d6778847c9 | ||
|
|
9a96645b53 | ||
|
|
ffa1b19e26 | ||
|
|
6f98b140a8 | ||
|
|
e83d1a26e6 | ||
|
|
b237d68c47 | ||
|
|
1027762816 | ||
|
|
42893fc3bd | ||
|
|
a479761be5 | ||
|
|
6d7265d966 | ||
|
|
32048b7658 | ||
|
|
08f79c6b93 | ||
|
|
699a2268d6 | ||
|
|
410f9c485e | ||
|
|
8561e5e38e | ||
|
|
17617fe839 | ||
|
|
7f4173ab22 | ||
|
|
84236edaf8 | ||
|
|
370dc2d727 | ||
|
|
211b07a2e2 | ||
|
|
9f67ba6a38 | ||
|
|
03798fd604 | ||
|
|
7bb4897b9f | ||
|
|
4b0e97e666 | ||
|
|
5b655dd4cd | ||
|
|
023a61c0e5 | ||
|
|
38cc6383b7 | ||
|
|
77ac863bb8 | ||
|
|
fdab219755 | ||
|
|
f31e8d08cd | ||
|
|
224c8ec0fa | ||
|
|
309c19ef63 | ||
|
|
13aad7e8b4 | ||
|
|
6f36d0d06c | ||
|
|
76d734a4bd | ||
|
|
b14f29b5b7 | ||
|
|
c57b30e342 | ||
|
|
f6023a7c76 | ||
|
|
6357a2d9b8 | ||
|
|
7e3a1a8b18 | ||
|
|
5f1b8f71f3 | ||
|
|
cca8bb9092 | ||
|
|
647314d3cc | ||
|
|
30e6773617 | ||
|
|
08774dc558 | ||
|
|
481618826d | ||
|
|
befcada36a | ||
|
|
b71bf9332c | ||
|
|
1303c93139 | ||
|
|
29c8c75492 | ||
|
|
862d83c691 | ||
|
|
f18eeb4da8 | ||
|
|
d40fed016f | ||
|
|
76dc3ddf56 | ||
|
|
d80d9a4c4e | ||
|
|
281ee1c2bf | ||
|
|
65e976198e | ||
|
|
a0d668e850 | ||
|
|
f7d624e684 | ||
|
|
f5c395adb2 | ||
|
|
09192b4d6e | ||
|
|
74ec3783e7 | ||
|
|
1c38ce8245 | ||
|
|
702cfe15be | ||
|
|
54d790828f | ||
|
|
aff35fea29 | ||
|
|
25a82bcbe3 | ||
|
|
cb58100587 | ||
|
|
9fbe96fd7c | ||
|
|
98cd400443 | ||
|
|
873e699f6d | ||
|
|
9a8f6c824f | ||
|
|
a98888ad07 | ||
|
|
db98500b72 | ||
|
|
3feee09cfe | ||
|
|
4a1cd0d391 | ||
|
|
edb5071d3b | ||
|
|
e9509aa5e6 | ||
|
|
5e6ca1b72d | ||
|
|
543bf2ffbd | ||
|
|
15a7a4c38b | ||
|
|
640d07bf35 | ||
|
|
e5ecc2b942 | ||
|
|
cfd8fe40f4 | ||
|
|
abba6e0642 | ||
|
|
ec94fb89a2 | ||
|
|
bb167efa7b | ||
|
|
2a550ef96d | ||
|
|
03ed7d73fc | ||
|
|
446852db3b | ||
|
|
7c90b57e87 | ||
|
|
6339e2588b | ||
|
|
af6687405b | ||
|
|
a2bfad1c29 | ||
|
|
645aa55abc | ||
|
|
05329c885a | ||
|
|
b3fed93a74 | ||
|
|
2c6fad0ea7 | ||
|
|
57854c2231 | ||
|
|
a8cf4293e0 | ||
|
|
ba70dce803 | ||
|
|
5b4c3ace56 | ||
|
|
2ade7a15e2 | ||
|
|
e83f71d678 | ||
|
|
412c91cb6b | ||
|
|
aa44167319 | ||
|
|
dd5700e8b3 | ||
|
|
ef7fc430d7 | ||
|
|
f1bcb6c634 | ||
|
|
4a4eb17d08 | ||
|
|
8afc267c68 | ||
|
|
6457ab31b6 | ||
|
|
306dfa2043 | ||
|
|
424bdade0b | ||
|
|
10857e3321 | ||
|
|
85a4e47879 | ||
|
|
759e49f025 | ||
|
|
43924e31b8 | ||
|
|
3b34fcf59f | ||
|
|
ba7253eaf7 | ||
|
|
be23682a30 | ||
|
|
3a5dce4c92 | ||
|
|
22d7e60d0e | ||
|
|
5752156c9e | ||
|
|
a30215a530 | ||
|
|
f9c8c1b964 | ||
|
|
5650f67ef5 | ||
|
|
5ec25dfb94 | ||
|
|
ef16682725 | ||
|
|
883486cc67 | ||
|
|
f367f9b747 | ||
|
|
a3d987fa73 | ||
|
|
2d48685673 | ||
|
|
9b21ace1e9 | ||
|
|
be2c03fa96 | ||
|
|
f5585e9252 | ||
|
|
4d534dd7e4 | ||
|
|
c8584e1cce | ||
|
|
84a1de464c | ||
|
|
3966f3d319 | ||
|
|
e6166cf711 | ||
|
|
2285712834 | ||
|
|
53cb6128e8 | ||
|
|
8c317baf19 | ||
|
|
8cac933c71 | ||
|
|
03e61a4bf8 | ||
|
|
71446a76b2 | ||
|
|
28db8d6c7c | ||
|
|
786e33d7d5 | ||
|
|
b140d6c50e | ||
|
|
64a95abdee | ||
|
|
57f926be17 | ||
|
|
4933b67959 | ||
|
|
370b4f1b9e | ||
|
|
f3b7baa84e | ||
|
|
eafdb2c807 | ||
|
|
a91fa821ab | ||
|
|
37ef162cda | ||
|
|
770928acfc | ||
|
|
d0f3570219 | ||
|
|
3d07c2605f | ||
|
|
c350798528 | ||
|
|
6bc3cc0bec | ||
|
|
2e3e5fcc81 | ||
|
|
dfdb10f6de | ||
|
|
5cbe5909eb | ||
|
|
04d52b450b | ||
|
|
a586a89547 | ||
|
|
1905eacf15 | ||
|
|
858ec0d740 | ||
|
|
76cfd406ca | ||
|
|
9dbaad859d | ||
|
|
95d43e17b3 | ||
|
|
09a2dff8de | ||
|
|
57208f879a | ||
|
|
149638431d | ||
|
|
30d2940c67 | ||
|
|
5ee86fc5d0 | ||
|
|
a03d0e2c3f | ||
|
|
8bd367d58d | ||
|
|
bc633e03aa | ||
|
|
797d0f1ef1 | ||
|
|
1be3e86aa0 | ||
|
|
e56dd38021 | ||
|
|
410904bef1 | ||
|
|
026cc120e7 | ||
|
|
ef2fda05cf | ||
|
|
92277e3ae2 | ||
|
|
fbc34d70b0 | ||
|
|
91dcddbdf7 | ||
|
|
874f42ad6c | ||
|
|
1989ef4ebc | ||
|
|
4f4c72c065 | ||
|
|
666cc72661 | ||
|
|
4524e8f5c9 | ||
|
|
bd07a29886 | ||
|
|
a0d865492e | ||
|
|
de27790de8 | ||
|
|
9c910b7be2 | ||
|
|
7f23ab94e2 | ||
|
|
77dc036c8f | ||
|
|
aa6e8d82ce | ||
|
|
3010285bb3 | ||
|
|
aaad3252f8 | ||
|
|
9065f534d8 | ||
|
|
52361c94e5 | ||
|
|
798be60fef | ||
|
|
6294154b15 | ||
|
|
6594fe077d | ||
|
|
582706cde6 | ||
|
|
6537cbdc17 | ||
|
|
53959459bb | ||
|
|
22d6121099 | ||
|
|
48d7f6f2f4 | ||
|
|
9fd4ddc490 | ||
|
|
a4d2fddbb2 | ||
|
|
c54a3f2721 | ||
|
|
04c0dba697 | ||
|
|
5406e3b7c5 | ||
|
|
6b624b7d00 | ||
|
|
2d364d4d80 | ||
|
|
1f27bf3774 | ||
|
|
d30a2653b5 | ||
|
|
3086822cd2 | ||
|
|
2c08336490 | ||
|
|
5936ac58c2 | ||
|
|
ded77e3f5c | ||
|
|
8a29df0a6c | ||
|
|
9db22babaf | ||
|
|
c318c5ed61 | ||
|
|
61243c65cd | ||
|
|
4a5d5cb462 | ||
|
|
cbf1447ebd | ||
|
|
30104441bf | ||
|
|
b4a70804f0 | ||
|
|
74f6707bde | ||
|
|
223eb8c84d | ||
|
|
107d000606 | ||
|
|
43e05607af | ||
|
|
55793452d5 | ||
|
|
686ba37255 | ||
|
|
03ed19dad5 | ||
|
|
ad2b6e5de1 | ||
|
|
767676d6ff | ||
|
|
bc7a54c615 | ||
|
|
1bda393678 | ||
|
|
bb5495c6bd | ||
|
|
484f905749 | ||
|
|
e0d61a4336 | ||
|
|
e643a16ba5 | ||
|
|
98fadec2b6 | ||
|
|
14f464ecb0 | ||
|
|
2ecdaf9bd4 | ||
|
|
707c898f66 | ||
|
|
69e4400774 | ||
|
|
695efde68d | ||
|
|
0c4b769011 | ||
|
|
e53eff0634 | ||
|
|
6c75243a06 | ||
|
|
efde37880b | ||
|
|
7d8f6381be | ||
|
|
3c361e3393 | ||
|
|
8440ecef5e | ||
|
|
6401f1b1c9 | ||
|
|
7487a7c988 | ||
|
|
f44584fa10 | ||
|
|
7b32165614 | ||
|
|
b0dc94d187 | ||
|
|
0383c4e1d8 | ||
|
|
a8c5758222 | ||
|
|
a7fabfd8cb | ||
|
|
5d5b575d16 | ||
|
|
ac1373653c | ||
|
|
b097aa787b | ||
|
|
723be0fe69 | ||
|
|
f0597a03de | ||
|
|
65f0656f54 | ||
|
|
507ece15a5 | ||
|
|
30be4d1613 | ||
|
|
366e89bda0 | ||
|
|
f159c3f768 | ||
|
|
8506d1d567 | ||
|
|
111829da46 | ||
|
|
605798073e | ||
|
|
8320f2b094 | ||
|
|
df0d8d809b | ||
|
|
062886df64 | ||
|
|
148ea3aaa8 | ||
|
|
ab5f66c13a | ||
|
|
e65ffb8e68 | ||
|
|
949c1ab517 | ||
|
|
946d8ee046 | ||
|
|
c54a8a2e10 | ||
|
|
31177e4f85 | ||
|
|
750f81b4b5 | ||
|
|
987ff02a45 | ||
|
|
f5adaf813c | ||
|
|
78ff7dc7f0 | ||
|
|
d1fced3324 | ||
|
|
e7df9c289b | ||
|
|
a78d7231a9 | ||
|
|
ba7ae0002e | ||
|
|
a090f7b839 | ||
|
|
34ed15a987 | ||
|
|
cacec4c910 | ||
|
|
3e47d4e65b | ||
|
|
8b42fa150b | ||
|
|
60e660b9c7 | ||
|
|
fe74f013e3 | ||
|
|
24c0c70f90 | ||
|
|
757f91ca89 | ||
|
|
5c34f7847e | ||
|
|
de456f014e | ||
|
|
d29565066d | ||
|
|
4d52c9233b | ||
|
|
6da1ca0cb9 | ||
|
|
2f02f1518a | ||
|
|
e8863707de | ||
|
|
6a336dfc69 | ||
|
|
35dec1b9e4 | ||
|
|
f148280c99 | ||
|
|
599fe39749 | ||
|
|
44f3fcb238 | ||
|
|
af40fdb285 | ||
|
|
9daf8b825c | ||
|
|
ef5d8ce367 | ||
|
|
4a199ab23b | ||
|
|
6f0f5a569d | ||
|
|
3172fbfde6 | ||
|
|
e97a07a505 | ||
|
|
6579ad92da | ||
|
|
ec2fad0cfa | ||
|
|
6196ac7995 | ||
|
|
095a861018 | ||
|
|
2449ed7765 | ||
|
|
117a0408d6 | ||
|
|
a54b0223a3 | ||
|
|
44ee708ba5 | ||
|
|
58a20d0fb6 | ||
|
|
063078a02d | ||
|
|
01402fea50 | ||
|
|
b7fc2d1147 | ||
|
|
43eeb7011c | ||
|
|
d7901a4220 | ||
|
|
0c6271dabc | ||
|
|
2d4cf0c9f5 | ||
|
|
0646d0dd91 | ||
|
|
83e54b45a5 | ||
|
|
5cd87d3d27 | ||
|
|
689d8a80b5 | ||
|
|
b1d82a92e7 | ||
|
|
4d65627a50 | ||
|
|
ce3a68d817 | ||
|
|
409725be24 | ||
|
|
b74f74a0d7 | ||
|
|
719d554430 | ||
|
|
13f54f4521 | ||
|
|
57dfc9cf42 | ||
|
|
57244a6823 | ||
|
|
8bdde01bef | ||
|
|
09bbd5a472 | ||
|
|
9154a74400 | ||
|
|
1399b84b32 | ||
|
|
2ddbb3a8fa | ||
|
|
e46a6d1cc1 | ||
|
|
b698ab9011 | ||
|
|
0a2572a5eb | ||
|
|
77d049cc3d | ||
|
|
7b8f053be2 | ||
|
|
2c850d5293 | ||
|
|
4056bbf10b | ||
|
|
896b04a846 | ||
|
|
93cda8b6ec | ||
|
|
bb5e930684 | ||
|
|
43761fed2a | ||
|
|
a636299680 | ||
|
|
08e5bd5b72 | ||
|
|
2f057bef5e | ||
|
|
5ab4f21444 | ||
|
|
9ec26ed481 | ||
|
|
29c9df1389 | ||
|
|
867e9c51d4 | ||
|
|
0170f7b42a | ||
|
|
74bb6ead95 | ||
|
|
303388e5cb | ||
|
|
8388779937 | ||
|
|
fc7dfca452 | ||
|
|
e5a1db2392 | ||
|
|
6790656af6 | ||
|
|
b7477bdc15 | ||
|
|
ffc61f31de | ||
|
|
e612871ea7 | ||
|
|
7f40f09f10 | ||
|
|
456e42257c | ||
|
|
8618c271cf | ||
|
|
72ca1ccc23 | ||
|
|
075b4bef3f | ||
|
|
b59fce4393 | ||
|
|
8674a25eb8 | ||
|
|
10bf8fd2cd | ||
|
|
57cb22ff3c | ||
|
|
0162abdcae | ||
|
|
5801171518 | ||
|
|
bf1edbd1e2 | ||
|
|
a8484d987d | ||
|
|
9b2147f608 | ||
|
|
32530b378e | ||
|
|
a42905efa6 | ||
|
|
c59745f9dd | ||
|
|
b4ad9a5d08 | ||
|
|
3ead7a38b1 | ||
|
|
bf90435200 | ||
|
|
9c181fa3d3 | ||
|
|
3af0b1eb90 | ||
|
|
7110c318ee | ||
|
|
49a552ccdc | ||
|
|
57685f17a9 | ||
|
|
a1c09a463f | ||
|
|
194121760a | ||
|
|
6a987d46bf | ||
|
|
e3db0b39b9 | ||
|
|
4d4f0ee188 | ||
|
|
ac7334c167 | ||
|
|
e7bdd69af0 | ||
|
|
fefc655969 | ||
|
|
4dceaef60e | ||
|
|
6fc10dd3ae | ||
|
|
1ecd05a584 | ||
|
|
976acaca31 | ||
|
|
b4e5131d59 | ||
|
|
49f7cfefd7 | ||
|
|
fc365092f6 | ||
|
|
7f26240442 | ||
|
|
db559bb20a | ||
|
|
52850faa15 | ||
|
|
57d9a6c836 | ||
|
|
752c880bfc | ||
|
|
d83a354781 | ||
|
|
17dd81336d | ||
|
|
eaa46a2575 | ||
|
|
fc0ec1e71e | ||
|
|
fb2f92df1d | ||
|
|
74adbb77b7 | ||
|
|
788e544e1d | ||
|
|
368a0d4d2d | ||
|
|
962b7222d0 | ||
|
|
17c1f54369 | ||
|
|
33ae38e71b | ||
|
|
ef58af4bf1 | ||
|
|
3fad2db2f8 | ||
|
|
9feaeb28ca | ||
|
|
0075364715 | ||
|
|
99c5da5da5 | ||
|
|
22c957bc20 | ||
|
|
3316d59910 | ||
|
|
a109ce1eca | ||
|
|
e581a78d65 | ||
|
|
3c78f9900c | ||
|
|
bd606943e6 | ||
|
|
6381666df4 | ||
|
|
736f1aa301 | ||
|
|
b1a4eac7a8 | ||
|
|
8226a5276b | ||
|
|
77ad0bb12e | ||
|
|
9412b42206 | ||
|
|
2a91d87074 | ||
|
|
4a23617d79 | ||
|
|
0e2ceed74d | ||
|
|
ed56aed8eb | ||
|
|
8d909cbdc0 | ||
|
|
bf98943cbb | ||
|
|
6ff4552be2 | ||
|
|
1c7eb79370 | ||
|
|
f095a75f1e | ||
|
|
f70af6018c | ||
|
|
71b3b1ff4c | ||
|
|
d9fefa0c6c | ||
|
|
3bfe922381 | ||
|
|
a85cf17bf1 | ||
|
|
dbb5a09918 | ||
|
|
93e5097f20 | ||
|
|
dd53f2dc83 | ||
|
|
2b83c80593 | ||
|
|
6930f60c06 | ||
|
|
376b76e75c | ||
|
|
1ddd4509dc | ||
|
|
6af3f4f4cf | ||
|
|
6726c5f958 | ||
|
|
d5a9c43cb2 | ||
|
|
19a5a6a4eb | ||
|
|
617a599ee9 | ||
|
|
25e2d4da44 | ||
|
|
ad2e7218cb | ||
|
|
917637fa9b | ||
|
|
b595ee1c0b | ||
|
|
c8260a4a56 | ||
|
|
d2eaff3204 | ||
|
|
b65f5a844f | ||
|
|
95a69f99ba | ||
|
|
71d609895a | ||
|
|
9229630447 | ||
|
|
eb18a0b7dc | ||
|
|
05ed5c0d74 | ||
|
|
41330ecc5e | ||
|
|
16fbcc6e36 | ||
|
|
d87da9c7de | ||
|
|
94563b6017 | ||
|
|
34d22f7047 | ||
|
|
e24d996fbe | ||
|
|
9b52617919 | ||
|
|
efc1d46c89 | ||
|
|
9397833ceb | ||
|
|
e9433e83cd | ||
|
|
f3c58100a0 | ||
|
|
8900231d99 | ||
|
|
c7a63b8a2b | ||
|
|
90e90672a4 | ||
|
|
fa51e5c762 | ||
|
|
911f55d005 | ||
|
|
d30eb4e570 | ||
|
|
67bcfb6947 | ||
|
|
3915a61b1e | ||
|
|
c170d321e8 | ||
|
|
2802c476ee | ||
|
|
1050cebf7f | ||
|
|
dad73465fc | ||
|
|
8e2ac98fe2 | ||
|
|
9aaf0c36d5 | ||
|
|
1cb07e9cfd | ||
|
|
f1ccdf25b1 | ||
|
|
6dca497b27 | ||
|
|
42a83262a1 | ||
|
|
63ee9cbee6 | ||
|
|
3862f8ca7c | ||
|
|
4ada7cffd0 | ||
|
|
a664ce4298 | ||
|
|
8d7b6c6905 | ||
|
|
16d22d404a | ||
|
|
ccb24d5779 | ||
|
|
8795b45cb4 | ||
|
|
628d3bff45 | ||
|
|
0336bc9de9 | ||
|
|
033cb21797 | ||
|
|
09b98a45df | ||
|
|
38857ba29e | ||
|
|
1c7520ec8f | ||
|
|
362b9769b2 | ||
|
|
b2d68bd3d2 | ||
|
|
0dc7e635d4 | ||
|
|
80e070a857 | ||
|
|
cc203245e4 | ||
|
|
2f9a65fc93 | ||
|
|
62738e8001 | ||
|
|
5ecacf0c7f | ||
|
|
06b103c8d4 | ||
|
|
d473b7bca8 | ||
|
|
50a1e81ba7 | ||
|
|
d9885b1b64 | ||
|
|
0a9c8cada2 | ||
|
|
60f55f8461 | ||
|
|
7bedaea38f | ||
|
|
9e4b87e798 | ||
|
|
95bf59095c | ||
|
|
e0f34a9720 | ||
|
|
f3797c2a8e | ||
|
|
30cbcccc80 | ||
|
|
f49c0d696f | ||
|
|
71f564ee5b | ||
|
|
4b0950aba5 | ||
|
|
8c3af822ec | ||
|
|
878a207d19 | ||
|
|
0537ad860a | ||
|
|
2cdbbb1aea | ||
|
|
7af977d36b | ||
|
|
9afff4cf30 | ||
|
|
48ba9734aa | ||
|
|
897fc59f72 | ||
|
|
947e44ae67 | ||
|
|
e44843beba | ||
|
|
147482ea69 | ||
|
|
09091c5cf8 | ||
|
|
50827a5f69 | ||
|
|
2d6444c924 | ||
|
|
1d2675d9aa | ||
|
|
ad98990a8e | ||
|
|
8e58c143f2 | ||
|
|
556a4a2395 | ||
|
|
5be987b40f | ||
|
|
066bc35e69 | ||
|
|
403779437c | ||
|
|
fb806f61d4 | ||
|
|
6ce306661c |
34
INSTALL
34
INSTALL
@@ -1,44 +1,30 @@
|
||||
LVM2 installation
|
||||
=================
|
||||
Installation
|
||||
============
|
||||
|
||||
1) Install device-mapper
|
||||
|
||||
Ensure the device-mapper has been installed on the machine.
|
||||
|
||||
The device-mapper should be in the kernel (look for 'device-mapper'
|
||||
messages in the kernel logs) and /usr/include/libdevmapper.h
|
||||
and libdevmapper.so should be present.
|
||||
|
||||
The device-mapper is available from:
|
||||
ftp://ftp.sistina.com/pub/LVM2/device-mapper/
|
||||
|
||||
|
||||
2) Generate custom makefiles.
|
||||
1) Generate custom makefiles.
|
||||
|
||||
Run the 'configure' script from the top directory.
|
||||
|
||||
If you wish to use the built-in LVM2 shell and have GNU readline
|
||||
installed (http://www.gnu.org/directory/readline.html) use:
|
||||
./configure --enable-readline
|
||||
|
||||
If you don't want to include the LVM1 backwards-compatibility code use:
|
||||
./configure --with-lvm1=none
|
||||
|
||||
To separate the LVM1 support into a shared library loaded by lvm.conf use:
|
||||
./configure --with-lvm1=shared
|
||||
|
||||
Use ./configure --help to see other options.
|
||||
|
||||
3) Build and install LVM2.
|
||||
2) Build and install.
|
||||
|
||||
Run 'make install' from the top directory.
|
||||
Run 'make' from the top directory to build everything you configured.
|
||||
Run 'make install' to build and install everything you configured.
|
||||
|
||||
If you only want the device-mapper libraries and tools use
|
||||
'make device-mapper' or 'make install_device-mapper'.
|
||||
|
||||
4) Create a configuration file
|
||||
3) If using LVM2, create a configuration file.
|
||||
|
||||
The tools will work fine without a configuration file being
|
||||
present, but you ought to review the example file in doc/example.conf.
|
||||
For example, specifying the devices that LVM2 is to use can
|
||||
make the tools run more efficiently - and avoid scanning /dev/cdrom!
|
||||
|
||||
Please also refer to the WHATS_NEW file and the manual pages for the
|
||||
individual commands.
|
||||
|
||||
78
Makefile.in
78
Makefile.in
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@@ -18,43 +18,55 @@ VPATH = @srcdir@
|
||||
|
||||
SUBDIRS = doc include man scripts
|
||||
|
||||
ifeq ("@UDEV_RULES@", "yes")
|
||||
SUBDIRS += udev
|
||||
endif
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
SUBDIRS += po
|
||||
endif
|
||||
|
||||
SUBDIRS += lib tools daemons
|
||||
SUBDIRS += lib tools daemons libdm
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
SUBDIRS += dmeventd
|
||||
ifeq ("@APPLIB@", "yes")
|
||||
SUBDIRS += liblvm
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),distclean)
|
||||
SUBDIRS += daemons/clvmd \
|
||||
dmeventd \
|
||||
daemons/dmeventd/plugins \
|
||||
daemons/dmeventd \
|
||||
lib/format1 \
|
||||
lib/format_pool \
|
||||
lib/locking \
|
||||
lib/mirror \
|
||||
lib/snapshot \
|
||||
po \
|
||||
test/mm test/device test/format1 test/regex test/filters
|
||||
DISTCLEAN_TARGETS += lib/misc/configure.h
|
||||
test/api \
|
||||
test \
|
||||
po
|
||||
DISTCLEAN_TARGETS += lib/misc/configure.h lib/misc/lvm-version.h
|
||||
DISTCLEAN_DIRS += lcov_reports*
|
||||
endif
|
||||
|
||||
include make.tmpl
|
||||
|
||||
daemons: lib
|
||||
lib: include
|
||||
tools: lib
|
||||
dmeventd: tools
|
||||
po: tools daemons dmeventd
|
||||
libdm: include
|
||||
lib: libdm
|
||||
liblvm: lib
|
||||
daemons: lib tools
|
||||
tools: lib device-mapper
|
||||
po: tools daemons
|
||||
|
||||
libdm.device-mapper: include.device-mapper
|
||||
daemons.device-mapper: libdm.device-mapper
|
||||
tools.device-mapper: libdm.device-mapper
|
||||
device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
lib.pofile: include.pofile
|
||||
tools.pofile: lib.pofile
|
||||
daemons.pofile: lib.pofile
|
||||
dmeventd.pofile: tools.pofile
|
||||
po.pofile: tools.pofile daemons.pofile dmeventd.pofile
|
||||
po.pofile: tools.pofile daemons.pofile
|
||||
pofile: po.pofile
|
||||
endif
|
||||
|
||||
@@ -71,3 +83,39 @@ endif
|
||||
|
||||
check: all
|
||||
$(MAKE) -C test all
|
||||
|
||||
ifneq ("@LCOV@", "")
|
||||
.PHONY: lcov-reset lcov lcov-dated
|
||||
|
||||
ifeq ($(MAKECMDGOALS),lcov-dated)
|
||||
LCOV_REPORTS_DIR=$(top_srcdir)/lcov_reports-$(shell date +%Y%m%d%k%M%S)
|
||||
else
|
||||
LCOV_REPORTS_DIR=$(top_srcdir)/lcov_reports
|
||||
endif
|
||||
|
||||
lcov-reset:
|
||||
$(LCOV) -d $(top_srcdir)/dmeventd --zerocounters
|
||||
$(LCOV) -d $(top_srcdir)/libdm --zerocounters
|
||||
$(LCOV) -d $(top_srcdir)/lib --zerocounters
|
||||
$(LCOV) -d $(top_srcdir)/tools --zerocounters
|
||||
|
||||
lcov: all
|
||||
$(RM) -rf $(LCOV_REPORTS_DIR)
|
||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||
$(LCOV) -b ${top_srcdir}/libdm -d $(top_srcdir)/libdm -c -o $(LCOV_REPORTS_DIR)/libdm.info
|
||||
$(LCOV) -b $(top_srcdir)/lib -d $(top_srcdir)/lib -c -o $(LCOV_REPORTS_DIR)/lib.info
|
||||
$(LCOV) -b $(top_srcdir)/tools -d $(top_srcdir)/tools -c -o $(LCOV_REPORTS_DIR)/tools.info
|
||||
DMEVENTD_INFO="$(LCOV_REPORTS_DIR)/dmeventd.info" ;\
|
||||
DMEVENTD_INFO_A="-a $$DMEVENTDINFO" ;\
|
||||
$(LCOV) -b $(top_srcdir)/dmeventd -d $(top_srcdir)/dmeventd -c -o $$DMEVENTD_INFO || DMEVENTD_INFO_A="" ;\
|
||||
$(LCOV) $$DMEVENTD_INFO_A -a $(LCOV_REPORTS_DIR)/lib.info \
|
||||
-a $(LCOV_REPORTS_DIR)/libdm.info \
|
||||
-a $(LCOV_REPORTS_DIR)/tools.info \
|
||||
-o $(LCOV_REPORTS_DIR)/lvm.info
|
||||
ifneq ("@GENHTML@", "")
|
||||
$(GENHTML) -o $(LCOV_REPORTS_DIR) -p $(top_srcdir) $(LCOV_REPORTS_DIR)/lvm.info
|
||||
endif
|
||||
|
||||
lcov-dated: lcov
|
||||
|
||||
endif
|
||||
|
||||
18
README
18
README
@@ -1,23 +1,27 @@
|
||||
This directory contains LVM2, the new version of the userland LVM
|
||||
tools designed for the new device-mapper for the Linux kernel.
|
||||
This tree contains the LVM2 and device-mapper tools and libraries.
|
||||
|
||||
The device-mapper needs to be installed before compiling these LVM2 tools.
|
||||
|
||||
For more information about LVM2 read the WHATS_NEW file.
|
||||
For more information about LVM2 read the changelog in the WHATS_NEW file.
|
||||
Installation instructions are in INSTALL.
|
||||
|
||||
There is no warranty - see COPYING and COPYING.LIB.
|
||||
|
||||
Tarballs are available from:
|
||||
ftp://sources.redhat.com/pub/lvm2/
|
||||
ftp://sources.redhat.com/pub/dm/
|
||||
|
||||
To access the CVS tree use:
|
||||
cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
|
||||
CVS password: cvs
|
||||
cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 co LVM2
|
||||
|
||||
Mailing list for discussion/bug reports etc.
|
||||
Mailing list for general discussion related to LVM2:
|
||||
linux-lvm@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||
|
||||
Mailing list for LVM2 development, patches and commits:
|
||||
lvm-devel@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||
|
||||
Mailing list for device-mapper development, including kernel patches
|
||||
and multipath-tools:
|
||||
dm-devel@redhat.com
|
||||
Subscribe from https://www.redhat.com/mailman/listinfo/dm-devel
|
||||
|
||||
1
VERSION_DM
Normal file
1
VERSION_DM
Normal file
@@ -0,0 +1 @@
|
||||
1.02.36-cvs (2009-08-06)
|
||||
587
WHATS_NEW
587
WHATS_NEW
@@ -1,5 +1,580 @@
|
||||
Version 2.02.29 -
|
||||
==================================
|
||||
Version 2.02.51 - 6th August 2009
|
||||
=================================
|
||||
Fix locking in clvmd (2.02.50).
|
||||
Add --noudevsync option for relevant LVM tools.
|
||||
Add activation/udev_sync to lvm.conf.
|
||||
Only change LV symlinks on ACTIVATE not PRELOAD.
|
||||
Make lvconvert honour log mirror options combined with downconversion.
|
||||
Allow LV suspend while --ignorelockingfailure is in force.
|
||||
Update synopsis in lvconvert manpage to mention --repair.
|
||||
Set cookies in activation code and wait for udev to complete processing.
|
||||
Added configure --enable-udev_rules --enable-udev_sync.
|
||||
Added configure --with-udev-prefix --with-udevdir.
|
||||
Added udev dir to hold udev rules.
|
||||
Add devices/data_alignment_detection to lvm.conf.
|
||||
Add devices/data_alignment_offset_detection to lvm.conf.
|
||||
Add --dataalignmentoffset to pvcreate to shift start of aligned data area.
|
||||
Fix _mda_setup() to not check first mda's size before pe_align rounding.
|
||||
Document -I option of clvmd in the man page.
|
||||
Fix configure script to handle multiple clvmd selections.
|
||||
Fix lvm2app.pc installation filename.
|
||||
Remove pv_t, vg_t & lv_t handles from lib. Only liblvm uses them.
|
||||
Rename lvm.h to lvm2app.h for now.
|
||||
|
||||
Version 2.02.50 - 28th July 2009
|
||||
================================
|
||||
Change test/api/test.c prompt so it's not confused with the main lvm prompt.
|
||||
Update liblvm unit tests in test/api to cover latest liblvm changes.
|
||||
Add unimplemented lvm_lv_resize and lvm_pv_resize skeletons to liblvm.
|
||||
Add lvm_library_get_version to liblvm.
|
||||
Add lvm_config_override to liblvm to allow caller to override LVM config.
|
||||
Add lvm_lv_is_active and lvm_lv_is_suspended to liblvm.
|
||||
Add lvm_lv_activate and lvm_lv_deactivate to liblvm.
|
||||
Add lvm_scan, lvm_vg_reduce and lvm_vg_remove_lv to liblvm.
|
||||
Add functions to get numeric properties to liblvm.
|
||||
Add lvm_{pv|vg|lv}_get_{name|uuid} to liblvm.
|
||||
Add lvm_vg_list_pvs and lvm_vg_list_lvs to liblvm.
|
||||
Add lvm_vg_open and lvm_vg_create_lv_linear to liblvm.
|
||||
Add lvm_list_vg_names/uuids to liblvm.
|
||||
Add lvm_errno and lvm_errmsg to liblvm to obtain failure information.
|
||||
Rename lvm_create/destroy to lvm_init/quit.
|
||||
Rename lvm_reload_config to lvm_config_reload.
|
||||
Refactor _override_settings to use new override_config_tree_from_string.
|
||||
Add vg_reduce to metadata.c and metadata-exported.h.
|
||||
Update lvm.h to clarify API behavior and return codes.
|
||||
Update lvm_vg_extend to do an implicit pvcreate on the device.
|
||||
Update display.c to use vg_free(vg) instead of duplicating the calculation.
|
||||
Refactor vg_size, vg_free, and pv_mda_count field calculations for liblvm.
|
||||
Refactor pvcreate and lvcreate for liblvm.
|
||||
Add global/wait_for_locks to lvm.conf so blocking for locks can be disabled.
|
||||
All LV locks are non-blocking so remove LCK_NONBLOCK from separate macros.
|
||||
Fix race condition with vgcreate and vgextend on same device (2.02.49).
|
||||
Remove redundant validate_name call from vgreduce.
|
||||
Remove unused handles lvseg, pvseg inside liblvm/lvm.h.
|
||||
Add liblvm2app Makefile installation targets.
|
||||
Add liblvm pkgconfig file.
|
||||
Use newly-independent LVM_LIBAPI in liblvm soname. E.g. liblvm2app.so.2.1.
|
||||
Add an API version number, LVM_LIBAPI, to the VERSION string for liblvm.
|
||||
Pass a pointer to struct cmd_context to init_multiple_segtypes
|
||||
Return EINVALID_CMD_LINE not success when invalid VG name format is used.
|
||||
Remove unnecessary messages after vgcreate/vgsplit refactor (2.02.49).
|
||||
Add log_errno to set a specific errno and replace log_error in due course.
|
||||
Change create_toolcontext to still return an object if it fails part-way.
|
||||
Add EUNCLASSIFIED (-1) as the default LVM errno code.
|
||||
Store any errno and error messages issued while processing each command.
|
||||
Use log_error macro consistently throughout in place of log_err.
|
||||
|
||||
Version 2.02.49 - 15th July 2009
|
||||
================================
|
||||
Exclude VG_GLOBAL from vg_write_lock_held so scans open devs read-only again.
|
||||
Add unit test case for liblvm VG create/delete APIs.
|
||||
Add liblvm APIs to implement creation and deletion of VGs.
|
||||
Initialize cmd->cmd_line to "liblvm" in new liblvm library.
|
||||
Place handles to liblvm objects for pv, vg, lv, lvseg, pvseg inside lvm.h.
|
||||
Refactor vgsplit and vgextend to remove READ_REQUIRE_RESIZEABLE flag.
|
||||
Use _exit() not exit() after forking to avoid flushing libc buffers twice.
|
||||
Add cast to log_info arg in _find_labeller to avoid Sparc64 warning.
|
||||
Make cmd->cmd_line const.
|
||||
Fix dev name mismatch in vgcreate man page example.
|
||||
Refactor vg_remove_single for use in liblvm.
|
||||
Make all tools use consistent lock ordering obtaining VG_ORPHAN lock second.
|
||||
Check md devices for a partition table during device scan.
|
||||
Add extended device (blkext) and md partition (mdp) types to filters.
|
||||
Make text metadata read errors for segment areas more precise.
|
||||
Fix text segment metadata read errors to mention correct segment name.
|
||||
Include segment and LV names in text segment import error messages.
|
||||
Add parent node to config_node structure.
|
||||
Update vgsplit and vgcreate to call new vg_create and 'set' functions.
|
||||
Change vg_create to take minimal parameters, obtain a lock, and return vg_t.
|
||||
Refactor vgchange extent_size, max_lv, max_pv, and alloc_policy for liblvm.
|
||||
Update t-vgcreate-usage.sh to test for default vg properties.
|
||||
Fix memory leak in vgsplit when re-reading the vg.
|
||||
Make various exit/cleanup paths more robust after lvm init failures.
|
||||
Use LCK_NONBLOCK implicitly instead of explicit vg_read() flag.
|
||||
Remove unnecessary locking and existence tests from new vg_read() interface.
|
||||
Permit several segment types to be registered by a single shared object.
|
||||
Update the man pages to document size units uniformly.
|
||||
Allow commandline sizes to be specified in terms of bytes and sectors.
|
||||
Update 'md_chunk_alignment' to use stripe-width to align PV data area.
|
||||
Update test/t-inconsistent-metadata.sh to match new vg_read interface.
|
||||
Add lvmcache_init() to polldaemon initialization.
|
||||
Convert tools to use new vg_read / vg_read_for_update.
|
||||
Fix segfault in vg_release when vg->cmd is NULL.
|
||||
|
||||
Version 2.02.48 - 30th June 2009
|
||||
================================
|
||||
Abort if automatic metadata correction fails when reading VG to update it.
|
||||
Explicitly request fallback to default major number in device mapper.
|
||||
Ignore suspended devices during repair.
|
||||
Call vgreduce --removemissing automatically to fix missing PVs in dmeventd.
|
||||
Suggest using lvchange --resync when adding leg to not-yet-synced mirror.
|
||||
Destroy toolcontext on clvmd exit to avoid memory pool leaks.
|
||||
Fix lvconvert not to poll mirror if no conversion in progress.
|
||||
Fix memory leaks in toolcontext error path.
|
||||
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.
|
||||
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.
|
||||
Fix possible double release of VG after recovery.
|
||||
Add parameter to process_each_vg specifying what to do with inconsistent VG.
|
||||
Unify error messages when processing inconsistent volume group.
|
||||
Use lvconvert --repair instead of vgreduce in mirror dmeventd DSO.
|
||||
Introduce lvconvert --use_policies (repair policy according to lvm.conf).
|
||||
Update clvmd-corosync to match new corosync API.
|
||||
Fix lib Makefile to include any shared libraries in default target.
|
||||
Fix rename of active snapshot with virtual origin.
|
||||
Fix convert polling to ignore LV with different UUID.
|
||||
Cache underlying device readahead only before activation calls.
|
||||
Fix segfault when calculating readahead on missing device in vgreduce.
|
||||
Remove verbose 'visited' messages.
|
||||
Handle multi-extent mirror log allocation when smallest PV has only 1 extent.
|
||||
Add LSB standard headers and functions (incl. reload) to clvmd initscript.
|
||||
When creating new LV, double-check that name is not already in use.
|
||||
Remove /dev/vgname/lvname symlink automatically if LV is no longer visible.
|
||||
Rename internal vorigin LV to match visible LV.
|
||||
Suppress 'removed' messages displayed when internal LVs are removed.
|
||||
Fix lvchange -a and -p for sparse LVs.
|
||||
Fix lvcreate --virtualsize to activate the new device immediately.
|
||||
Make --snapshot optional with lvcreate --virtualsize.
|
||||
Generalise --virtualoriginsize to --virtualsize.
|
||||
Skip virtual origins in process_each_lv_in_vg() without --all.
|
||||
Fix counting of virtual origin LVs in vg_validate.
|
||||
Attempt to load dm-zero module if zero target needed but not present.
|
||||
|
||||
Version 2.02.47 - 22nd May 2009
|
||||
===============================
|
||||
Rename liblvm.so to liblvm2app.so and use configure --enable-applib.
|
||||
Reinstate version in liblvm2cmd.so soname. (2.02.44)
|
||||
|
||||
Version 2.02.46 - 21st May 2009
|
||||
===============================
|
||||
Inherit readahead setting from underlying devices during activation.
|
||||
Detect LVs active on remote nodes by querying locks if supported.
|
||||
Enable online resizing of mirrors.
|
||||
Use suspend with flush when device size was changed during table preload.
|
||||
Implement query_resource_fn for cluster_locking.
|
||||
Support query_resource_fn in locking modules.
|
||||
Introduce CLVMD_CMD_LOCK_QUERY command for clvmd.
|
||||
Fix pvmove to revert operation if temporary mirror creation fails.
|
||||
Fix metadata export for VG with missing PVs.
|
||||
Add vgimportclone and install it and the man page by default.
|
||||
Force max_lv restriction only for newly created LV.
|
||||
Remove unneeded import parameter from lv_create_empty.
|
||||
Merge lv_is_displayable and lv_is_visible functions.
|
||||
Introduce lv_set_visible & lv_set_hidden functions.
|
||||
Fix lv_is_visible to handle virtual origin.
|
||||
Introduce link_lv_to_vg and unlink_lv_from_vg functions.
|
||||
Remove lv_count from VG and use counter function instead.
|
||||
Fix snapshot segment import to not use duplicate segments & replace.
|
||||
Do not query nonexistent devices for readahead.
|
||||
Remove NON_BLOCKING lock flag from tools and set a policy to auto-set.
|
||||
Remove snapshot_count from VG and use function instead.
|
||||
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)
|
||||
Add sparse devices: lvcreate -s --virtualoriginsize (hidden zero origin).
|
||||
Fix minimum width of devices column in reports.
|
||||
Add lvs origin_size field.
|
||||
Fix linux configure --enable-debug to exclude -O2.
|
||||
Implement lvconvert --repair for repairing partially-failed mirrors.
|
||||
Fix vgreduce --removemissing failure exit code.
|
||||
Fix remote metadata backup for clvmd.
|
||||
Introduce unlock_and_release_vg macro.
|
||||
Introduce vg_release() to be called to free every struct volume_group.
|
||||
Alloc PV internal structure from VG mempool if possible.
|
||||
Fix metadata backup to run after vg_commit always.
|
||||
Tidy clvmd volume lock cache functions.
|
||||
Fix pvs report for orphan PVs when segment attributes are requested.
|
||||
Fix pvs -a output to not read volume groups from non-PV devices.
|
||||
Add MMC (mmcblk) device type to filters.
|
||||
Introduce memory pools per volume group (to reduce memory for large VGs).
|
||||
Use copy of PV structure when manipulating global PV lists.
|
||||
Always return exit error status when locking of volume group fails.
|
||||
Fix mirror log convert validation question.
|
||||
Avoid referencing files from DESTDIR during build process.
|
||||
Avoid creating some static libraries unless configured --enable-static_link.
|
||||
Enable use of cached metadata for pvs and pvdisplay commands.
|
||||
Add missing 'device-mapper' internal subdir build dependency.
|
||||
Fix memory leak in mirror allocation code.
|
||||
Save and restore the previous logging level when log level is changed.
|
||||
Fix error message when archive initialization fails.
|
||||
Make sure clvmd-corosync releases the lockspace when it exits.
|
||||
Fix segfault for vgcfgrestore on VG with missing PVs.
|
||||
Block SIGTERM & SIGINT in clvmd subthreads.
|
||||
Detect and conditionally wipe swapspace signatures in pvcreate.
|
||||
Fix maximal volume count check for snapshots if max_lv set for volume group.
|
||||
Fix lvcreate to remove unused cow volume if the snapshot creation fails.
|
||||
Fix error messages when PV uuid or pe_start reading fails.
|
||||
Build new liblvm application-level library.
|
||||
Rename liblvm.a to liblvm-internal.a.
|
||||
Flush memory pool and fix locking in clvmd refresh and backup command.
|
||||
Fix unlocks in clvmd-corosync. (2.02.45)
|
||||
Fix error message when adding metadata directory to internal list fails.
|
||||
Fix size and error message of memory allocation at backup initialization.
|
||||
Remove old metadata backup file after renaming VG.
|
||||
Restore log_suppress state when metadata backup file is up-to-date.
|
||||
|
||||
Version 2.02.45 - 3rd March 2009
|
||||
================================
|
||||
Avoid scanning empty metadata areas for VG names.
|
||||
Attempt proper clean up in child before executing new binary in exec_cmd().
|
||||
Do not scan devices if reporting only attributes from PV label.
|
||||
Use pkgconfig to obtain corosync library details during configuration.
|
||||
Fix error returns in clvmd-corosync interface to DLM.
|
||||
Add --refresh to vgchange and vgmknodes man pages.
|
||||
Pass --test from lvresize to fsadm as --dry-run.
|
||||
Supply argv[] list to exec_cmd() to allow for variable number of parameters.
|
||||
Prevent fsadm from checking mounted filesystems.
|
||||
No longer treats any other key as 'no' when prompting in fsadm.
|
||||
Tidy fsadm command line processing.
|
||||
Add lib/lvm.h and lib/lvm_base.c for the new library interface.
|
||||
Move tools/version.h to lib/misc/lvm-version.h.
|
||||
Split LVM_VERSION into MAJOR, MINOR, PATCHLEVEL, RELEASE and RELEASE_DATE.
|
||||
Add system_dir parameter to create_toolcontext().
|
||||
Add --dataalignment to pvcreate to specify alignment of data area.
|
||||
Exclude LCK_CACHE locks from _vg_lock_count, fixing interrupt unblocking.
|
||||
Provide da and mda locations in debug message when writing text format label.
|
||||
Mention the restriction on file descriptors at invocation on the lvm man page.
|
||||
Index cached vgmetadata by vgid not vgname to cope with duplicate vgnames.
|
||||
No longer require kernel and metadata major numbers to match.
|
||||
Add a fully-functional get_cluster_name() to clvmd corosync interface.
|
||||
Remove duplicate cpg_initialize from clvmd startup.
|
||||
Add option to /etc/sysconfig/cluster to select cluster type for clvmd.
|
||||
Allow clvmd to start up if its lockspace already exists.
|
||||
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.
|
||||
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.
|
||||
Mention --with-clvmd=corosync in ./configure.
|
||||
Replace internal vg_check_status() implementation.
|
||||
Rename vg_read() to vg_read_internal().
|
||||
|
||||
Version 2.02.44 - 26th January 2009
|
||||
===================================
|
||||
Fix --enable-static_link after the recent repository changes.
|
||||
Add corosync/DLM cluster interface to clvmd.
|
||||
Add --nameprefixes, --unquoted, --rows to pvs, vgs, lvs man pages.
|
||||
Fix lvresize size conversion for fsadm when block size is not 1K.
|
||||
Fix pvs segfault when run with orphan PV and some VG fields.
|
||||
Display a 'dev_size' of zero for missing devices in reports.
|
||||
Add pv_mda_size to pvs and vg_mda_size to vgs.
|
||||
Fix lvmdump /sys listing to include virtual devices directory.
|
||||
Add "--refresh" functionality to vgchange and vgmknodes.
|
||||
Avoid exceeding LV size when wiping device.
|
||||
Calculate mirror log size instead of using 1 extent.
|
||||
Ensure requested device number is available before activating with it.
|
||||
Fix incorrect exit status from 'help <command>'.
|
||||
Fix vgrename using UUID if there are VGs with identical names.
|
||||
Fix segfault when invalid field given in reporting commands.
|
||||
Move is_static from cmd to global is_static().
|
||||
Refactor init_lvm() for lvmcmdline and clvmd.
|
||||
Add liblvm interactive test infrastructure to build.
|
||||
Add skeleton lvm2.h file in preparation for a shared library interface.
|
||||
Use better random seed value in temp file creation.
|
||||
Add read_urandom to read /dev/urandom. Use in uuid calculation.
|
||||
Use displayable_lvs_in_vg and lv_is_displayable for consistency throughout.
|
||||
Fix race in vgcreate that would result in second caller overwriting first.
|
||||
Fix uninitialised lv_count in vgdisplay -c.
|
||||
Don't skip updating pvid hash when lvmcache_info struct got swapped.
|
||||
Add tinfo to termcap search path for pld-linux.
|
||||
Fix startup race in clvmd.
|
||||
Generate Red Hat clvmd startup script at config time with correct paths.
|
||||
Fix clvmd & dmeventd builds after tree restructuring.
|
||||
Cope with snapshot dependencies when removing a whole VG with lvremove.
|
||||
Make man pages and tool help text consistent using | for alternative options.
|
||||
|
||||
Version 2.02.43 - 10th November 2008
|
||||
====================================
|
||||
Merge device-mapper into the lvm2 tree.
|
||||
Correct prototype for --permission on lvchange and lvcreate man pages.
|
||||
Exit with non-zero status from vgdisplay if couldn't show any requested VG.
|
||||
Move list.c into libdevmapper and rename functions.
|
||||
Rename a couple of variables that matched function names.
|
||||
Use simplified x.y.z version number in libdevmapper.pc.
|
||||
Remove ancient debian directory.
|
||||
Split out lvm-logging.h from log.h and lvm-globals.[ch] from log.[ch].
|
||||
|
||||
Version 2.02.42 - 26th October 2008
|
||||
===================================
|
||||
Accept locking fallback_to_* options in the global section as documented.
|
||||
Fix temp table activation in mirror conversions not to happen in other cmds.
|
||||
Fix temp table in mirror conversions to use always-present error not zero.
|
||||
|
||||
Version 2.02.41 - 17th October 2008
|
||||
===================================
|
||||
Use temp table to set device size when converting mirrors.
|
||||
In resume_mirror_images replace activate_lv with resume_lv as workaround.
|
||||
Avoid overwriting in-use on-disk text metadata by forgetting MDA_HEADER_SIZE.
|
||||
Fix snapshot monitoring library to not cancel monitoring invalid snapshot.
|
||||
Generate man pages from templates and include version.
|
||||
Add usrlibdir and usrsbindir to configure.
|
||||
Fix conversion of md chunk size into sectors.
|
||||
Free text metadata buffer after a failure writing it.
|
||||
Fix misleading error message when there are no allocatable extents in VG.
|
||||
Fix handling of PVs which reappeared with old metadata version.
|
||||
Fix mirror DSO to call vgreduce with proper parameters.
|
||||
Fix validation of --minor and --major in lvcreate to require -My always.
|
||||
Fix release: clvmd build, vgreduce consolidate & tests, /dev/ioerror warning.
|
||||
|
||||
Version 2.02.40 - 19th September 2008
|
||||
=====================================
|
||||
Allow lvremove to remove LVs from VGs with missing PVs.
|
||||
In VG with PVs missing, by default allow activation of LVs that are complete.
|
||||
Track PARTIAL_LV and MISSING_PV flags internally.
|
||||
Require --force with --removemissing in vgreduce to remove partial LVs.
|
||||
No longer write out PARTIAL flag into metadata backups.
|
||||
Treat new default activation/missing_stripe_filler "error" as an error target.
|
||||
Remove internal partial_mode.
|
||||
Add devices/md_chunk_alignment to lvm.conf.
|
||||
Pass struct physical_volume to pe_align and adjust for md chunk size.
|
||||
Store sysfs location in struct cmd_context.
|
||||
Avoid shuffling remaining mirror images when removing one, retaining primary.
|
||||
Add missing LV error target activation in _remove_mirror_images.
|
||||
Prevent resizing an LV while lvconvert is using it.
|
||||
Avoid repeatedly wiping cache while VG_GLOBAL is held in vgscan & pvscan.
|
||||
Fix pvresize to not allow resize if PV has two metadata areas.
|
||||
Fix setting of volume limit count if converting to lvm1 format.
|
||||
Fix vgconvert logical volume id metadata validation.
|
||||
Fix lvmdump metadata gather option (-m) to work correctly.
|
||||
Fix allocation bug in text metadata format write error path.
|
||||
Fix vgcfgbackup to properly check filename if template is used.
|
||||
configure aborts if lcov or genhtml are missing with --enable-profiling
|
||||
vgremove tries to remove lv snapshot first.
|
||||
Added function lv_remove_with_dependencies().
|
||||
Improve file descriptor leak detection to display likely culprit and filename.
|
||||
Change clustered mirror kernel module name from cmirror to dm-log-clustered.
|
||||
Avoid looping forever in _pv_analyze_mda_raw used by pvck.
|
||||
Change lvchange exit status to indicate if any part of the operation failed.
|
||||
Fix pvchange and pvremove to handle PVs without mdas.
|
||||
Refactor _text_pv_read and always return mda list if requested.
|
||||
Fix configure to work w/o readline unless --enable-readline used. (2.02.39)
|
||||
Remove is_lvm_partition template which has not yet been coded.
|
||||
Refactor pvcreate to separate parameter parsing from validation logic.
|
||||
Check for label_write() failure in _text_pv_write().
|
||||
Add pvcreate tests and update vgsplit tests to handle lvm1 and lvm2 metadata.
|
||||
Fix pvchange -M1 -u to preserve existing extent locations when there's a VG.
|
||||
Cease recognising snapshot-in-use percentages returned by early devt kernels.
|
||||
Add backward-compatible flags field to on-disk format_text metadata.
|
||||
Fix dmeventd monitoring libraries to link against liblvm2cmd again. (2.02.39)
|
||||
|
||||
Version 2.02.39 - 27th June 2008
|
||||
================================
|
||||
Enable readline by default if available.
|
||||
Update autoconf to 2008-01-16.
|
||||
Add $DISTCLEAN_DIRS to make.tmpl.in.
|
||||
Create coverage reports with --enable-profiling and make lcov or lcov-dated.
|
||||
Fix up cache for PVs without mdas after consistent VG metadata is processed.
|
||||
Update validation of safe mirror log type conversions in lvconvert.
|
||||
Fix lvconvert to disallow snapshot and mirror combinations.
|
||||
Fix reporting of LV fields alongside unallocated PV segments.
|
||||
Add --unquoted and --rows to reporting tools.
|
||||
Add and use uninitialized_var() macro to suppress invalid compiler warnings.
|
||||
Introduce enum for md minor sb version to suppress compiler warning.
|
||||
Avoid undefined return value after _memlock manipulation in lvm2_run.
|
||||
Avoid link failure if configured without --enable-cmdlib or --enable-readline.
|
||||
Make clvmd return at once if other nodes down in a gulm or openais cluster.
|
||||
Fix and improve readahead 'auto' calculation for stripe_size.
|
||||
Fix lvchange output for -r auto setting if auto is already set.
|
||||
Add test case for readahead.
|
||||
Avoid ambiguous use of identifier error_message_produced.
|
||||
Begin syncing configure.in for merge/unification with device-mapper.
|
||||
Fix add_mirror_images not to dereference uninitialized log_lv upon failure.
|
||||
Don't call openlog for every debug line output by clvmd.
|
||||
Add --force to lvextend and lvresize.
|
||||
Fix vgchange not to activate component mirror volumes directly.
|
||||
Fix test directory clean up in make distclean.
|
||||
|
||||
Version 2.02.38 - 11th June 2008
|
||||
================================
|
||||
Fix tracking of validity of PVs with no mdas in lvmcache.
|
||||
Fix return values for reporting commands when run with no PVs, LVs, or VGs.
|
||||
Add omitted unlock_vg() call when sigint_caught() during vg processing.
|
||||
Fix free_count when reading pool metadata.
|
||||
Fix segfault when using pvcreate on a device containing pool metadata.
|
||||
Fix segfault after _free_vginfo by remembering to remove vginfo from list.
|
||||
Tweak detection of invalid fid after changes to PVs in VG in _vg_read.
|
||||
Revert assuming precommitted metadata is live when activating (unnecessary).
|
||||
Drop cached metadata for disappearing VG in vgmerge.
|
||||
In script-processing mode, stop if any command fails.
|
||||
Warn if command exits with non-zero status code without a prior log_error.
|
||||
Check lv_count in vg_validate.
|
||||
Add --nameprefixes to reporting tools for field name prefix output format.
|
||||
|
||||
Version 2.02.37 - 6th June 2008
|
||||
===============================
|
||||
Make clvmd-cman use a hash rather than an array for node updown info.
|
||||
Correct config file line numbers in messages when parsing comments.
|
||||
Drop cached metadata when renaming a VG.
|
||||
Allow for vginfo changing during _vg_read.
|
||||
Decode numbers in clvmd debugging output.
|
||||
Add missing deactivation after activation failure in lvcreate -Zy.
|
||||
When activating, if precommitted metadata is still cached, assume it's live.
|
||||
When removing LV symlinks, skip any where the VG name is not determined.
|
||||
Drop metadata cache if update fails in vg_revert or vg_commit.
|
||||
Avoid spurious duplicate VG messages referring to VGs that are gone.
|
||||
Drop dev_name_confirmed error message to debug level.
|
||||
Fix setpriority error message to signed int.
|
||||
Temporarily disable dmeventd mirror monitoring during lvchange --resync.
|
||||
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.
|
||||
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.
|
||||
Don't touch /dev in vgrename if activation is disabled.
|
||||
|
||||
Version 2.02.36 - 29th April 2008
|
||||
=================================
|
||||
Fix fsadm.sh to work with older blockdev, blkid & readlink binaries.
|
||||
Fix lvresize to pass new size to fsadm when extending device.
|
||||
Remove unused struct in clvmd-openais, and use correct node count.
|
||||
Fix nodes list in clvmd-openais, and allow for broadcast messages.
|
||||
Exclude VG_GLOBAL from internal concurrent VG lock counter.
|
||||
Fix vgsplit internal counting of snapshot LVs.
|
||||
Fix vgmerge snapshot_count when source VG contains snapshots.
|
||||
Simplify clvmd-openais by using non-async saLckResourceLock.
|
||||
Fix internal LV counter when a snapshot is removed.
|
||||
Fix metadata corruption writing lvm1-formatted metadata with snapshots.
|
||||
Fix lvconvert -m0 allocatable space check.
|
||||
|
||||
Version 2.02.35 - 15th April 2008
|
||||
=================================
|
||||
Drop cached VG metadata before and after committing changes to it.
|
||||
Rename P_global to P_#global.
|
||||
Don't attempt remote metadata backups of non-clustered VGs. (2.02.29)
|
||||
Don't store fid in VG metadata cache to avoid clvmd segfault. (2.02.34)
|
||||
Update vgsplit tests to verify loosening of active LV restriction.
|
||||
Update vgsplit to only restrict split with active LVs involved in split.
|
||||
Add lv_is_active() to determine whether an lv is active.
|
||||
|
||||
Version 2.02.34 - 10th April 2008
|
||||
=================================
|
||||
Improve preferred_names lvm.conf example.
|
||||
Fix vgdisplay 'Cur LV' field to match lvdisplay output.
|
||||
Fix lv_count report field to exclude hidden LVs.
|
||||
Add vg_is_clustered() helper function.
|
||||
Fix vgsplit to only move hidden 'snapshotN' LVs when necessary.
|
||||
Update vgsplit tests for lvnames on the cmdline.
|
||||
Update vgsplit man page to reflect lvnames on the cmdline.
|
||||
Update vgsplit to take "-n LogicalVolumeName" on the cmdline.
|
||||
Use clustered mirror log with pvmove in clustered VGs, if available.
|
||||
Fix some pvmove error status codes.
|
||||
Fix vgsplit error paths to release vg_to lock.
|
||||
Indicate whether or not VG is clustered in vgcreate log message.
|
||||
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.
|
||||
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.
|
||||
Fix output if overriding command_names on cmdline.
|
||||
Add detection of clustered mirror log capability.
|
||||
Add check to vg_commit() ensuring VG lock held before writing new VG metadata.
|
||||
Add validation of LV name to pvmove -n.
|
||||
Make clvmd refresh the context correctly when lvm.conf is updated.
|
||||
Add some basic internal VG lock validation.
|
||||
Add per-command flags to control which commands use the VG metadata cache.
|
||||
Fix vgsplit locking of new VG (2.02.30).
|
||||
Avoid erroneous vgsplit error message for new VG. (2.02.29)
|
||||
Suppress duplicate message when lvresize fails because of invalid vgname.
|
||||
Cache VG metadata internally while VG lock is held.
|
||||
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.
|
||||
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.
|
||||
Add 'is_reserved_lvname()' for identifying hidden LVs.
|
||||
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.
|
||||
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.
|
||||
Use return_0 in a couple more places.
|
||||
Correct a function name typo in _line_append error message.
|
||||
Include limits.h in clvmd so it compiles with newer headers.
|
||||
Add VirtIO disks (virtblk) to filters.
|
||||
Fix resetting of MIRROR_IMAGE and VISIBLE_LV after removal of LV. (2.02.30)
|
||||
Fix remove_layer_from_lv to empty the LV before removing it. (2.02.30)
|
||||
Add missing no-longer-used segs_using_this_lv test to check_lv_segments.
|
||||
Remove redundant non-NULL tests before calling free in clvmd.c.
|
||||
Avoid a compiler warning: make is_orphan's parameter const.
|
||||
Fix lvconvert detection of mirror conversion in progress. (2.02.30)
|
||||
Avoid automatic lvconvert polldaemon invocation when -R specified. (2.02.30)
|
||||
Fix 'pvs -a' to detect VGs of PVs without metadata areas.
|
||||
Divide up internal orphan volume group by format type.
|
||||
Update usage message for clvmd.
|
||||
Fix clvmd man page not to print <br> and clarified debug options.
|
||||
Fix lvresize to support /dev/mapper prefix in the LV name.
|
||||
Fix unfilled parameter passed to fsadm from lvresize.
|
||||
Update fsadm to call lvresize if the partition size differs (with option -l).
|
||||
Fix fsadm to support VG/LV names.
|
||||
|
||||
Version 2.02.33 - 31st January 2008
|
||||
===================================
|
||||
Fix mirror log name construction during lvconvert. (2.02.30)
|
||||
Make monitor_dev_for_events recurse through the stack of LVs.
|
||||
Clean up some more compiler warnings.
|
||||
Some whitespace tidy-ups.
|
||||
Use stack return macros throughout.
|
||||
Rely upon internally-cached PV labels while corresponding VG lock is held.
|
||||
|
||||
Version 2.02.32 - 29th January 2008
|
||||
===================================
|
||||
Fix two check_lv_segments error messages to show whole segment.
|
||||
Refactor mirror log attachment code.
|
||||
Fix internal metadata corruption in lvchange --resync. (2.02.30)
|
||||
Fix new parameter validation in vgsplit and test mode. (2.02.30)
|
||||
Remove redundant cnxman-socket.h file from clvmd directory.
|
||||
Fix pvs, vgs, lvs error exit status on some error paths.
|
||||
|
||||
Version 2.02.31 - 19th January 2008
|
||||
===================================
|
||||
Fix lvcreate --nosync not to wait for non-happening sync. (2.02.30)
|
||||
Add very_verbose lvconvert messages.
|
||||
Avoid readahead error message with default setting of lvcreate -M1. (2.02.29)
|
||||
|
||||
Version 2.02.30 - 17th January 2008
|
||||
===================================
|
||||
Set default readahead to twice maximium 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.
|
||||
Fix process_all_pvs to detect non-orphans with no MDAs correctly.
|
||||
Don't use block_on_error with mirror targets version 1.12 and above.
|
||||
Update vgsplit to accept vgcreate options when new VG is destination.
|
||||
Update vgsplit to accept existing VG as destination.
|
||||
lvconvert waits for completion of initial sync by default.
|
||||
Refactor vgcreate for parameter validation and add tests.
|
||||
Add new convert_lv field to lvs output.
|
||||
Print warning when lvm tools are running as non-root.
|
||||
Add snapshot dmeventd library (enables dmeventd snapshot monitoring).
|
||||
Prevent pvcreate from overwriting MDA-less PVs belonging to active VGs.
|
||||
Fix a segfault if using pvs with --all argument. (2.02.29)
|
||||
Update --uuid argument description in man pages.
|
||||
Fix vgreduce PV list processing not to process every PV in the VG. (2.02.29)
|
||||
Extend lvconvert to use polldaemon.
|
||||
Add support for stacked mirrors.
|
||||
Major restructuring of pvmove and lvconvert layer manipulation code.
|
||||
Replace tools/fsadm with scripts/fsadm.sh.
|
||||
Append fields to report/pvsegs_cols_verbose.
|
||||
Permit LV segment fields with PV segment reports.
|
||||
Add seg_start_pe and seg_pe_ranges to reports.
|
||||
|
||||
Version 2.02.29 - 5th December 2007
|
||||
===================================
|
||||
Make clvmd backup vg metadata on remote nodes.
|
||||
Refactor pvmove allocation code.
|
||||
Decode cluster locking state in log message.
|
||||
@@ -36,14 +611,16 @@ Version 2.02.29 -
|
||||
Add const attributes to pv accessor functions.
|
||||
Refactor vg_add_snapshot() and lv_create_empty().
|
||||
Handle new sysfs subsystem/block/devices directory structure.
|
||||
Tests are run with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
|
||||
Run test with LVM_SYSTEM_DIR pointing to private root and /dev dirs.
|
||||
Fix a bug in lvm_dump.sh checks for lvm/dmsetup binaries.
|
||||
Fix underquotations in lvm_dump.sh.
|
||||
Refactor lvcreate stripe and mirror parameter validation.
|
||||
All tools: print --help output to stdout, not stderr.
|
||||
After a diagnostic, suggest --help, rather than printing all --help output.
|
||||
Print --help output to stdout, not stderr.
|
||||
After a cmdline processing error, don't print help text but suggest --help.
|
||||
Add %PVS extents option to lvresize, lvextend, and lvcreate.
|
||||
Add 'make check' to run tests in new subdirectory 'test'.
|
||||
Moved the obsolete test subdirectory to old-tests.
|
||||
Cope with relative paths in configure --with-dmdir.
|
||||
Remove no-longer-correct restrictions on PV arg count with stripes/mirrors.
|
||||
Fix strdup memory leak in str_list_dup().
|
||||
Link with -lpthread when static SELinux libraries require that.
|
||||
|
||||
99
WHATS_NEW_DM
99
WHATS_NEW_DM
@@ -1,10 +1,104 @@
|
||||
Version 1.02.36 - 6th August 2009
|
||||
=================================
|
||||
Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
|
||||
Add libdevmapper functions to support synchronisation with udev.
|
||||
|
||||
Version 1.02.35 - 28th July 2009
|
||||
================================
|
||||
Add LOG_LINE_WITH_ERRNO macro.
|
||||
Use log_error macro consistently throughout in place of log_err.
|
||||
|
||||
Version 1.02.34 - 15th July 2009
|
||||
================================
|
||||
Use _exit() not exit() after forking to avoid flushing libc buffers twice.
|
||||
Rename plog macro to LOG_LINE & add LOG_MESG variant for dm_dump_memory_debug.
|
||||
Change plog to use dm_log_with_errno unless deprecated dm_log_init was used.
|
||||
Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns.
|
||||
Fix whitespace in linear target line to fix identical table line detection.
|
||||
Add device number to more log messages during activation.
|
||||
|
||||
Version 1.02.33 - 30th June 2009
|
||||
================================
|
||||
Don't fallback to default major number: use dm_task_set_major_minor. (1.02.31)
|
||||
Do not fork daemon when dmeventd cannot be found.
|
||||
Add crypt target handling to libdevmapper tree nodes.
|
||||
Add splitname command to dmsetup.
|
||||
Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports.
|
||||
Make mempool optional in dm_split_lvm_name().
|
||||
|
||||
Version 1.02.32 - 21st May 2009
|
||||
===============================
|
||||
Only generate libdevmapper.a when configured to link statically.
|
||||
Export dm_tree_node_size_changed() from libdevmapper.
|
||||
Propagate the table size_changed property up the dm device tree.
|
||||
Detect failure to free memory pools when releasing the library.
|
||||
Fix segfault when getopt processes dmsetup -U, -G and -M options.
|
||||
|
||||
Version 1.02.31 - 3rd March 2009
|
||||
================================
|
||||
If kernel supports only one dm major number, use in place of any supplied.
|
||||
|
||||
Version 1.02.30 - 26th January 2009
|
||||
====================================
|
||||
Add "all" field to reports expanding to all fields of report type.
|
||||
Enforce device name length and character limitations in libdm.
|
||||
Replace _dm_snprintf with EMIT_PARAMS macro for creating target lines.
|
||||
|
||||
Version 1.02.29 - 10th November 2008
|
||||
====================================
|
||||
Merge device-mapper into the LVM2 tree.
|
||||
Split out dm-logging.h from log.h.
|
||||
Use lvm-types.h.
|
||||
Add usrsbindir to configure.
|
||||
|
||||
Version 1.02.28 - 18th September 2008
|
||||
=====================================
|
||||
Only resume devices in dm_tree_preload_children if size changes.
|
||||
Extend deptree buffers so the largest possible device numbers fit.
|
||||
Generate versioned libdevmapper-event.so.
|
||||
Underline longer report help text headings.
|
||||
|
||||
Version 1.02.27 - 25th June 2008
|
||||
================================
|
||||
Align struct memblock in dbg_malloc for sparc.
|
||||
Add --unquoted and --rows to dmsetup.
|
||||
Avoid compiler warning about cast in dmsetup.c's OFFSET_OF macro.
|
||||
Fix inverted no_flush debug message.
|
||||
Remove --enable-jobs from configure. (Set at runtime instead.)
|
||||
Bring configure.in and list.h into line with the lvm2 versions.
|
||||
|
||||
Version 1.02.26 - 6th June 2008
|
||||
===============================
|
||||
Initialise params buffer to empty string in _emit_segment.
|
||||
Skip add_dev_node when ioctls disabled.
|
||||
Make dm_hash_iter safe against deletion.
|
||||
Accept a NULL pointer to dm_free silently.
|
||||
Add tables_loaded, readonly and suspended columns to reports.
|
||||
Add --nameprefixes to dmsetup.
|
||||
Add field name prefix option to reporting functions.
|
||||
Calculate string size within dm_pool_grow_object.
|
||||
|
||||
Version 1.02.25 - 10th April 2008
|
||||
=================================
|
||||
Remove redundant if-before-free tests.
|
||||
Use log_warn for reporting field help text instead of log_print.
|
||||
Change cluster mirror log type name (s/clustered_/clustered-/)
|
||||
|
||||
Version 1.02.24 - 20th December 2007
|
||||
====================================
|
||||
Fix deptree to pass new name to _resume_node after a rename.
|
||||
Suppress other node operations if node is deleted.
|
||||
Add node operation stack debug messages.
|
||||
Report error when empty device name passed to readahead functions.
|
||||
Fix minimum readahead debug message.
|
||||
|
||||
Version 1.02.23 - 5th December 2007
|
||||
===================================
|
||||
Update dm-ioctl.h after removal of compat code.
|
||||
Add readahead support to libdevmapper and dmsetup.
|
||||
Fix double free in a libdevmapper-event error path.
|
||||
Fix configure --with-dmeventd-path substitution.
|
||||
Allow a DM_DEV_DIR environment variable to override /dev.
|
||||
Allow a DM_DEV_DIR environment variable to override /dev in dmsetup.
|
||||
Create a libdevmapper.so.$LIB_VERSION symlink within the build tree.
|
||||
Avoid static link failure with some SELinux libraries that require libpthread.
|
||||
Remove obsolete dmfs code from tree and update INSTALL.
|
||||
@@ -22,7 +116,7 @@ Version 1.02.22 - 21st August 2007
|
||||
Version 1.02.21 - 13th July 2007
|
||||
================================
|
||||
Introduce _LOG_STDERR to send log_warn() messages to stderr not stdout.
|
||||
Fix dmsetup -o devno string termination. (1.02.20)
|
||||
Fix dmsetup -o devno string termination. (1.02.20)
|
||||
|
||||
Version 1.02.20 - 15th June 2007
|
||||
================================
|
||||
@@ -310,4 +404,3 @@ 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.
|
||||
|
||||
|
||||
60
autoconf/config.guess
vendored
60
autoconf/config.guess
vendored
@@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
|
||||
# Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2006-07-02'
|
||||
timestamp='2008-01-23'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -56,8 +56,8 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -161,6 +161,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
sh5el) machine=sh5le-unknown ;;
|
||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format, if it has switched
|
||||
@@ -329,7 +330,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
|
||||
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:*)
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
sun4*:SunOS:6*:*)
|
||||
@@ -531,7 +532,7 @@ EOF
|
||||
echo rs6000-ibm-aix3.2
|
||||
fi
|
||||
exit ;;
|
||||
*:AIX:*:[45])
|
||||
*:AIX:*:[456])
|
||||
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
|
||||
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
|
||||
IBM_ARCH=rs6000
|
||||
@@ -780,7 +781,7 @@ EOF
|
||||
i*:CYGWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-cygwin
|
||||
exit ;;
|
||||
i*:MINGW*:*)
|
||||
*:MINGW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit ;;
|
||||
i*:windows32*:*)
|
||||
@@ -790,12 +791,18 @@ EOF
|
||||
i*:PW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-pw32
|
||||
exit ;;
|
||||
x86:Interix*:[3456]*)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
EM64T:Interix*:[3456]*)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:Interix*:[3456]*)
|
||||
case ${UNAME_MACHINE} in
|
||||
x86)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
EM64T | authenticamd)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
IA64)
|
||||
echo ia64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
esac ;;
|
||||
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
|
||||
echo i${UNAME_MACHINE}-pc-mks
|
||||
exit ;;
|
||||
@@ -829,7 +836,14 @@ EOF
|
||||
echo ${UNAME_MACHINE}-pc-minix
|
||||
exit ;;
|
||||
arm*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
eval $set_cc_for_build
|
||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_EABI__
|
||||
then
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
else
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
|
||||
fi
|
||||
exit ;;
|
||||
avr32*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
@@ -950,6 +964,9 @@ EOF
|
||||
x86_64:Linux:*:*)
|
||||
echo x86_64-unknown-linux-gnu
|
||||
exit ;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
i*86:Linux:*:*)
|
||||
# The BFD linker knows what the default object file format is, so
|
||||
# first see if it will tell us. cd to the root directory to prevent
|
||||
@@ -1208,6 +1225,15 @@ EOF
|
||||
SX-6:SUPER-UX:*:*)
|
||||
echo sx6-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-7:SUPER-UX:*:*)
|
||||
echo sx7-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-8:SUPER-UX:*:*)
|
||||
echo sx8-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-8R:SUPER-UX:*:*)
|
||||
echo sx8r-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -1458,9 +1484,9 @@ This script, last modified $timestamp, has failed to recognize
|
||||
the operating system you are using. It is advised that you
|
||||
download the most up to date version of the config scripts from
|
||||
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
and
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
|
||||
If the version you run ($0) is already up to date, please
|
||||
send the following data and any information you think might be
|
||||
|
||||
66
autoconf/config.sub
vendored
66
autoconf/config.sub
vendored
@@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
|
||||
# Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2006-09-20'
|
||||
timestamp='2008-01-16'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@@ -72,8 +72,8 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -245,12 +245,12 @@ case $basic_machine in
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| fido | fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore \
|
||||
| maxq | mb | microblaze | mcore | mep \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
@@ -324,7 +324,7 @@ case $basic_machine in
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
@@ -369,10 +369,14 @@ case $basic_machine in
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| xstormy16-* | xtensa-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-*)
|
||||
;;
|
||||
# Recognize the basic CPU types without company name, with glob match.
|
||||
xtensa*)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
386bsd)
|
||||
@@ -443,6 +447,14 @@ case $basic_machine in
|
||||
basic_machine=ns32k-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
blackfin)
|
||||
basic_machine=bfin-unknown
|
||||
os=-linux
|
||||
;;
|
||||
blackfin-*)
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
@@ -475,8 +487,8 @@ case $basic_machine in
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16c)
|
||||
basic_machine=cr16c-unknown
|
||||
cr16)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
crds | unos)
|
||||
@@ -668,6 +680,14 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
;;
|
||||
m68knommu-*)
|
||||
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
m88k-omron*)
|
||||
basic_machine=m88k-omron
|
||||
;;
|
||||
@@ -683,6 +703,10 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
basic_machine=arm-unknown
|
||||
os=-mingw32ce
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
@@ -809,6 +833,14 @@ case $basic_machine in
|
||||
basic_machine=i860-intel
|
||||
os=-osf
|
||||
;;
|
||||
parisc)
|
||||
basic_machine=hppa-unknown
|
||||
os=-linux
|
||||
;;
|
||||
parisc-*)
|
||||
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
pbd)
|
||||
basic_machine=sparc-tti
|
||||
;;
|
||||
@@ -925,6 +957,9 @@ case $basic_machine in
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sh5el)
|
||||
basic_machine=sh5le-unknown
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
@@ -1014,6 +1049,10 @@ case $basic_machine in
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tile*)
|
||||
basic_machine=tile-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
@@ -1219,7 +1258,7 @@ case $os in
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1414,6 +1453,9 @@ case $basic_machine in
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
os=-elf
|
||||
;;
|
||||
|
||||
522
configure.in
522
configure.in
@@ -1,8 +1,6 @@
|
||||
##
|
||||
###############################################################################
|
||||
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
|
||||
## Copyright (C) 2004, 2007 Red Hat, Inc. All rights reserved.
|
||||
##
|
||||
## This file is part of LVM2.
|
||||
## Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
##
|
||||
## This copyrighted material is made available to anyone wishing to use,
|
||||
## modify, copy, or redistribute it subject to the terms and conditions
|
||||
@@ -18,9 +16,7 @@ AC_PREREQ(2.57)
|
||||
dnl -- Process this file with autoconf to produce a configure script.
|
||||
AC_INIT
|
||||
AC_CONFIG_SRCDIR([lib/device/dev-cache.h])
|
||||
|
||||
################################################################################
|
||||
AC_CONFIG_HEADERS(lib/misc/configure.h)
|
||||
AC_CONFIG_HEADERS([lib/misc/configure.h])
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup the directory where autoconf has auxilary files
|
||||
@@ -39,50 +35,58 @@ case "$host_os" in
|
||||
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
|
||||
LIB_SUFFIX="so"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=yes
|
||||
DM_IOCTLS=yes
|
||||
SELINUX=yes
|
||||
REALTIME=yes
|
||||
CLUSTER=internal
|
||||
FSADM=no ;;
|
||||
FSADM=yes
|
||||
;;
|
||||
darwin*)
|
||||
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
||||
COPTIMISE_FLAG="-O2"
|
||||
CLDFLAGS="$CLDFLAGS"
|
||||
CLDWHOLEARCHIVE="-all_load"
|
||||
CLDNOWHOLEARCHIVE=
|
||||
LDDEPS="$LDDEPS"
|
||||
LDFLAGS="$LDFLAGS"
|
||||
LIB_SUFFIX="dylib"
|
||||
LIB_SUFFIX=dylib
|
||||
DEVMAPPER=yes
|
||||
ODIRECT=no
|
||||
DM_IOCTLS=no
|
||||
SELINUX=no
|
||||
REALTIME=no
|
||||
CLUSTER=none
|
||||
FSADM=no ;;
|
||||
FSADM=no
|
||||
;;
|
||||
esac
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for programs.
|
||||
AC_PROG_SED
|
||||
AC_PROG_AWK
|
||||
AC_PROG_CC
|
||||
|
||||
dnl probably no longer needed in 2008, but...
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_MKDIR_P
|
||||
AC_PROG_RANLIB
|
||||
AC_PATH_PROG(CFLOW_CMD, cflow)
|
||||
AC_PATH_PROG(CSCOPE_CMD, cscope)
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for header files.
|
||||
dnl -- Check for header files.
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_HEADER_TIME
|
||||
|
||||
AC_CHECK_HEADERS(fcntl.h limits.h locale.h stddef.h syslog.h sys/file.h sys/ioctl.h sys/param.h sys/time.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_HEADERS(assert.h ctype.h libgen.h signal.h stdio.h sys/mman.h sys/resource.h sys/stat.h sys/types.h sys/utsname.h sys/wait.h time.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_HEADERS([locale.h stddef.h syslog.h sys/file.h sys/time.h assert.h \
|
||||
libgen.h signal.h sys/mman.h sys/resource.h sys/utsname.h sys/wait.h time.h], ,
|
||||
[AC_MSG_ERROR(bailing out)])
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
@@ -91,12 +95,19 @@ case "$host_os" in
|
||||
AC_CHECK_HEADERS(machine/endian.h sys/disk.h,,AC_MSG_ERROR(bailing out)) ;;
|
||||
esac
|
||||
|
||||
AC_CHECK_HEADERS([ctype.h dirent.h errno.h fcntl.h getopt.h inttypes.h limits.h \
|
||||
stdarg.h stdio.h stdlib.h string.h sys/ioctl.h sys/param.h sys/stat.h \
|
||||
sys/types.h unistd.h], , [AC_MSG_ERROR(bailing out)])
|
||||
AC_CHECK_HEADERS(termios.h sys/statvfs.h)
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for typedefs, structures, and compiler characteristics.
|
||||
dnl -- Check for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIGNAL
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_MODE_T
|
||||
AC_CHECK_MEMBERS([struct stat.st_rdev])
|
||||
@@ -104,7 +115,9 @@ AC_STRUCT_TM
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for functions
|
||||
AC_CHECK_FUNCS(gethostname getpagesize memset munmap setlocale strcasecmp strchr strdup strncasecmp strerror strrchr strstr strtol strtoul,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_FUNCS([gethostname getpagesize memset mkdir rmdir munmap setlocale \
|
||||
strcasecmp strchr strdup strncasecmp strerror strrchr strstr strtol strtoul \
|
||||
uname], , [AC_MSG_ERROR(bailing out)])
|
||||
AC_FUNC_ALLOCA
|
||||
AC_FUNC_CLOSEDIR_VOID
|
||||
AC_FUNC_FORK
|
||||
@@ -114,22 +127,28 @@ AC_FUNC_MEMCMP
|
||||
AC_FUNC_MMAP
|
||||
AC_FUNC_STAT
|
||||
AC_FUNC_STRTOD
|
||||
AC_FUNC_VPRINTF
|
||||
|
||||
################################################################################
|
||||
dnl -- Enables statically-linked tools
|
||||
AC_MSG_CHECKING(whether to use static linking)
|
||||
AC_ARG_ENABLE(static_link,
|
||||
[ --enable-static_link Use this to link the tools to their libraries
|
||||
statically. Default is dynamic linking],
|
||||
STATIC_LINK=$enableval, STATIC_LINK=no)
|
||||
AC_MSG_RESULT($STATIC_LINK)
|
||||
|
||||
################################################################################
|
||||
dnl -- Prefix is /usr by default, the exec_prefix default is setup later
|
||||
AC_PREFIX_DEFAULT(/usr)
|
||||
|
||||
################################################################################
|
||||
dnl -- Parallel make jobs?
|
||||
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup the ownership of the files
|
||||
AC_MSG_CHECKING(file owner)
|
||||
OWNER="root"
|
||||
|
||||
AC_ARG_WITH(user,
|
||||
[ --with-user=USER Set the owner of installed files ],
|
||||
[ --with-user=USER Set the owner of installed files [[USER=root]] ],
|
||||
[ OWNER="$withval" ])
|
||||
AC_MSG_RESULT($OWNER)
|
||||
|
||||
@@ -142,7 +161,7 @@ dnl -- Setup the group ownership of the files
|
||||
AC_MSG_CHECKING(group owner)
|
||||
GROUP="root"
|
||||
AC_ARG_WITH(group,
|
||||
[ --with-group=GROUP Set the group owner of installed files ],
|
||||
[ --with-group=GROUP Set the group owner of installed files [[GROUP=root]] ],
|
||||
[ GROUP="$withval" ])
|
||||
AC_MSG_RESULT($GROUP)
|
||||
|
||||
@@ -150,6 +169,33 @@ if test x$GROUP != x; then
|
||||
GROUP="-g $GROUP"
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup device node ownership
|
||||
AC_MSG_CHECKING(device node uid)
|
||||
|
||||
AC_ARG_WITH(device-uid,
|
||||
[ --with-device-uid=UID Set the owner used for new device nodes [[UID=0]] ],
|
||||
[ DM_DEVICE_UID="$withval" ], [ DM_DEVICE_UID="0" ] )
|
||||
AC_MSG_RESULT($DM_DEVICE_UID)
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup device group ownership
|
||||
AC_MSG_CHECKING(device node gid)
|
||||
|
||||
AC_ARG_WITH(device-gid,
|
||||
[ --with-device-gid=UID Set the group used for new device nodes [[GID=0]] ],
|
||||
[ DM_DEVICE_GID="$withval" ], [ DM_DEVICE_GID="0" ] )
|
||||
AC_MSG_RESULT($DM_DEVICE_GID)
|
||||
|
||||
################################################################################
|
||||
dnl -- Setup device mode
|
||||
AC_MSG_CHECKING(device node mode)
|
||||
|
||||
AC_ARG_WITH(device-mode,
|
||||
[ --with-device-mode=MODE Set the mode used for new device nodes [[MODE=0600]] ],
|
||||
[ DM_DEVICE_MODE="$withval" ], [ DM_DEVICE_MODE="0600" ] )
|
||||
AC_MSG_RESULT($DM_DEVICE_MODE)
|
||||
|
||||
################################################################################
|
||||
dnl -- LVM1 tool fallback option
|
||||
AC_MSG_CHECKING(whether to enable lvm1 fallback)
|
||||
@@ -261,30 +307,13 @@ if test x$MIRRORS = xinternal; then
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enables staticly-linked tools
|
||||
AC_MSG_CHECKING(whether to use static linking)
|
||||
AC_ARG_ENABLE(static_link, [ --enable-static_link Use this to link the tools to their libraries
|
||||
statically. Default is dynamic linking], STATIC_LINK=$enableval, STATIC_LINK=no)
|
||||
AC_MSG_RESULT($STATIC_LINK)
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable readline
|
||||
dnl -- Disable readline
|
||||
AC_MSG_CHECKING(whether to enable readline)
|
||||
AC_ARG_ENABLE(readline, [ --enable-readline Enable readline support],
|
||||
READLINE=$enableval, READLINE=no)
|
||||
AC_ARG_ENABLE([readline],
|
||||
[ --disable-readline Disable readline support],
|
||||
[READLINE=$enableval], [READLINE=maybe])
|
||||
AC_MSG_RESULT($READLINE)
|
||||
|
||||
if test x$READLINE = xyes; then
|
||||
AC_DEFINE([READLINE_SUPPORT], 1, [Define to 1 to include the LVM readline shell.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable selinux
|
||||
AC_MSG_CHECKING(whether to enable selinux support)
|
||||
AC_ARG_ENABLE(selinux, [ --disable-selinux Disable selinux support],
|
||||
SELINUX=$enableval)
|
||||
AC_MSG_RESULT($SELINUX)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable realtime clock support
|
||||
AC_MSG_CHECKING(whether to enable realtime support)
|
||||
@@ -296,7 +325,7 @@ AC_MSG_RESULT($REALTIME)
|
||||
dnl -- Build cluster LVM daemon
|
||||
AC_MSG_CHECKING(whether to build cluster LVM daemon)
|
||||
AC_ARG_WITH(clvmd,
|
||||
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/none/all
|
||||
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/corosync/none/all
|
||||
[TYPE=none] ],
|
||||
[ CLVMD="$withval" ],
|
||||
[ CLVMD="none" ])
|
||||
@@ -310,11 +339,24 @@ if test x$CLVMD != xnone && test x$CLUSTER = xnone; then
|
||||
CLUSTER=internal
|
||||
fi
|
||||
|
||||
dnl -- Look for corosync libraries if required.
|
||||
if [[ "x$CLVMD" = xall -o `expr x"$CLVMD" : '.*corosync.*'` != 0 ]]; then
|
||||
PKG_CHECK_MODULES(QUORUM, libquorum, [],
|
||||
[AC_MSG_RESULT([no pkg for quorum library, using -lquorum]);
|
||||
QUORUM_LIBS="-lquorum"])
|
||||
PKG_CHECK_MODULES(CONFDB, libconfdb, [],
|
||||
[AC_MSG_RESULT([no pkg for confdb library, using -lconfdb]);
|
||||
CONFDB_LIBS="-lconfdb"])
|
||||
PKG_CHECK_MODULES(CPG, libcpg, [],
|
||||
[AC_MSG_RESULT([no pkg for libcpg library, using -lcpg]);
|
||||
CPG_LIBS="-lcpg"])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable debugging
|
||||
AC_MSG_CHECKING(whether to enable debugging)
|
||||
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging],
|
||||
DEBUG=$enableval, DEBUG=no)
|
||||
DEBUG=$enableval, DEBUG=no)
|
||||
AC_MSG_RESULT($DEBUG)
|
||||
|
||||
dnl -- Normally turn off optimisation for debug builds
|
||||
@@ -328,21 +370,65 @@ fi
|
||||
dnl -- Override optimisation
|
||||
AC_MSG_CHECKING(for C optimisation flag)
|
||||
AC_ARG_WITH(optimisation,
|
||||
[ --with-optimisation=OPT C optimisation flag [OPT=-O2] ],
|
||||
[ --with-optimisation=OPT C optimisation flag [[OPT=-O2]] ],
|
||||
[ COPTIMISE_FLAG="$withval" ])
|
||||
AC_MSG_RESULT($COPTIMISE_FLAG)
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable profiling
|
||||
AC_MSG_CHECKING(whether to gather gcov profiling data)
|
||||
AC_ARG_ENABLE(profiling,
|
||||
AC_HELP_STRING(--enable-profiling, [Gather gcov profiling data]),
|
||||
PROFILING=$enableval, PROFILING=no)
|
||||
AC_MSG_RESULT($PROFILING)
|
||||
|
||||
if test "x$PROFILING" = xyes; then
|
||||
COPTIMISE_FLAG="$COPTIMISE_FLAG -fprofile-arcs -ftest-coverage"
|
||||
AC_PATH_PROG(LCOV, lcov, no)
|
||||
AC_PATH_PROG(GENHTML, genhtml, no)
|
||||
if test "$LCOV" = no -o "$GENHTML" = no ; then
|
||||
AC_MSG_ERROR([lcov and genhtml are required for profiling])
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable devmapper
|
||||
AC_MSG_CHECKING(whether to use device-mapper)
|
||||
AC_ARG_ENABLE(devmapper, [ --disable-devmapper Disable device-mapper interaction],
|
||||
AC_ARG_ENABLE(devmapper, [ --disable-devmapper Disable LVM2 device-mapper interaction],
|
||||
DEVMAPPER=$enableval)
|
||||
AC_MSG_RESULT($DEVMAPPER)
|
||||
|
||||
if test x$DEVMAPPER = xyes; then
|
||||
AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable device-mapper interaction.])
|
||||
AC_DEFINE([DEVMAPPER_SUPPORT], 1, [Define to 1 to enable LVM2 device-mapper interaction.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable udev synchronisation
|
||||
AC_MSG_CHECKING(whether to enable synchronisation with udev processing)
|
||||
AC_ARG_ENABLE(udev_sync, [ --enable-udev_sync Enable synchronisation with udev processing],
|
||||
UDEV_SYNC=$enableval, UDEV_SYNC=no)
|
||||
AC_MSG_RESULT($UDEV_SYNC)
|
||||
|
||||
if test x$UDEV_SYNC = xyes; then
|
||||
AC_DEFINE([UDEV_SYNC_SUPPORT], 1, [Define to 1 to enable synchronisation with udev processing.])
|
||||
fi
|
||||
|
||||
dnl -- Enable udev rules
|
||||
AC_MSG_CHECKING(whether to enable installation of udev rules required for synchronisation)
|
||||
AC_ARG_ENABLE(udev_rules, [ --enable-udev_rules Install rule files needed for udev synchronisation],
|
||||
UDEV_RULES=$enableval, UDEV_RULES=$UDEV_SYNC)
|
||||
AC_MSG_RESULT($UDEV_RULES)
|
||||
|
||||
################################################################################
|
||||
dnl -- Compatibility mode
|
||||
AC_ARG_ENABLE(compat, [ --enable-compat Enable support for old device-mapper versions],
|
||||
DM_COMPAT=$enableval, DM_COMPAT=no)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable ioctl
|
||||
AC_ARG_ENABLE(ioctl, [ --disable-driver Disable calls to device-mapper in the kernel],
|
||||
DM_IOCTLS=$enableval)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable O_DIRECT
|
||||
AC_MSG_CHECKING(whether to enable O_DIRECT)
|
||||
@@ -354,16 +440,37 @@ if test x$ODIRECT = xyes; then
|
||||
AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable liblvm2app.so
|
||||
AC_MSG_CHECKING(whether to build liblvm2app.so application library)
|
||||
AC_ARG_ENABLE(applib,
|
||||
[ --enable-applib Build application library],
|
||||
APPLIB=$enableval, APPLIB=no)
|
||||
AC_MSG_RESULT($APPLIB)
|
||||
AC_SUBST([LVM2APP_LIB])
|
||||
test x$APPLIB = xyes \
|
||||
&& LVM2APP_LIB=-llvm2app \
|
||||
|| LVM2APP_LIB=
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable cmdlib
|
||||
AC_MSG_CHECKING(whether to compile liblvm2cmd.so)
|
||||
AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library],
|
||||
CMDLIB=$enableval, CMDLIB=no)
|
||||
AC_MSG_RESULT($CMDLIB)
|
||||
AC_SUBST([LVM2CMD_LIB])
|
||||
test x$CMDLIB = xyes \
|
||||
&& LVM2CMD_LIB=-llvm2cmd \
|
||||
|| LVM2CMD_LIB=
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable pkg-config
|
||||
AC_ARG_ENABLE(pkgconfig, [ --enable-pkgconfig Install pkgconfig support],
|
||||
PKGCONFIG=$enableval, PKGCONFIG=no)
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable fsadm
|
||||
AC_MSG_CHECKING(whether to build fsadm)
|
||||
AC_MSG_CHECKING(whether to install fsadm)
|
||||
AC_ARG_ENABLE(fsadm, [ --enable-fsadm Enable fsadm],
|
||||
FSADM=$enableval)
|
||||
AC_MSG_RESULT($FSADM)
|
||||
@@ -375,34 +482,52 @@ AC_ARG_ENABLE(dmeventd, [ --enable-dmeventd Enable the device-mapper even
|
||||
DMEVENTD=$enableval)
|
||||
AC_MSG_RESULT($DMEVENTD)
|
||||
|
||||
BUILD_DMEVENTD=$DMEVENTD
|
||||
|
||||
dnl -- dmeventd currently requires internal mirror support
|
||||
if test x$DMEVENTD = xyes && test x$MIRRORS != xinternal; then
|
||||
AC_MSG_ERROR(
|
||||
--enable-dmeventd currently requires --with-mirrors=internal
|
||||
)
|
||||
if test x$DMEVENTD = xyes; then
|
||||
if test x$MIRRORS != xinternal; then
|
||||
AC_MSG_ERROR(
|
||||
--enable-dmeventd currently requires --with-mirrors=internal
|
||||
)
|
||||
fi
|
||||
if test x$CMDLIB = xno; then
|
||||
AC_MSG_ERROR(
|
||||
--enable-dmeventd requires --enable-cmdlib to be used as well
|
||||
)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD = xyes; then
|
||||
AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Mess with default exec_prefix
|
||||
dnl -- getline included in recent libc
|
||||
|
||||
AC_CHECK_LIB(c, getline, AC_DEFINE([HAVE_GETLINE], 1,
|
||||
[Define to 1 if getline is available.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- canonicalize_file_name included in recent libc
|
||||
|
||||
AC_CHECK_LIB(c, canonicalize_file_name,
|
||||
AC_DEFINE([HAVE_CANONICALIZE_FILE_NAME], 1,
|
||||
[Define to 1 if canonicalize_file_name is available.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Clear default exec_prefix - install into /sbin rather than /usr/sbin
|
||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
||||
then exec_prefix="";
|
||||
fi;
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for library functions.
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS(mkdir rmdir uname,,AC_MSG_ERROR(bailing out))
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for termcap (Shamelessly copied from parted 1.4.17)
|
||||
if test x$READLINE = xyes; then
|
||||
AC_SEARCH_LIBS(tgetent, ncurses curses termcap termlib, ,
|
||||
AC_MSG_ERROR(
|
||||
if test x$READLINE != xno; then
|
||||
AC_SEARCH_LIBS([tgetent], [tinfo ncurses curses termcap termlib],
|
||||
[tg_found=yes], [tg_found=no])
|
||||
test x$READLINE:$tg_found = xyes:no &&
|
||||
AC_MSG_ERROR(
|
||||
termcap could not be found which is required for the
|
||||
--enable-readline option (which is enabled by default). Either disable readline
|
||||
support with --disable-readline or download and install termcap from:
|
||||
@@ -412,7 +537,6 @@ Note: if you are using precompiled packages you will also need the development
|
||||
Note: (n)curses also seems to work as a substitute for termcap. This was
|
||||
not found either - but you could try installing that as well.
|
||||
)
|
||||
)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -436,12 +560,21 @@ Features cannot be 'shared' when building statically
|
||||
)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable selinux
|
||||
AC_MSG_CHECKING(whether to enable selinux support)
|
||||
AC_ARG_ENABLE(selinux, [ --disable-selinux Disable selinux support],
|
||||
SELINUX=$enableval)
|
||||
AC_MSG_RESULT($SELINUX)
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for selinux
|
||||
if test x$SELINUX = xyes; then
|
||||
AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
|
||||
|
||||
if test x$HAVE_SEPOL = xyes; then
|
||||
AC_DEFINE([HAVE_SEPOL], 1,
|
||||
[Define to 1 if sepol_check_context is available.])
|
||||
LIBS="-lsepol $LIBS"
|
||||
fi
|
||||
|
||||
@@ -454,7 +587,7 @@ if test x$SELINUX = xyes; then
|
||||
AC_MSG_WARN(Disabling selinux)
|
||||
fi
|
||||
|
||||
# With --enable-static_link and selinux enabled, linking lvm.static
|
||||
# With --enable-static_link and selinux enabled, linking
|
||||
# fails on at least Debian unstable due to unsatisfied references
|
||||
# to pthread_mutex_lock and _unlock. See if we need -lpthread.
|
||||
if test "$STATIC_LINK-$HAVE_SELINUX" = yes-yes; then
|
||||
@@ -482,13 +615,15 @@ fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for getopt
|
||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 to if getopt_long is available.]))
|
||||
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getopt_long is available.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
|
||||
if test x$READLINE = xyes; then
|
||||
AC_CHECK_LIB(readline, readline, ,
|
||||
AC_MSG_ERROR(
|
||||
if test x$READLINE != xno; then
|
||||
rl_found=yes
|
||||
AC_CHECK_LIB([readline], [readline], , [rl_found=no])
|
||||
test x$READLINE:$rl_found = xyes:no &&
|
||||
AC_MSG_ERROR(
|
||||
GNU Readline could not be found which is required for the
|
||||
--enable-readline option (which is enabled by default). Either disable readline
|
||||
support with --disable-readline or download and install readline from:
|
||||
@@ -496,8 +631,11 @@ support with --disable-readline or download and install readline from:
|
||||
Note: if you are using precompiled packages you will also need the development
|
||||
package as well (which may be called readline-devel or something similar).
|
||||
)
|
||||
)
|
||||
AC_CHECK_FUNC(rl_completion_matches, AC_DEFINE([HAVE_RL_COMPLETION_MATCHES], 1, [Define to 1 if rl_completion_matches() is available.]))
|
||||
if test $rl_found = yes; then
|
||||
AC_CHECK_FUNCS([rl_completion_matches])
|
||||
AC_DEFINE([READLINE_SUPPORT], 1,
|
||||
[Define to 1 to include the LVM readline shell.])
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -508,6 +646,7 @@ AC_ARG_ENABLE(nls, [ --enable-nls Enable Native Language Support],
|
||||
AC_MSG_RESULT($INTL)
|
||||
|
||||
if test x$INTL = xyes; then
|
||||
# FIXME - Move this - can be device-mapper too
|
||||
INTL_PACKAGE="lvm2"
|
||||
AC_PATH_PROG(MSGFMT, msgfmt)
|
||||
if [[ "x$MSGFMT" == x ]];
|
||||
@@ -517,32 +656,42 @@ if test x$INTL = xyes; then
|
||||
fi;
|
||||
|
||||
AC_ARG_WITH(localedir,
|
||||
[ --with-localedir=DIR Translation files in DIR [PREFIX/share/locale]],
|
||||
[ LOCALEDIR="$withval" ],
|
||||
[ LOCALEDIR='${prefix}/share/locale' ])
|
||||
[ --with-localedir=DIR Translation files in DIR [[PREFIX/share/locale]] ],
|
||||
[ LOCALEDIR="$withval" ],
|
||||
[ LOCALEDIR='${prefix}/share/locale' ])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
AC_ARG_WITH(confdir,
|
||||
[ --with-confdir=DIR Configuration files in DIR [/etc]],
|
||||
[ CONFDIR="$withval" ],
|
||||
[ CONFDIR='/etc' ])
|
||||
[ --with-confdir=DIR Configuration files in DIR [[/etc]]],
|
||||
[ CONFDIR="$withval" ],
|
||||
[ CONFDIR='/etc' ])
|
||||
|
||||
AC_ARG_WITH(staticdir,
|
||||
[ --with-staticdir=DIR Static binary in DIR [EXEC_PREFIX/sbin]],
|
||||
[ STATICDIR="$withval" ],
|
||||
[ STATICDIR='${exec_prefix}/sbin' ])
|
||||
[ --with-staticdir=DIR Static binary in DIR [[EPREFIX/sbin]]],
|
||||
[ STATICDIR="$withval" ],
|
||||
[ STATICDIR='${exec_prefix}/sbin' ])
|
||||
|
||||
AC_ARG_WITH(dmdir,
|
||||
[ --with-dmdir=DIR Build against device-mapper source tree in DIR],
|
||||
[ DMDIR="$withval" CPPFLAGS="$CPPFLAGS -I$DMDIR/include"],
|
||||
[ DMDIR= ])
|
||||
AC_ARG_WITH(usrlibdir,
|
||||
[ --with-usrlibdir=DIR],
|
||||
[ usrlibdir="$withval"],
|
||||
[ usrlibdir='${prefix}/lib' ])
|
||||
|
||||
# Convert a relative dir name to absolute.
|
||||
case $DMDIR in
|
||||
/*) ;;
|
||||
*) DMDIR="`pwd`/$DMDIR" ;;
|
||||
esac
|
||||
AC_ARG_WITH(usrsbindir,
|
||||
[ --with-usrsbindir=DIR],
|
||||
[ usrsbindir="$withval"],
|
||||
[ usrsbindir='${prefix}/sbin' ])
|
||||
|
||||
################################################################################
|
||||
AC_ARG_WITH(udev_prefix,
|
||||
[ --with-udev-prefix=UPREFIX Install udev rule files in UPREFIX [[EPREFIX]]],
|
||||
[ udev_prefix="$withval"],
|
||||
[ udev_prefix='${exec_prefix}' ])
|
||||
|
||||
AC_ARG_WITH(udevdir,
|
||||
[ --with-udevdir=DIR udev rules in DIR [[UPREFIX/lib/udev/rules.d]]],
|
||||
[ udevdir="$withval"],
|
||||
[ udevdir='${udev_prefix}/lib/udev/rules.d' ])
|
||||
|
||||
################################################################################
|
||||
dnl -- Ensure additional headers required
|
||||
@@ -558,11 +707,6 @@ if test x$CLVMD != xnone; then
|
||||
AC_FUNC_SELECT_ARGTYPES
|
||||
fi
|
||||
|
||||
if test x$FSADM = xyes; then
|
||||
AC_CHECK_HEADERS(fstab.h sys/mount.h sys/vfs.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_FUNCS(memmove,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$CLUSTER != xnone; then
|
||||
AC_CHECK_HEADERS(sys/socket.h sys/un.h,,AC_MSG_ERROR(bailing out))
|
||||
AC_CHECK_FUNCS(socket,,AC_MSG_ERROR(bailing out))
|
||||
@@ -576,12 +720,14 @@ if test x$INTL = xyes; then
|
||||
AC_CHECK_HEADERS(libintl.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
|
||||
|
||||
if test x$HAVE_SELINUX = xyes; then
|
||||
AC_CHECK_HEADERS(selinux/selinux.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
if test x$UDEV_SYNC = xyes; then
|
||||
AC_CHECK_HEADERS(sys/ipc.h sys/sem.h,,AC_MSG_ERROR(bailing out))
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
AC_PATH_PROG(MODPROBE_CMD, modprobe)
|
||||
|
||||
@@ -590,52 +736,131 @@ if test x$MODPROBE_CMD != x; then
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test "-f VERSION"; then
|
||||
LVM_VERSION="\"`cat VERSION`\""
|
||||
else
|
||||
LVM_VERSION="Unknown"
|
||||
dnl -- dmeventd pidfile and executable path
|
||||
AH_TEMPLATE(DMEVENTD_PIDFILE, [Path to dmeventd pidfile.])
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
AC_ARG_WITH(dmeventd-pidfile,
|
||||
[ --with-dmeventd-pidfile=PATH dmeventd pidfile [[/var/run/dmeventd.pid]] ],
|
||||
[ AC_DEFINE_UNQUOTED(DMEVENTD_PIDFILE,"$withval") ],
|
||||
[ AC_DEFINE_UNQUOTED(DMEVENTD_PIDFILE,"/var/run/dmeventd.pid") ])
|
||||
fi
|
||||
|
||||
AH_TEMPLATE(DMEVENTD_PATH, [Path to dmeventd binary.])
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
dmeventd_prefix="$exec_prefix"
|
||||
if test "x$dmeventd_prefix" = "xNONE"; then
|
||||
dmeventd_prefix="$prefix"
|
||||
fi
|
||||
if test "x$dmeventd_prefix" = "xNONE"; then
|
||||
dmeventd_prefix=""
|
||||
fi
|
||||
AC_ARG_WITH(dmeventd-path,
|
||||
[ --with-dmeventd-path=PATH dmeventd path [[EPREFIX/sbin/dmeventd]] ],
|
||||
[ AC_DEFINE_UNQUOTED(DMEVENTD_PATH,"$withval") ],
|
||||
[ AC_DEFINE_UNQUOTED(DMEVENTD_PATH,"$dmeventd_prefix/sbin/dmeventd") ])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
AC_SUBST(JOBS)
|
||||
AC_SUBST(STATIC_LINK)
|
||||
AC_SUBST(LVM1)
|
||||
AC_SUBST(POOL)
|
||||
AC_SUBST(SNAPSHOTS)
|
||||
AC_SUBST(MIRRORS)
|
||||
AC_SUBST(OWNER)
|
||||
AC_SUBST(GROUP)
|
||||
dnl -- which kernel interface to use (ioctl only)
|
||||
AC_MSG_CHECKING(for kernel interface choice)
|
||||
AC_ARG_WITH(interface,
|
||||
[ --with-interface=IFACE Choose kernel interface (ioctl) [[ioctl]] ],
|
||||
[ interface="$withval" ],
|
||||
[ interface=ioctl ])
|
||||
if [[ "x$interface" != xioctl ]];
|
||||
then
|
||||
AC_MSG_ERROR(--with-interface=ioctl required. fs no longer supported.)
|
||||
fi
|
||||
AC_MSG_RESULT($interface)
|
||||
|
||||
################################################################################
|
||||
DM_LIB_VERSION="\"`cat VERSION_DM 2>/dev/null || echo Unknown`\""
|
||||
AC_DEFINE_UNQUOTED(DM_LIB_VERSION, $DM_LIB_VERSION, [Library version])
|
||||
|
||||
DM_LIB_PATCHLEVEL=`cat VERSION_DM | $AWK -F '[[-. ]]' '{printf "%s.%s.%s",$1,$2,$3}'`
|
||||
|
||||
LVM_VERSION="\"`cat VERSION 2>/dev/null || echo Unknown`\""
|
||||
|
||||
VER=`cat VERSION`
|
||||
LVM_RELEASE_DATE="\"`echo $VER | $SED 's/.* (//;s/).*//'`\""
|
||||
VER=`echo "$VER" | $AWK '{print $1}'`
|
||||
LVM_RELEASE="\"`echo "$VER" | $AWK -F '-' '{print $2}'`\""
|
||||
VER=`echo "$VER" | $AWK -F '-' '{print $1}'`
|
||||
LVM_MAJOR=`echo "$VER" | $AWK -F '.' '{print $1}'`
|
||||
LVM_MINOR=`echo "$VER" | $AWK -F '.' '{print $2}'`
|
||||
LVM_PATCHLEVEL=`echo "$VER" | $AWK -F '[[(.]]' '{print $3}'`
|
||||
LVM_LIBAPI=`echo "$VER" | $AWK -F '[[()]]' '{print $2}'`
|
||||
|
||||
################################################################################
|
||||
AC_SUBST(APPLIB)
|
||||
AC_SUBST(BUILD_DMEVENTD)
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(COPTIMISE_FLAG)
|
||||
AC_SUBST(CFLOW_CMD)
|
||||
AC_SUBST(CLDFLAGS)
|
||||
AC_SUBST(CLDWHOLEARCHIVE)
|
||||
AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||
AC_SUBST(LDDEPS)
|
||||
AC_SUBST(LDFLAGS)
|
||||
AC_SUBST(LIB_SUFFIX)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LVM_VERSION)
|
||||
AC_SUBST(LVM1_FALLBACK)
|
||||
AC_SUBST(CLDWHOLEARCHIVE)
|
||||
AC_SUBST(CLUSTER)
|
||||
AC_SUBST(CLVMD)
|
||||
AC_SUBST(CMDLIB)
|
||||
AC_SUBST(CONFDB_CFLAGS)
|
||||
AC_SUBST(CONFDB_LIBS)
|
||||
AC_SUBST(CONFDIR)
|
||||
AC_SUBST(COPTIMISE_FLAG)
|
||||
AC_SUBST(CPG_CFLAGS)
|
||||
AC_SUBST(CPG_LIBS)
|
||||
AC_SUBST(CSCOPE_CMD)
|
||||
AC_SUBST(DEBUG)
|
||||
AC_SUBST(DEVMAPPER)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_SELINUX)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
AC_SUBST(CMDLIB)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(LOCALEDIR)
|
||||
AC_SUBST(CONFDIR)
|
||||
AC_SUBST(STATICDIR)
|
||||
AC_SUBST(DMDIR)
|
||||
AC_SUBST(INTL_PACKAGE)
|
||||
AC_SUBST(INTL)
|
||||
AC_SUBST(CLVMD)
|
||||
AC_SUBST(CLUSTER)
|
||||
AC_SUBST(FSADM)
|
||||
AC_SUBST(DMEVENTD)
|
||||
AC_SUBST(CFLOW_CMD)
|
||||
AC_SUBST(CSCOPE_CMD)
|
||||
AC_SUBST(DM_COMPAT)
|
||||
AC_SUBST(DM_DEVICE_GID)
|
||||
AC_SUBST(DM_DEVICE_MODE)
|
||||
AC_SUBST(DM_DEVICE_UID)
|
||||
AC_SUBST(DM_IOCTLS)
|
||||
AC_SUBST(DM_LIB_VERSION)
|
||||
AC_SUBST(DM_LIB_PATCHLEVEL)
|
||||
AC_SUBST(FSADM)
|
||||
AC_SUBST(GROUP)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
AC_SUBST(HAVE_SELINUX)
|
||||
AC_SUBST(INTL)
|
||||
AC_SUBST(INTL_PACKAGE)
|
||||
AC_SUBST(JOBS)
|
||||
AC_SUBST(LDDEPS)
|
||||
AC_SUBST(LIBS)
|
||||
AC_SUBST(LIB_SUFFIX)
|
||||
AC_SUBST(LOCALEDIR)
|
||||
AC_SUBST(LVM1)
|
||||
AC_SUBST(LVM1_FALLBACK)
|
||||
AC_SUBST(LVM_VERSION)
|
||||
AC_SUBST(LVM_LIBAPI)
|
||||
AC_SUBST(LVM_MAJOR)
|
||||
AC_SUBST(LVM_MINOR)
|
||||
AC_SUBST(LVM_PATCHLEVEL)
|
||||
AC_SUBST(LVM_RELEASE)
|
||||
AC_SUBST(LVM_RELEASE_DATE)
|
||||
AC_SUBST(MIRRORS)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(OWNER)
|
||||
AC_SUBST(PKGCONFIG)
|
||||
AC_SUBST(POOL)
|
||||
AC_SUBST(QUORUM_CFLAGS)
|
||||
AC_SUBST(QUORUM_LIBS)
|
||||
AC_SUBST(SNAPSHOTS)
|
||||
AC_SUBST(STATICDIR)
|
||||
AC_SUBST(STATIC_LINK)
|
||||
AC_SUBST(UDEV_RULES)
|
||||
AC_SUBST([LIB_PTHREAD])
|
||||
AC_SUBST(interface)
|
||||
AC_SUBST(kerneldir)
|
||||
AC_SUBST(missingkernel)
|
||||
AC_SUBST(kernelvsn)
|
||||
AC_SUBST(tmpdir)
|
||||
AC_SUBST(udev_prefix)
|
||||
AC_SUBST(udevdir)
|
||||
AC_SUBST(usrlibdir)
|
||||
AC_SUBST(usrsbindir)
|
||||
|
||||
################################################################################
|
||||
dnl -- First and last lines should not contain files to generate in order to
|
||||
@@ -645,8 +870,11 @@ Makefile
|
||||
make.tmpl
|
||||
daemons/Makefile
|
||||
daemons/clvmd/Makefile
|
||||
dmeventd/Makefile
|
||||
dmeventd/mirror/Makefile
|
||||
daemons/dmeventd/Makefile
|
||||
daemons/dmeventd/libdevmapper-event.pc
|
||||
daemons/dmeventd/plugins/Makefile
|
||||
daemons/dmeventd/plugins/mirror/Makefile
|
||||
daemons/dmeventd/plugins/snapshot/Makefile
|
||||
doc/Makefile
|
||||
include/Makefile
|
||||
lib/Makefile
|
||||
@@ -654,25 +882,23 @@ lib/format1/Makefile
|
||||
lib/format_pool/Makefile
|
||||
lib/locking/Makefile
|
||||
lib/mirror/Makefile
|
||||
lib/misc/lvm-version.h
|
||||
lib/snapshot/Makefile
|
||||
test/Makefile
|
||||
libdm/Makefile
|
||||
libdm/libdevmapper.pc
|
||||
liblvm/Makefile
|
||||
liblvm/liblvm2app.pc
|
||||
man/Makefile
|
||||
po/Makefile
|
||||
scripts/clvmd_init_red_hat
|
||||
scripts/Makefile
|
||||
test/Makefile
|
||||
test/api/Makefile
|
||||
tools/Makefile
|
||||
tools/version.h
|
||||
tools/fsadm/Makefile
|
||||
udev/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
if test x$ODIRECT != xyes; then
|
||||
AC_MSG_WARN(Warning: O_DIRECT disabled: low-memory pvmove may lock up)
|
||||
fi
|
||||
|
||||
if test x$FSADM == xyes; then
|
||||
AC_MSG_WARN(fsadm support is untested)
|
||||
fi
|
||||
|
||||
if test x$DMEVENTD == xyes; then
|
||||
AC_MSG_WARN(dmeventd support is untested)
|
||||
fi
|
||||
|
||||
@@ -15,9 +15,18 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
.PHONY: dmeventd clvmd
|
||||
|
||||
ifneq ("@CLVMD@", "none")
|
||||
SUBDIRS = clvmd
|
||||
endif
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
SUBDIRS += dmeventd
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
device-mapper: dmeventd.device-mapper
|
||||
endif
|
||||
|
||||
77
daemons/clogd/Makefile
Normal file
77
daemons/clogd/Makefile
Normal file
@@ -0,0 +1,77 @@
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
##
|
||||
## Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||
##
|
||||
## This copyrighted material is made available to anyone wishing to use,
|
||||
## modify, copy, or redistribute it subject to the terms and conditions
|
||||
## of the GNU General Public License v.2.
|
||||
##
|
||||
###############################################################################
|
||||
###############################################################################
|
||||
|
||||
SOURCES = clogd.c cluster.c functions.c link_mon.c local.c logging.c
|
||||
|
||||
TARGET = $(shell if [ ! -e /usr/include/linux/dm-log-userspace.h ]; then \
|
||||
echo 'no_clogd_kernel_headers'; \
|
||||
elif [ ! -e /usr/include/linux/ext2_fs.h ]; then \
|
||||
echo 'no_e2fsprogs_devel'; \
|
||||
elif [ ! -e /usr/include/openais/saCkpt.h ]; then \
|
||||
echo 'no_openais_devel'; \
|
||||
else \
|
||||
echo 'clogd'; \
|
||||
fi)
|
||||
|
||||
ifneq ($(DEBUG), )
|
||||
CFLAGS += -DDEBUG
|
||||
endif
|
||||
|
||||
ifneq ($(MEMB), )
|
||||
CFLAGS += -DMEMB
|
||||
endif
|
||||
|
||||
ifneq ($(CKPT), )
|
||||
CFLAGS += -DCKPT
|
||||
endif
|
||||
|
||||
ifneq ($(RESEND), )
|
||||
CFLAGS += -DRESEND
|
||||
endif
|
||||
|
||||
CFLAGS += -g
|
||||
|
||||
LDFLAGS += $(shell if [ -e /usr/lib64/openais ]; then \
|
||||
echo '-L/usr/lib64/openais -L/usr/lib64 -L/lib64'; \
|
||||
else \
|
||||
echo '-L/usr/lib/openais -L/usr/lib -L/lib'; \
|
||||
fi)
|
||||
LDFLAGS += -lcpg -lSaCkpt -lext2fs -ldevmapper
|
||||
|
||||
all: ${TARGET}
|
||||
|
||||
clogd: ${SOURCES}
|
||||
${CC} ${CFLAGS} -o $@ $^ ${LDFLAGS}
|
||||
|
||||
no_clogd_kernel_headers:
|
||||
echo "Unable to find clogd kernel headers"
|
||||
exit 1
|
||||
|
||||
no_e2fsprogs_devel:
|
||||
echo "Unable to find ext2fs kernel headers."
|
||||
echo "Install 'e2fsprogs-devel'?"
|
||||
exit 1
|
||||
|
||||
no_openais_devel:
|
||||
echo "Unable to find openAIS headers."
|
||||
echo "http://sources.redhat.com/cluster/wiki/"
|
||||
exit 1
|
||||
|
||||
install: clogd
|
||||
install -d /usr/sbin
|
||||
install clogd /usr/sbin
|
||||
|
||||
uninstall:
|
||||
rm /usr/sbin/clogd
|
||||
|
||||
clean:
|
||||
rm -f *.o clogd *~
|
||||
265
daemons/clogd/clogd.c
Normal file
265
daemons/clogd/clogd.c
Normal file
@@ -0,0 +1,265 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/dm-log-userspace.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
|
||||
#include "functions.h"
|
||||
#include "local.h"
|
||||
#include "cluster.h"
|
||||
#include "common.h"
|
||||
#include "logging.h"
|
||||
#include "link_mon.h"
|
||||
|
||||
static int exit_now = 0;
|
||||
static sigset_t signal_mask;
|
||||
static int signal_received;
|
||||
|
||||
static void process_signals(void);
|
||||
static void daemonize(void);
|
||||
static void init_all(void);
|
||||
static void cleanup_all(void);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
daemonize();
|
||||
|
||||
init_all();
|
||||
|
||||
/* Parent can now exit, we're ready to handle requests */
|
||||
kill(getppid(), SIGTERM);
|
||||
|
||||
LOG_PRINT("Starting clogd:");
|
||||
LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
|
||||
LOG_DBG(" Compiled with debugging.");
|
||||
|
||||
while (!exit_now) {
|
||||
links_monitor();
|
||||
|
||||
links_issue_callbacks();
|
||||
|
||||
process_signals();
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* parent_exit_handler: exit the parent
|
||||
* @sig: the signal
|
||||
*
|
||||
*/
|
||||
static void parent_exit_handler(int sig)
|
||||
{
|
||||
exit_now = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* create_lockfile - create and lock a lock file
|
||||
* @lockfile: location of lock file
|
||||
*
|
||||
* Returns: 0 on success, -1 otherwise
|
||||
*/
|
||||
static int create_lockfile(char *lockfile)
|
||||
{
|
||||
int fd;
|
||||
struct flock lock;
|
||||
char buffer[50];
|
||||
|
||||
if((fd = open(lockfile, O_CREAT | O_WRONLY,
|
||||
(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0)
|
||||
return -errno;
|
||||
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_start = 0;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_len = 0;
|
||||
|
||||
if (fcntl(fd, F_SETLK, &lock) < 0) {
|
||||
close(fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (ftruncate(fd, 0) < 0) {
|
||||
close(fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
sprintf(buffer, "%d\n", getpid());
|
||||
|
||||
if(write(fd, buffer, strlen(buffer)) < strlen(buffer)){
|
||||
close(fd);
|
||||
unlink(lockfile);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sig_handler(int sig)
|
||||
{
|
||||
sigaddset(&signal_mask, sig);
|
||||
++signal_received;
|
||||
}
|
||||
|
||||
static void process_signal(int sig){
|
||||
int r = 0;
|
||||
|
||||
switch(sig) {
|
||||
case SIGINT:
|
||||
case SIGQUIT:
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
r += log_status();
|
||||
break;
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
log_debug();
|
||||
/*local_debug();*/
|
||||
cluster_debug();
|
||||
return;
|
||||
default:
|
||||
LOG_PRINT("Unknown signal received... ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
LOG_DBG("No current cluster logs... safe to exit.");
|
||||
cleanup_all();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
LOG_ERROR("Cluster logs exist. Refusing to exit.");
|
||||
}
|
||||
|
||||
static void process_signals(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
if (!signal_received)
|
||||
return;
|
||||
|
||||
signal_received = 0;
|
||||
|
||||
for (x = 1; x < _NSIG; x++) {
|
||||
if (sigismember(&signal_mask, x)) {
|
||||
sigdelset(&signal_mask, x);
|
||||
process_signal(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* daemonize
|
||||
*
|
||||
* Performs the steps necessary to become a daemon.
|
||||
*/
|
||||
static void daemonize(void)
|
||||
{
|
||||
int pid;
|
||||
int status;
|
||||
|
||||
signal(SIGTERM, &parent_exit_handler);
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
LOG_ERROR("Unable to fork()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pid) {
|
||||
/* Parent waits here for child to get going */
|
||||
while (!waitpid(pid, &status, WNOHANG) && !exit_now);
|
||||
if (exit_now)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
switch (WEXITSTATUS(status)) {
|
||||
case EXIT_LOCKFILE:
|
||||
LOG_ERROR("Failed to create lockfile");
|
||||
LOG_ERROR("Process already running?");
|
||||
break;
|
||||
case EXIT_KERNEL_SOCKET:
|
||||
LOG_ERROR("Unable to create netlink socket");
|
||||
break;
|
||||
case EXIT_KERNEL_BIND:
|
||||
LOG_ERROR("Unable to bind to netlink socket");
|
||||
break;
|
||||
case EXIT_KERNEL_SETSOCKOPT:
|
||||
LOG_ERROR("Unable to setsockopt on netlink socket");
|
||||
break;
|
||||
case EXIT_CLUSTER_CKPT_INIT:
|
||||
LOG_ERROR("Unable to initialize checkpoint service");
|
||||
LOG_ERROR("Has the cluster infrastructure been started?");
|
||||
break;
|
||||
case EXIT_FAILURE:
|
||||
LOG_ERROR("Failed to start: Generic error");
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Failed to start: Unknown error");
|
||||
break;
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
setsid();
|
||||
chdir("/");
|
||||
umask(0);
|
||||
|
||||
close(0); close(1); close(2);
|
||||
open("/dev/null", O_RDONLY); /* reopen stdin */
|
||||
open("/dev/null", O_WRONLY); /* reopen stdout */
|
||||
open("/dev/null", O_WRONLY); /* reopen stderr */
|
||||
|
||||
LOG_OPEN("clogd", LOG_PID, LOG_DAEMON);
|
||||
|
||||
if (create_lockfile("/var/run/clogd.pid"))
|
||||
exit(EXIT_LOCKFILE);
|
||||
|
||||
signal(SIGINT, &sig_handler);
|
||||
signal(SIGQUIT, &sig_handler);
|
||||
signal(SIGTERM, &sig_handler);
|
||||
signal(SIGHUP, &sig_handler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGUSR1, &sig_handler);
|
||||
signal(SIGUSR2, &sig_handler);
|
||||
sigemptyset(&signal_mask);
|
||||
signal_received = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_all
|
||||
*
|
||||
* Initialize modules. Exit on failure.
|
||||
*/
|
||||
static void init_all(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = init_local()) ||
|
||||
(r = init_cluster())) {
|
||||
exit(r);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup_all
|
||||
*
|
||||
* Clean up before exiting
|
||||
*/
|
||||
static void cleanup_all(void)
|
||||
{
|
||||
cleanup_local();
|
||||
cleanup_cluster();
|
||||
}
|
||||
1650
daemons/clogd/cluster.c
Normal file
1650
daemons/clogd/cluster.c
Normal file
File diff suppressed because it is too large
Load Diff
46
daemons/clogd/cluster.h
Normal file
46
daemons/clogd/cluster.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef __CLUSTER_LOG_CLUSTER_DOT_H__
|
||||
#define __CLUSTER_LOG_CLUSTER_DOT_H__
|
||||
|
||||
#include <libdevmapper.h>
|
||||
#include <linux/dm-log-userspace.h>
|
||||
|
||||
/*
|
||||
* There is other information in addition to what can
|
||||
* be found in the dm_ulog_request structure that we
|
||||
* need for processing. 'clog_request' is the wrapping
|
||||
* structure we use to make the additional fields
|
||||
* available.
|
||||
*/
|
||||
struct clog_request {
|
||||
struct dm_list list;
|
||||
|
||||
/*
|
||||
* 'originator' is the machine from which the requests
|
||||
* was made.
|
||||
*/
|
||||
uint32_t originator;
|
||||
|
||||
/*
|
||||
* 'pit_server' is the "point-in-time" server for the
|
||||
* request. (I.e. The machine that was the server at
|
||||
* the time the request was issued - only important during
|
||||
* startup.
|
||||
*/
|
||||
uint32_t pit_server;
|
||||
|
||||
/*
|
||||
* The request from the kernel that is being processed
|
||||
*/
|
||||
struct dm_ulog_request u_rq;
|
||||
};
|
||||
|
||||
int init_cluster(void);
|
||||
void cleanup_cluster(void);
|
||||
void cluster_debug(void);
|
||||
|
||||
int create_cluster_cpg(char *uuid, uint64_t luid);
|
||||
int destroy_cluster_cpg(char *uuid);
|
||||
|
||||
int cluster_send(struct clog_request *rq);
|
||||
|
||||
#endif /* __CLUSTER_LOG_CLUSTER_DOT_H__ */
|
||||
22
daemons/clogd/common.h
Normal file
22
daemons/clogd/common.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef __CLUSTER_LOG_COMMON_DOT_H__
|
||||
#define __CLUSTER_LOG_COMMON_DOT_H__
|
||||
|
||||
/*
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_FAILURE 1
|
||||
*/
|
||||
|
||||
#define EXIT_LOCKFILE 2
|
||||
|
||||
#define EXIT_KERNEL_SOCKET 3 /* Failed netlink socket create */
|
||||
#define EXIT_KERNEL_BIND 4
|
||||
#define EXIT_KERNEL_SETSOCKOPT 5
|
||||
|
||||
#define EXIT_CLUSTER_CKPT_INIT 6 /* Failed to init checkpoint */
|
||||
|
||||
#define EXIT_QUEUE_NOMEM 7
|
||||
|
||||
|
||||
#define DM_ULOG_REQUEST_SIZE 1024
|
||||
|
||||
#endif /* __CLUSTER_LOG_COMMON_DOT_H__ */
|
||||
1854
daemons/clogd/functions.c
Normal file
1854
daemons/clogd/functions.c
Normal file
File diff suppressed because it is too large
Load Diff
23
daemons/clogd/functions.h
Normal file
23
daemons/clogd/functions.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef __CLOG_FUNCTIONS_DOT_H__
|
||||
#define __CLOG_FUNCTIONS_DOT_H__
|
||||
|
||||
#include <linux/dm-log-userspace.h>
|
||||
#include "cluster.h"
|
||||
|
||||
#define LOG_RESUMED 1
|
||||
#define LOG_SUSPENDED 2
|
||||
|
||||
int local_resume(struct dm_ulog_request *rq);
|
||||
int cluster_postsuspend(char *, uint64_t);
|
||||
|
||||
int do_request(struct clog_request *rq, int server);
|
||||
int push_state(const char *uuid, uint64_t luid,
|
||||
const char *which, char **buf, uint32_t debug_who);
|
||||
int pull_state(const char *uuid, uint64_t luid,
|
||||
const char *which, char *buf, int size);
|
||||
|
||||
int log_get_state(struct dm_ulog_request *rq);
|
||||
int log_status(void);
|
||||
void log_debug(void);
|
||||
|
||||
#endif /* __CLOG_FUNCTIONS_DOT_H__ */
|
||||
138
daemons/clogd/link_mon.c
Normal file
138
daemons/clogd/link_mon.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
struct link_callback {
|
||||
int fd;
|
||||
char *name;
|
||||
void *data;
|
||||
int (*callback)(void *data);
|
||||
|
||||
struct link_callback *next;
|
||||
};
|
||||
|
||||
static int used_pfds = 0;
|
||||
static int free_pfds = 0;
|
||||
static struct pollfd *pfds = NULL;
|
||||
static struct link_callback *callbacks = NULL;
|
||||
|
||||
int links_register(int fd, char *name, int (*callback)(void *data), void *data)
|
||||
{
|
||||
int i;
|
||||
struct link_callback *lc;
|
||||
|
||||
for (i = 0; i < used_pfds; i++) {
|
||||
if (fd == pfds[i].fd) {
|
||||
LOG_ERROR("links_register: Duplicate file descriptor");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
lc = malloc(sizeof(*lc));
|
||||
if (!lc)
|
||||
return -ENOMEM;
|
||||
|
||||
lc->fd = fd;
|
||||
lc->name = name;
|
||||
lc->data = data;
|
||||
lc->callback = callback;
|
||||
|
||||
if (!free_pfds) {
|
||||
struct pollfd *tmp;
|
||||
tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1));
|
||||
if (!tmp) {
|
||||
free(lc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pfds = tmp;
|
||||
free_pfds = used_pfds + 1;
|
||||
}
|
||||
|
||||
free_pfds--;
|
||||
pfds[used_pfds].fd = fd;
|
||||
pfds[used_pfds].events = POLLIN;
|
||||
pfds[used_pfds].revents = 0;
|
||||
used_pfds++;
|
||||
|
||||
lc->next = callbacks;
|
||||
callbacks = lc;
|
||||
LOG_DBG("Adding %s/%d", lc->name, lc->fd);
|
||||
LOG_DBG(" used_pfds = %d, free_pfds = %d",
|
||||
used_pfds, free_pfds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int links_unregister(int fd)
|
||||
{
|
||||
int i;
|
||||
struct link_callback *p, *c;
|
||||
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (fd == pfds[i].fd) {
|
||||
/* entire struct is copied (overwritten) */
|
||||
pfds[i] = pfds[used_pfds - 1];
|
||||
used_pfds--;
|
||||
free_pfds++;
|
||||
}
|
||||
|
||||
for (p = NULL, c = callbacks; c; p = c, c = c->next)
|
||||
if (fd == c->fd) {
|
||||
LOG_DBG("Freeing up %s/%d", c->name, c->fd);
|
||||
LOG_DBG(" used_pfds = %d, free_pfds = %d",
|
||||
used_pfds, free_pfds);
|
||||
if (p)
|
||||
p->next = c->next;
|
||||
else
|
||||
callbacks = c->next;
|
||||
free(c);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int links_monitor(void)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < used_pfds; i++) {
|
||||
pfds[i].revents = 0;
|
||||
}
|
||||
|
||||
r = poll(pfds, used_pfds, -1);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = 0;
|
||||
/* FIXME: handle POLLHUP */
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (pfds[i].revents & POLLIN) {
|
||||
LOG_DBG("Data ready on %d", pfds[i].fd);
|
||||
|
||||
/* FIXME: Add this back return 1;*/
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int links_issue_callbacks(void)
|
||||
{
|
||||
int i;
|
||||
struct link_callback *lc;
|
||||
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (pfds[i].revents & POLLIN)
|
||||
for (lc = callbacks; lc; lc = lc->next)
|
||||
if (pfds[i].fd == lc->fd) {
|
||||
LOG_DBG("Issuing callback on %s/%d",
|
||||
lc->name, lc->fd);
|
||||
lc->callback(lc->data);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
9
daemons/clogd/link_mon.h
Normal file
9
daemons/clogd/link_mon.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __LINK_MON_DOT_H__
|
||||
#define __LINK_MON_DOT_H__
|
||||
|
||||
int links_register(int fd, char *name, int (*callback)(void *data), void *data);
|
||||
int links_unregister(int fd);
|
||||
int links_monitor(void);
|
||||
int links_issue_callbacks(void);
|
||||
|
||||
#endif /* __LINK_MON_DOT_H__ */
|
||||
403
daemons/clogd/local.c
Normal file
403
daemons/clogd/local.c
Normal file
@@ -0,0 +1,403 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/poll.h>
|
||||
#include <linux/connector.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#include "linux/dm-log-userspace.h"
|
||||
#include "functions.h"
|
||||
#include "cluster.h"
|
||||
#include "common.h"
|
||||
#include "logging.h"
|
||||
#include "link_mon.h"
|
||||
#include "local.h"
|
||||
|
||||
static int cn_fd; /* Connector (netlink) socket fd */
|
||||
static char recv_buf[2048];
|
||||
static char send_buf[2048];
|
||||
|
||||
|
||||
/* FIXME: merge this function with kernel_send_helper */
|
||||
static int kernel_ack(uint32_t seq, int error)
|
||||
{
|
||||
int r;
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)send_buf;
|
||||
struct cn_msg *msg = NLMSG_DATA(nlh);
|
||||
|
||||
if (error < 0) {
|
||||
LOG_ERROR("Programmer error: error codes must be positive");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
nlh->nlmsg_seq = 0;
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
msg->len = 0;
|
||||
msg->id.idx = CN_IDX_DM;
|
||||
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
|
||||
msg->seq = seq;
|
||||
msg->ack = error;
|
||||
|
||||
r = send(cn_fd, nlh, NLMSG_LENGTH(sizeof(struct cn_msg)), 0);
|
||||
/* FIXME: do better error processing */
|
||||
if (r <= 0)
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* kernel_recv
|
||||
* @rq: the newly allocated request from kernel
|
||||
*
|
||||
* Read requests from the kernel and allocate space for the new request.
|
||||
* If there is no request from the kernel, *rq is NULL.
|
||||
*
|
||||
* This function is not thread safe due to returned stack pointer. In fact,
|
||||
* the returned pointer must not be in-use when this function is called again.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on error
|
||||
*/
|
||||
static int kernel_recv(struct clog_request **rq)
|
||||
{
|
||||
int r = 0;
|
||||
int len;
|
||||
struct cn_msg *msg;
|
||||
struct dm_ulog_request *u_rq;
|
||||
|
||||
*rq = NULL;
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
|
||||
len = recv(cn_fd, recv_buf, sizeof(recv_buf), 0);
|
||||
if (len < 0) {
|
||||
LOG_ERROR("Failed to recv message from kernel");
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (((struct nlmsghdr *)recv_buf)->nlmsg_type) {
|
||||
case NLMSG_ERROR:
|
||||
LOG_ERROR("Unable to recv message from kernel: NLMSG_ERROR");
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
case NLMSG_DONE:
|
||||
msg = (struct cn_msg *)NLMSG_DATA((struct nlmsghdr *)recv_buf);
|
||||
len -= sizeof(struct nlmsghdr);
|
||||
|
||||
if (len < sizeof(struct cn_msg)) {
|
||||
LOG_ERROR("Incomplete request from kernel received");
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (msg->len > DM_ULOG_REQUEST_SIZE) {
|
||||
LOG_ERROR("Not enough space to receive kernel request (%d/%d)",
|
||||
msg->len, DM_ULOG_REQUEST_SIZE);
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!msg->len)
|
||||
LOG_ERROR("Zero length message received");
|
||||
|
||||
len -= sizeof(struct cn_msg);
|
||||
|
||||
if (len < msg->len)
|
||||
LOG_ERROR("len = %d, msg->len = %d", len, msg->len);
|
||||
|
||||
msg->data[msg->len] = '\0'; /* Cleaner way to ensure this? */
|
||||
u_rq = (struct dm_ulog_request *)msg->data;
|
||||
|
||||
if (!u_rq->request_type) {
|
||||
LOG_DBG("Bad transmission, requesting resend [%u]",
|
||||
msg->seq);
|
||||
r = -EAGAIN;
|
||||
|
||||
if (kernel_ack(msg->seq, EAGAIN)) {
|
||||
LOG_ERROR("Failed to NACK kernel transmission [%u]",
|
||||
msg->seq);
|
||||
r = -EBADE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we've got sizeof(struct cn_msg) + sizeof(struct nlmsghdr)
|
||||
* worth of space that precede the request structure from the
|
||||
* kernel. Since that space isn't going to be used again, we
|
||||
* can take it for our purposes; rather than allocating a whole
|
||||
* new structure and doing a memcpy.
|
||||
*
|
||||
* We should really make sure 'clog_request' doesn't grow
|
||||
* beyond what is available to us, but we need only check it
|
||||
* once... perhaps at compile time?
|
||||
*/
|
||||
// *rq = container_of(u_rq, struct clog_request, u_rq);
|
||||
*rq = (void *)u_rq -
|
||||
(sizeof(struct clog_request) -
|
||||
sizeof(struct dm_ulog_request));
|
||||
|
||||
/* Clear the wrapper container fields */
|
||||
memset(*rq, 0, (void *)u_rq - (void *)(*rq));
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown nlmsg_type");
|
||||
r = -EBADE;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (r)
|
||||
*rq = NULL;
|
||||
|
||||
return (r == -EAGAIN) ? 0 : r;
|
||||
}
|
||||
|
||||
static int kernel_send_helper(void *data, int out_size)
|
||||
{
|
||||
int r;
|
||||
struct nlmsghdr *nlh;
|
||||
struct cn_msg *msg;
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
nlh = (struct nlmsghdr *)send_buf;
|
||||
nlh->nlmsg_seq = 0; /* FIXME: Is this used? */
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(out_size + sizeof(struct cn_msg));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
msg = NLMSG_DATA(nlh);
|
||||
memcpy(msg->data, data, out_size);
|
||||
msg->len = out_size;
|
||||
msg->id.idx = CN_IDX_DM;
|
||||
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
|
||||
msg->seq = 0;
|
||||
|
||||
r = send(cn_fd, nlh, NLMSG_LENGTH(out_size + sizeof(struct cn_msg)), 0);
|
||||
/* FIXME: do better error processing */
|
||||
if (r <= 0)
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_local_work
|
||||
*
|
||||
* Any processing errors are placed in the 'rq'
|
||||
* structure to be reported back to the kernel.
|
||||
* It may be pointless for this function to
|
||||
* return an int.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
static int do_local_work(void *data)
|
||||
{
|
||||
int r;
|
||||
struct clog_request *rq;
|
||||
struct dm_ulog_request *u_rq = NULL;
|
||||
|
||||
r = kernel_recv(&rq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!rq)
|
||||
return 0;
|
||||
|
||||
u_rq = &rq->u_rq;
|
||||
LOG_DBG("[%s] Request from kernel received: [%s/%u]",
|
||||
SHORT_UUID(u_rq->uuid), RQ_TYPE(u_rq->request_type),
|
||||
u_rq->seq);
|
||||
switch (u_rq->request_type) {
|
||||
case DM_ULOG_CTR:
|
||||
case DM_ULOG_DTR:
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
case DM_ULOG_STATUS_INFO:
|
||||
case DM_ULOG_STATUS_TABLE:
|
||||
case DM_ULOG_PRESUSPEND:
|
||||
/* We do not specify ourselves as server here */
|
||||
r = do_request(rq, 0);
|
||||
if (r)
|
||||
LOG_DBG("Returning failed request to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
r = kernel_send(u_rq);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to respond to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
|
||||
break;
|
||||
case DM_ULOG_RESUME:
|
||||
/*
|
||||
* Resume is a special case that requires a local
|
||||
* component to join the CPG, and a cluster component
|
||||
* to handle the request.
|
||||
*/
|
||||
r = local_resume(u_rq);
|
||||
if (r) {
|
||||
LOG_DBG("Returning failed request to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
r = kernel_send(u_rq);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to respond to kernel [%s]",
|
||||
RQ_TYPE(u_rq->request_type));
|
||||
break;
|
||||
}
|
||||
/* ELSE, fall through */
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_FLUSH:
|
||||
case DM_ULOG_MARK_REGION:
|
||||
case DM_ULOG_GET_RESYNC_WORK:
|
||||
case DM_ULOG_SET_REGION_SYNC:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
case DM_ULOG_POSTSUSPEND:
|
||||
r = cluster_send(rq);
|
||||
if (r) {
|
||||
u_rq->data_size = 0;
|
||||
u_rq->error = r;
|
||||
kernel_send(u_rq);
|
||||
}
|
||||
|
||||
break;
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
r = kernel_ack(u_rq->seq, 0);
|
||||
|
||||
r = cluster_send(rq);
|
||||
if (r) {
|
||||
/*
|
||||
* FIXME: store error for delivery on flush
|
||||
* This would allow us to optimize MARK_REGION
|
||||
* too.
|
||||
*/
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Invalid log request received (%u), ignoring.",
|
||||
u_rq->request_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (r && !u_rq->error)
|
||||
u_rq->error = r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* kernel_send
|
||||
* @u_rq: result to pass back to kernel
|
||||
*
|
||||
* This function returns the u_rq structure
|
||||
* (containing the results) to the kernel.
|
||||
* It then frees the structure.
|
||||
*
|
||||
* WARNING: should the structure be freed if
|
||||
* there is an error? I vote 'yes'. If the
|
||||
* kernel doesn't get the response, it should
|
||||
* resend the request.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
int kernel_send(struct dm_ulog_request *u_rq)
|
||||
{
|
||||
int r;
|
||||
int size;
|
||||
|
||||
if (!u_rq)
|
||||
return -EINVAL;
|
||||
|
||||
size = sizeof(struct dm_ulog_request) + u_rq->data_size;
|
||||
|
||||
if (!u_rq->data_size && !u_rq->error) {
|
||||
/* An ACK is all that is needed */
|
||||
|
||||
/* FIXME: add ACK code */
|
||||
} else if (size > DM_ULOG_REQUEST_SIZE) {
|
||||
/*
|
||||
* If we gotten here, we've already overrun
|
||||
* our allotted space somewhere.
|
||||
*
|
||||
* We must do something, because the kernel
|
||||
* is waiting for a response.
|
||||
*/
|
||||
LOG_ERROR("Not enough space to respond to server");
|
||||
u_rq->error = -ENOSPC;
|
||||
size = sizeof(struct dm_ulog_request);
|
||||
}
|
||||
|
||||
r = kernel_send_helper(u_rq, size);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to send msg to kernel.");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_local
|
||||
*
|
||||
* Initialize kernel communication socket (netlink)
|
||||
*
|
||||
* Returns: 0 on success, values from common.h on failure
|
||||
*/
|
||||
int init_local(void)
|
||||
{
|
||||
int r = 0;
|
||||
int opt;
|
||||
struct sockaddr_nl addr;
|
||||
|
||||
cn_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||
if (cn_fd < 0)
|
||||
return EXIT_KERNEL_SOCKET;
|
||||
|
||||
/* memset to fix valgrind complaint */
|
||||
memset(&addr, 0, sizeof(struct sockaddr_nl));
|
||||
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = CN_IDX_DM;
|
||||
addr.nl_pid = 0;
|
||||
|
||||
r = bind(cn_fd, (struct sockaddr *) &addr, sizeof(addr));
|
||||
if (r < 0) {
|
||||
close(cn_fd);
|
||||
return EXIT_KERNEL_BIND;
|
||||
}
|
||||
|
||||
opt = addr.nl_groups;
|
||||
r = setsockopt(cn_fd, 270, NETLINK_ADD_MEMBERSHIP, &opt, sizeof(opt));
|
||||
if (r) {
|
||||
close(cn_fd);
|
||||
return EXIT_KERNEL_SETSOCKOPT;
|
||||
}
|
||||
|
||||
/*
|
||||
r = fcntl(cn_fd, F_SETFL, FNDELAY);
|
||||
*/
|
||||
|
||||
links_register(cn_fd, "local", do_local_work, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup_local
|
||||
*
|
||||
* Clean up before exiting
|
||||
*/
|
||||
void cleanup_local(void)
|
||||
{
|
||||
links_unregister(cn_fd);
|
||||
close(cn_fd);
|
||||
}
|
||||
9
daemons/clogd/local.h
Normal file
9
daemons/clogd/local.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __CLUSTER_LOG_LOCAL_DOT_H__
|
||||
#define __CLUSTER_LOG_LOCAL_DOT_H__
|
||||
|
||||
int init_local(void);
|
||||
void cleanup_local(void);
|
||||
|
||||
int kernel_send(struct dm_ulog_request *rq);
|
||||
|
||||
#endif /* __CLUSTER_LOG_LOCAL_DOT_H__ */
|
||||
47
daemons/clogd/logging.c
Normal file
47
daemons/clogd/logging.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
|
||||
char *__rq_types_off_by_one[] = {
|
||||
"DM_ULOG_CTR",
|
||||
"DM_ULOG_DTR",
|
||||
"DM_ULOG_PRESUSPEND",
|
||||
"DM_ULOG_POSTSUSPEND",
|
||||
"DM_ULOG_RESUME",
|
||||
"DM_ULOG_GET_REGION_SIZE",
|
||||
"DM_ULOG_IS_CLEAN",
|
||||
"DM_ULOG_IN_SYNC",
|
||||
"DM_ULOG_FLUSH",
|
||||
"DM_ULOG_MARK_REGION",
|
||||
"DM_ULOG_CLEAR_REGION",
|
||||
"DM_ULOG_GET_RESYNC_WORK",
|
||||
"DM_ULOG_SET_REGION_SYNC",
|
||||
"DM_ULOG_GET_SYNC_COUNT",
|
||||
"DM_ULOG_STATUS_INFO",
|
||||
"DM_ULOG_STATUS_TABLE",
|
||||
"DM_ULOG_IS_REMOTE_RECOVERING",
|
||||
NULL
|
||||
};
|
||||
|
||||
int log_tabbing = 0;
|
||||
int log_is_open = 0;
|
||||
|
||||
/*
|
||||
* Variables for various conditional logging
|
||||
*/
|
||||
#ifdef MEMB
|
||||
int log_membership_change = 1;
|
||||
#else
|
||||
int log_membership_change = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CKPT
|
||||
int log_checkpoint = 1;
|
||||
#else
|
||||
int log_checkpoint = 0;
|
||||
#endif
|
||||
|
||||
#ifdef RESEND
|
||||
int log_resend_requests = 1;
|
||||
#else
|
||||
int log_resend_requests = 0;
|
||||
#endif
|
||||
60
daemons/clogd/logging.h
Normal file
60
daemons/clogd/logging.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef __CLUSTER_LOG_LOGGING_DOT_H__
|
||||
#define __CLUSTER_LOG_LOGGING_DOT_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/* SHORT_UUID - print last 8 chars of a string */
|
||||
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
|
||||
|
||||
extern char *__rq_types_off_by_one[];
|
||||
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
|
||||
|
||||
extern int log_tabbing;
|
||||
extern int log_is_open;
|
||||
extern int log_membership_change;
|
||||
extern int log_checkpoint;
|
||||
extern int log_resend_requests;
|
||||
|
||||
#define LOG_OPEN(ident, option, facility) do { \
|
||||
openlog(ident, option, facility); \
|
||||
log_is_open = 1; \
|
||||
} while (0)
|
||||
|
||||
#define LOG_CLOSE(void) do { \
|
||||
log_is_open = 0; \
|
||||
closelog(); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_OUTPUT(level, f, arg...) do { \
|
||||
int __i; \
|
||||
char __buffer[16]; \
|
||||
FILE *fp = (level > LOG_NOTICE) ? stderr : stdout; \
|
||||
if (log_is_open) { \
|
||||
for (__i = 0; (__i < log_tabbing) && (__i < 15); __i++) \
|
||||
__buffer[__i] = '\t'; \
|
||||
__buffer[__i] = '\0'; \
|
||||
syslog(level, "%s" f "\n", __buffer, ## arg); \
|
||||
} else { \
|
||||
for (__i = 0; __i < log_tabbing; __i++) \
|
||||
fprintf(fp, "\t"); \
|
||||
fprintf(fp, f "\n", ## arg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
|
||||
#else /* DEBUG */
|
||||
#define LOG_DBG(f, arg...)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define LOG_COND(__X, f, arg...) do {\
|
||||
if (__X) { \
|
||||
LOG_OUTPUT(LOG_NOTICE, f, ## arg); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_PRINT(f, arg...) LOG_OUTPUT(LOG_NOTICE, f, ## arg)
|
||||
#define LOG_ERROR(f, arg...) LOG_OUTPUT(LOG_ERR, f, ## arg)
|
||||
|
||||
#endif /* __CLUSTER_LOG_LOGGING_DOT_H__ */
|
||||
@@ -15,30 +15,40 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
QUORUM_LIBS = @QUORUM_LIBS@
|
||||
QUORUM_CFLAGS = @QUORUM_CFLAGS@
|
||||
CONFDB_LIBS = @CONFDB_LIBS@
|
||||
CONFDB_CFLAGS = @CONFDB_CFLAGS@
|
||||
CPG_LIBS = @CPG_LIBS@
|
||||
CPG_CFLAGS = @CPG_CFLAGS@
|
||||
|
||||
SOURCES = \
|
||||
clvmd-command.c \
|
||||
clvmd.c \
|
||||
lvm-functions.c \
|
||||
refresh_clvmd.c
|
||||
|
||||
ifeq ("@CLVMD@", "gulm")
|
||||
ifneq (,$(findstring gulm,, "@CLVMD@,"))
|
||||
GULM = yes
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "cman")
|
||||
ifneq (,$(findstring cman,, "@CLVMD@,"))
|
||||
CMAN = yes
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "openais")
|
||||
ifneq (,$(findstring openais,, "@CLVMD@,"))
|
||||
OPENAIS = yes
|
||||
GULM = no
|
||||
CMAN = no
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "all")
|
||||
ifneq (,$(findstring corosync,, "@CLVMD@,"))
|
||||
COROSYNC = yes
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring all,, "@CLVMD@,"))
|
||||
GULM = yes
|
||||
CMAN = yes
|
||||
OPENAIS = no
|
||||
OPENAIS = yes
|
||||
COROSYNC = yes
|
||||
endif
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
@@ -63,10 +73,18 @@ ifeq ("$(OPENAIS)", "yes")
|
||||
DEFS += -DUSE_OPENAIS
|
||||
endif
|
||||
|
||||
ifeq ("$(COROSYNC)", "yes")
|
||||
SOURCES += clvmd-corosync.c
|
||||
LMLIBS += $(QUORUM_LIBS) $(CONFDB_LIBS) $(CPG_LIBS) -ldlm
|
||||
CFLAGS += $(QUORUM_CFLAGS) $(CONFDB_CFLAGS) $(CPG_CFLAGS)
|
||||
DEFS += -DUSE_COROSYNC
|
||||
endif
|
||||
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
LVMLIBS = -llvm -lpthread
|
||||
LVMLIBS = -llvm-internal -lpthread
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
LVMLIBS += -ldevmapper-event
|
||||
@@ -82,7 +100,7 @@ include $(top_srcdir)/make.tmpl
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
|
||||
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm-internal.a
|
||||
$(CC) -o clvmd $(OBJECTS) $(CFLAGS) $(LDFLAGS) \
|
||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
@@ -90,7 +108,7 @@ clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
|
||||
|
||||
install_clvmd: $(TARGETS)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) clvmd \
|
||||
$(sbindir)/clvmd
|
||||
$(usrsbindir)/clvmd
|
||||
|
||||
install: $(INSTALL_TARGETS)
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ static const char CLVMD_SOCKNAME[] = "\0clvmd";
|
||||
/* Lock/Unlock commands */
|
||||
#define CLVMD_CMD_LOCK_LV 50
|
||||
#define CLVMD_CMD_LOCK_VG 51
|
||||
#define CLVMD_CMD_LOCK_QUERY 52
|
||||
|
||||
/* Misc functions */
|
||||
#define CLVMD_CMD_REFRESH 40
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
* CMAN communication layer for clvmd.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -36,23 +40,28 @@
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <libdevmapper.h>
|
||||
#include <libdlm.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
#include "log.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
struct clvmd_node
|
||||
{
|
||||
struct cman_node *node;
|
||||
int clvmd_up;
|
||||
};
|
||||
|
||||
static int num_nodes;
|
||||
static struct cman_node *nodes = NULL;
|
||||
static struct cman_node this_node;
|
||||
static int count_nodes; /* size of allocated nodes array */
|
||||
static int max_updown_nodes = 50; /* Current size of the allocated array */
|
||||
/* Node up/down status, indexed by nodeid */
|
||||
static int *node_updown = NULL;
|
||||
static struct dm_hash_table *node_updown_hash;
|
||||
static dlm_lshandle_t *lockspace;
|
||||
static cman_handle_t c_handle;
|
||||
|
||||
@@ -72,6 +81,8 @@ struct lock_wait {
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
node_updown_hash = dm_hash_create(100);
|
||||
|
||||
/* Open the cluster communication socket */
|
||||
c_handle = cman_init(NULL);
|
||||
if (!c_handle) {
|
||||
@@ -99,8 +110,13 @@ static int _init_cluster(void)
|
||||
/* Create a lockspace for LV & VG locks to live in */
|
||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
||||
if (!lockspace) {
|
||||
syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m");
|
||||
return -1;
|
||||
if (errno == EEXIST) {
|
||||
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
|
||||
}
|
||||
if (!lockspace) {
|
||||
syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
DEBUGLOG("DLM initialisation complete\n");
|
||||
@@ -165,8 +181,10 @@ static int _cluster_do_node_callback(struct local_client *client,
|
||||
|
||||
for (i = 0; i < _get_num_nodes(); i++) {
|
||||
if (nodes[i].cn_member && nodes[i].cn_nodeid) {
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
|
||||
if (!node_updown[nodes[i].cn_nodeid])
|
||||
int up = (int)(long)dm_hash_lookup_binary(node_updown_hash, (char *)&nodes[i].cn_nodeid, sizeof(int));
|
||||
|
||||
callback(client, (char *)&nodes[i].cn_nodeid, up);
|
||||
if (!up)
|
||||
somedown = -1;
|
||||
}
|
||||
}
|
||||
@@ -184,7 +202,7 @@ static void event_callback(cman_handle_t handle, void *private, int reason, int
|
||||
log_notice("clvmd on node %s has died\n", namebuf);
|
||||
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
|
||||
|
||||
node_updown[arg] = 0;
|
||||
dm_hash_insert_binary(node_updown_hash, (char *)&arg, sizeof(int), (void *)0);
|
||||
break;
|
||||
|
||||
case CMAN_REASON_STATECHANGE:
|
||||
@@ -239,28 +257,13 @@ static void _add_up_node(const char *csid)
|
||||
/* It's up ! */
|
||||
int nodeid = nodeid_from_csid(csid);
|
||||
|
||||
if (nodeid >= max_updown_nodes) {
|
||||
int new_size = nodeid + 10;
|
||||
int *new_updown = realloc(node_updown, new_size);
|
||||
|
||||
if (new_updown) {
|
||||
node_updown = new_updown;
|
||||
max_updown_nodes = new_size;
|
||||
DEBUGLOG("realloced more space for nodes. now %d\n",
|
||||
max_updown_nodes);
|
||||
} else {
|
||||
log_error
|
||||
("Realloc failed. Node status for clvmd will be wrong. quitting\n");
|
||||
exit(999);
|
||||
}
|
||||
}
|
||||
node_updown[nodeid] = 1;
|
||||
dm_hash_insert_binary(node_updown_hash, (char *)&nodeid, sizeof(int), (void *)1);
|
||||
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
||||
}
|
||||
|
||||
static void _cluster_closedown()
|
||||
{
|
||||
unlock_all();
|
||||
destroy_lvhash();
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
cman_finish(c_handle);
|
||||
}
|
||||
@@ -288,7 +291,12 @@ static void count_clvmds_running(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_nodes; i++) {
|
||||
node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
|
||||
int nodeid = nodes[i].cn_nodeid;
|
||||
|
||||
if (is_listening(nodeid) == 1)
|
||||
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)1);
|
||||
else
|
||||
dm_hash_insert_binary(node_updown_hash, (void *)&nodeid, sizeof(int), (void*)0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,6 +305,8 @@ static void get_members()
|
||||
{
|
||||
int retnodes;
|
||||
int status;
|
||||
int i;
|
||||
int high_nodeid = 0;
|
||||
|
||||
num_nodes = cman_get_node_count(c_handle);
|
||||
if (num_nodes == -1) {
|
||||
@@ -325,11 +335,10 @@ static void get_members()
|
||||
exit(6);
|
||||
}
|
||||
|
||||
if (node_updown == NULL) {
|
||||
size_t buf_len = sizeof(int) * max(num_nodes, max_updown_nodes);
|
||||
node_updown = malloc(buf_len);
|
||||
if (node_updown)
|
||||
memset(node_updown, 0, buf_len);
|
||||
/* Get the highest nodeid */
|
||||
for (i=0; i<retnodes; i++) {
|
||||
if (nodes[i].cn_nodeid > high_nodeid)
|
||||
high_nodeid = nodes[i].cn_nodeid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
@@ -67,9 +71,8 @@
|
||||
#include <libdevmapper.h>
|
||||
#include <libdlm.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "locking.h"
|
||||
#include "log.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
@@ -87,6 +90,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
|
||||
int status = 0;
|
||||
char *lockname;
|
||||
const char *locktype;
|
||||
struct utsname nodeinfo;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
@@ -118,9 +122,11 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
lockname = &args[2];
|
||||
/* Check to see if the VG is in use by LVM1 */
|
||||
status = do_check_lvm1(lockname);
|
||||
/* P_global causes a cache refresh */
|
||||
if (strcmp(lockname, "P_global") == 0)
|
||||
do_refresh_cache();
|
||||
/* P_#global causes a full cache refresh */
|
||||
if (!strcmp(lockname, "P_" VG_GLOBAL))
|
||||
do_refresh_cache();
|
||||
else
|
||||
drop_metadata(lockname + 2);
|
||||
|
||||
break;
|
||||
|
||||
@@ -139,6 +145,14 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
}
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_QUERY:
|
||||
lockname = &args[2];
|
||||
if (buflen < 3)
|
||||
return EIO;
|
||||
if ((locktype = do_lock_query(lockname)))
|
||||
*retlen = 1 + snprintf(*buf, buflen, "%s", locktype);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_REFRESH:
|
||||
do_refresh_cache();
|
||||
break;
|
||||
@@ -154,7 +168,11 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
lvm_do_backup(&args[2]);
|
||||
/*
|
||||
* Do not run backup on local node, caller should do that.
|
||||
*/
|
||||
if (!client)
|
||||
lvm_do_backup(&args[2]);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -251,7 +269,11 @@ int do_pre_command(struct local_client *client)
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
status = lock_vg(client);
|
||||
lockname = &args[2];
|
||||
/* We take out a real lock unless LCK_CACHE was set */
|
||||
if (!strncmp(lockname, "V_", 2) ||
|
||||
!strncmp(lockname, "P_#", 3))
|
||||
status = lock_vg(client);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
@@ -265,6 +287,7 @@ int do_pre_command(struct local_client *client)
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
case CLVMD_CMD_SET_DEBUG:
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
case CLVMD_CMD_LOCK_QUERY:
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -295,6 +318,7 @@ int do_post_command(struct local_client *client)
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
case CLVMD_CMD_LOCK_QUERY:
|
||||
/* Nothing to do here */
|
||||
break;
|
||||
|
||||
|
||||
@@ -93,5 +93,22 @@ struct cluster_ops *init_cman_cluster(void);
|
||||
struct cluster_ops *init_openais_cluster(void);
|
||||
#endif
|
||||
|
||||
#ifdef USE_COROSYNC
|
||||
# include <corosync/corotypes.h>
|
||||
# define COROSYNC_CSID_LEN (sizeof(int))
|
||||
# define COROSYNC_MAX_CLUSTER_MESSAGE 65535
|
||||
# define COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
|
||||
# ifndef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||
# define MAX_CLUSTER_MEMBER_NAME_LEN CS_MAX_NAME_LENGTH
|
||||
# endif
|
||||
# ifndef CMAN_MAX_CLUSTER_MESSAGE
|
||||
# define CMAN_MAX_CLUSTER_MESSAGE 65535
|
||||
# endif
|
||||
# ifndef MAX_CSID_LEN
|
||||
# define MAX_CSID_LEN sizeof(int)
|
||||
# endif
|
||||
struct cluster_ops *init_corosync_cluster(void);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
643
daemons/clvmd/clvmd-corosync.c
Normal file
643
daemons/clvmd/clvmd-corosync.c
Normal file
@@ -0,0 +1,643 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/* This provides the interface between clvmd and corosync/DLM as the cluster
|
||||
* and lock manager.
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <utmpx.h>
|
||||
#include <syslog.h>
|
||||
#include <assert.h>
|
||||
#include <libdevmapper.h>
|
||||
|
||||
#include <corosync/corotypes.h>
|
||||
#include <corosync/cpg.h>
|
||||
#include <corosync/quorum.h>
|
||||
#include <corosync/confdb.h>
|
||||
#include <libdlm.h>
|
||||
|
||||
#include "locking.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvmd.h"
|
||||
|
||||
/* Timeout value for several corosync calls */
|
||||
#define LOCKSPACE_NAME "clvmd"
|
||||
|
||||
static void cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len);
|
||||
static void cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries);
|
||||
static void _cluster_closedown(void);
|
||||
|
||||
/* Hash list of nodes in the cluster */
|
||||
static struct dm_hash_table *node_hash;
|
||||
|
||||
/* Number of active nodes */
|
||||
static int num_nodes;
|
||||
static unsigned int our_nodeid;
|
||||
|
||||
static struct local_client *cluster_client;
|
||||
|
||||
/* Corosync handles */
|
||||
static cpg_handle_t cpg_handle;
|
||||
static quorum_handle_t quorum_handle;
|
||||
|
||||
/* DLM Handle */
|
||||
static dlm_lshandle_t *lockspace;
|
||||
|
||||
static struct cpg_name cpg_group_name;
|
||||
|
||||
/* Corosync callback structs */
|
||||
cpg_callbacks_t cpg_callbacks = {
|
||||
.cpg_deliver_fn = cpg_deliver_callback,
|
||||
.cpg_confchg_fn = cpg_confchg_callback,
|
||||
};
|
||||
|
||||
quorum_callbacks_t quorum_callbacks = {
|
||||
.quorum_notify_fn = NULL,
|
||||
};
|
||||
|
||||
struct node_info
|
||||
{
|
||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
int nodeid;
|
||||
};
|
||||
|
||||
|
||||
/* Set errno to something approximating the right value and return 0 or -1 */
|
||||
static int cs_to_errno(cs_error_t err)
|
||||
{
|
||||
switch(err)
|
||||
{
|
||||
case CS_OK:
|
||||
return 0;
|
||||
case CS_ERR_LIBRARY:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_VERSION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_INIT:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_TIMEOUT:
|
||||
errno = ETIME;
|
||||
break;
|
||||
case CS_ERR_TRY_AGAIN:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
case CS_ERR_INVALID_PARAM:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_NO_MEMORY:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case CS_ERR_BAD_HANDLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_BUSY:
|
||||
errno = EBUSY;
|
||||
break;
|
||||
case CS_ERR_ACCESS:
|
||||
errno = EPERM;
|
||||
break;
|
||||
case CS_ERR_NOT_EXIST:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case CS_ERR_NAME_TOO_LONG:
|
||||
errno = ENAMETOOLONG;
|
||||
break;
|
||||
case CS_ERR_EXIST:
|
||||
errno = EEXIST;
|
||||
break;
|
||||
case CS_ERR_NO_SPACE:
|
||||
errno = ENOSPC;
|
||||
break;
|
||||
case CS_ERR_INTERRUPT:
|
||||
errno = EINTR;
|
||||
break;
|
||||
case CS_ERR_NAME_NOT_FOUND:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case CS_ERR_NO_RESOURCES:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case CS_ERR_NOT_SUPPORTED:
|
||||
errno = EOPNOTSUPP;
|
||||
break;
|
||||
case CS_ERR_BAD_OPERATION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_FAILED_OPERATION:
|
||||
errno = EIO;
|
||||
break;
|
||||
case CS_ERR_MESSAGE_ERROR:
|
||||
errno = EIO;
|
||||
break;
|
||||
case CS_ERR_QUEUE_FULL:
|
||||
errno = EXFULL;
|
||||
break;
|
||||
case CS_ERR_QUEUE_NOT_AVAILABLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_BAD_FLAGS:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_TOO_BIG:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case CS_ERR_NO_SECTIONS:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *print_corosync_csid(const char *csid)
|
||||
{
|
||||
static char buf[128];
|
||||
int id;
|
||||
|
||||
memcpy(&id, csid, sizeof(int));
|
||||
sprintf(buf, "%d", id);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len)
|
||||
{
|
||||
int target_nodeid;
|
||||
|
||||
memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
|
||||
|
||||
DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
|
||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
||||
|
||||
if (nodeid != our_nodeid)
|
||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
||||
process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
|
||||
msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
|
||||
}
|
||||
|
||||
static void cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
||||
{
|
||||
int i;
|
||||
struct node_info *ninfo;
|
||||
|
||||
DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n",
|
||||
joined_list_entries, left_list_entries, member_list_entries);
|
||||
|
||||
for (i=0; i<joined_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&joined_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = joined_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
COROSYNC_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
for (i=0; i<left_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&left_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (ninfo)
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
for (i=0; i<member_list_entries; i++) {
|
||||
if (member_list[i].nodeid == 0) continue;
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&member_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = member_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
COROSYNC_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
cs_error_t err;
|
||||
|
||||
node_hash = dm_hash_create(100);
|
||||
|
||||
err = cpg_initialize(&cpg_handle,
|
||||
&cpg_callbacks);
|
||||
if (err != CS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
err = quorum_initialize(&quorum_handle,
|
||||
&quorum_callbacks);
|
||||
if (err != CS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise Corosync quorum service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise Corosync quorum service: %d", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
|
||||
/* Create a lockspace for LV & VG locks to live in */
|
||||
lockspace = dlm_create_lockspace(LOCKSPACE_NAME, 0600);
|
||||
if (!lockspace) {
|
||||
if (errno == EEXIST) {
|
||||
lockspace = dlm_open_lockspace(LOCKSPACE_NAME);
|
||||
}
|
||||
if (!lockspace) {
|
||||
syslog(LOG_ERR, "Unable to create lockspace for CLVM: %m");
|
||||
quorum_finalize(quorum_handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
dlm_ls_pthread_init(lockspace);
|
||||
DEBUGLOG("DLM initialisation complete\n");
|
||||
|
||||
/* Connect to the clvmd group */
|
||||
strcpy((char *)cpg_group_name.value, "clvmd");
|
||||
cpg_group_name.length = strlen((char *)cpg_group_name.value);
|
||||
err = cpg_join(cpg_handle, &cpg_group_name);
|
||||
if (err != CS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
syslog(LOG_ERR, "Cannot join clvmd process group");
|
||||
DEBUGLOG("Cannot join clvmd process group: %d\n", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
err = cpg_local_get(cpg_handle,
|
||||
&our_nodeid);
|
||||
if (err != CS_OK) {
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
syslog(LOG_ERR, "Cannot get local node id\n");
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
DEBUGLOG("Our local node id is %d\n", our_nodeid);
|
||||
|
||||
DEBUGLOG("Connected to Corosync\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
destroy_lvhash();
|
||||
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
cpg_finalize(cpg_handle);
|
||||
quorum_finalize(quorum_handle);
|
||||
}
|
||||
|
||||
static void _get_our_csid(char *csid)
|
||||
{
|
||||
memcpy(csid, &our_nodeid, sizeof(int));
|
||||
}
|
||||
|
||||
/* Corosync doesn't really have nmode names so we
|
||||
just use the node ID in hex instead */
|
||||
static int _csid_from_name(char *csid, const char *name)
|
||||
{
|
||||
int nodeid;
|
||||
struct node_info *ninfo;
|
||||
|
||||
if (sscanf(name, "%x", &nodeid) == 1) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (ninfo)
|
||||
return nodeid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _name_from_csid(const char *csid, char *name)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
sprintf(name, "UNKNOWN %s", print_corosync_csid(csid));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(name, "%x", ninfo->nodeid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_num_nodes()
|
||||
{
|
||||
DEBUGLOG("num_nodes = %d\n", num_nodes);
|
||||
return num_nodes;
|
||||
}
|
||||
|
||||
/* Node is now known to be running a clvmd */
|
||||
static void _add_up_node(const char *csid)
|
||||
{
|
||||
struct node_info *ninfo;
|
||||
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
DEBUGLOG("corosync_add_up_node no node_hash entry for csid %s\n",
|
||||
print_corosync_csid(csid));
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGLOG("corosync_add_up_node %d\n", ninfo->nodeid);
|
||||
|
||||
ninfo->state = NODE_CLVMD;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call a callback for each node, so the caller knows whether it's up or down */
|
||||
static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
void (*callback)(struct local_client *,
|
||||
const char *csid, int node_up))
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
char csid[COROSYNC_CSID_LEN];
|
||||
|
||||
ninfo = dm_hash_get_data(node_hash, hn);
|
||||
memcpy(csid, dm_hash_get_key(node_hash, hn), COROSYNC_CSID_LEN);
|
||||
|
||||
DEBUGLOG("down_callback. node %d, state = %d\n", ninfo->nodeid,
|
||||
ninfo->state);
|
||||
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(const char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
struct dlm_lksb lksb;
|
||||
int err;
|
||||
|
||||
DEBUGLOG("lock_resource '%s', flags=%d, mode=%d\n", resource, flags, mode);
|
||||
|
||||
if (flags & LKF_CONVERT)
|
||||
lksb.sb_lkid = *lockid;
|
||||
|
||||
err = dlm_ls_lock_wait(lockspace,
|
||||
mode,
|
||||
&lksb,
|
||||
flags,
|
||||
resource,
|
||||
strlen(resource),
|
||||
0,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_lock returned %d\n", errno);
|
||||
return err;
|
||||
}
|
||||
if (lksb.sb_status != 0)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_lock returns lksb.sb_status %d\n", lksb.sb_status);
|
||||
errno = lksb.sb_status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGLOG("lock_resource returning %d, lock_id=%x\n", err, lksb.sb_lkid);
|
||||
|
||||
*lockid = lksb.sb_lkid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int _unlock_resource(const char *resource, int lockid)
|
||||
{
|
||||
struct dlm_lksb lksb;
|
||||
int err;
|
||||
|
||||
DEBUGLOG("unlock_resource: %s lockid: %x\n", resource, lockid);
|
||||
lksb.sb_lkid = lockid;
|
||||
|
||||
err = dlm_ls_unlock_wait(lockspace,
|
||||
lockid,
|
||||
0,
|
||||
&lksb);
|
||||
if (err != 0)
|
||||
{
|
||||
DEBUGLOG("Unlock returned %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (lksb.sb_status != EUNLOCK)
|
||||
{
|
||||
DEBUGLOG("dlm_ls_unlock_wait returns lksb.sb_status: %d\n", lksb.sb_status);
|
||||
errno = lksb.sb_status;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _is_quorate()
|
||||
{
|
||||
int quorate;
|
||||
if (quorum_getquorate(quorum_handle, &quorate) == CS_OK)
|
||||
return quorate;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_main_cluster_fd(void)
|
||||
{
|
||||
int select_fd;
|
||||
|
||||
cpg_fd_get(cpg_handle, &select_fd);
|
||||
return select_fd;
|
||||
}
|
||||
|
||||
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len,
|
||||
const char *csid,
|
||||
struct local_client **new_client)
|
||||
{
|
||||
cluster_client = fd;
|
||||
*new_client = NULL;
|
||||
cpg_dispatch(cpg_handle, CS_DISPATCH_ONE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid,
|
||||
const char *errtext)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
cs_error_t err;
|
||||
int target_node;
|
||||
|
||||
if (csid)
|
||||
memcpy(&target_node, csid, COROSYNC_CSID_LEN);
|
||||
else
|
||||
target_node = 0;
|
||||
|
||||
iov[0].iov_base = &target_node;
|
||||
iov[0].iov_len = sizeof(int);
|
||||
iov[1].iov_base = (char *)buf;
|
||||
iov[1].iov_len = msglen;
|
||||
|
||||
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
/*
|
||||
* We are not necessarily connected to a Red Hat Cluster system,
|
||||
* but if we are, this returns the cluster name from cluster.conf.
|
||||
* I've used confdb rather than ccs to reduce the inter-package
|
||||
* dependancies as well as to allow people to set a cluster name
|
||||
* for themselves even if they are not running on RH cluster.
|
||||
*/
|
||||
static int _get_cluster_name(char *buf, int buflen)
|
||||
{
|
||||
confdb_handle_t handle;
|
||||
int result;
|
||||
size_t namelen = buflen;
|
||||
hdb_handle_t cluster_handle;
|
||||
confdb_callbacks_t callbacks = {
|
||||
.confdb_key_change_notify_fn = NULL,
|
||||
.confdb_object_create_change_notify_fn = NULL,
|
||||
.confdb_object_delete_change_notify_fn = NULL
|
||||
};
|
||||
|
||||
/* This is a default in case everything else fails */
|
||||
strncpy(buf, "Corosync", buflen);
|
||||
|
||||
/* Look for a cluster name in confdb */
|
||||
result = confdb_initialize (&handle, &callbacks);
|
||||
if (result != CS_OK)
|
||||
return 0;
|
||||
|
||||
result = confdb_object_find_start(handle, OBJECT_PARENT_HANDLE);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
result = confdb_object_find(handle, OBJECT_PARENT_HANDLE, (void *)"cluster", strlen("cluster"), &cluster_handle);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
result = confdb_key_get(handle, cluster_handle, (void *)"name", strlen("name"), buf, &namelen);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
buf[namelen] = '\0';
|
||||
|
||||
out:
|
||||
confdb_finalize(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cluster_ops _cluster_corosync_ops = {
|
||||
.cluster_init_completed = NULL,
|
||||
.cluster_send_message = _cluster_send_message,
|
||||
.name_from_csid = _name_from_csid,
|
||||
.csid_from_name = _csid_from_name,
|
||||
.get_num_nodes = _get_num_nodes,
|
||||
.cluster_fd_callback = _cluster_fd_callback,
|
||||
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||
.is_quorate = _is_quorate,
|
||||
.get_our_csid = _get_our_csid,
|
||||
.add_up_node = _add_up_node,
|
||||
.reread_config = NULL,
|
||||
.cluster_closedown = _cluster_closedown,
|
||||
.get_cluster_name = _get_cluster_name,
|
||||
.sync_lock = _lock_resource,
|
||||
.sync_unlock = _unlock_resource,
|
||||
};
|
||||
|
||||
struct cluster_ops *init_corosync_cluster(void)
|
||||
{
|
||||
if (!_init_cluster())
|
||||
return &_cluster_corosync_ops;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@@ -44,9 +44,8 @@
|
||||
#include <ccs.h>
|
||||
#include <libgulm.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "locking.h"
|
||||
#include "log.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
@@ -249,7 +248,7 @@ static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
in_shutdown = 1;
|
||||
unlock_all();
|
||||
destroy_lvhash();
|
||||
lg_lock_logout(gulm_if);
|
||||
lg_core_logout(gulm_if);
|
||||
lg_release(gulm_if);
|
||||
@@ -665,6 +664,7 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
@@ -686,12 +686,14 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||
|
||||
}
|
||||
DEBUGLOG("down_callback2. node %s, state = %d\n", ninfo->name, ninfo->state);
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
|
||||
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return 0;
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Convert gulm error codes to unix errno numbers */
|
||||
@@ -948,7 +950,7 @@ static int get_all_cluster_nodes()
|
||||
}
|
||||
else {
|
||||
DEBUGLOG("Cannot resolve host name %s\n", nodename);
|
||||
log_err("Cannot resolve host name %s\n", nodename);
|
||||
log_error("Cannot resolve host name %s\n", nodename);
|
||||
}
|
||||
}
|
||||
free(nodename);
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
@@ -39,9 +43,8 @@
|
||||
#include <openais/saLck.h>
|
||||
#include <openais/cpg.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "locking.h"
|
||||
#include "log.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
@@ -50,11 +53,6 @@
|
||||
/* Timeout value for several openais calls */
|
||||
#define TIMEOUT 10
|
||||
|
||||
static void lck_lock_callback(SaInvocationT invocation,
|
||||
SaLckLockStatusT lockStatus,
|
||||
SaAisErrorT error);
|
||||
static void lck_unlock_callback(SaInvocationT invocation,
|
||||
SaAisErrorT error);
|
||||
static void cpg_deliver_callback (cpg_handle_t handle,
|
||||
struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
@@ -92,11 +90,6 @@ cpg_callbacks_t cpg_callbacks = {
|
||||
.cpg_confchg_fn = cpg_confchg_callback,
|
||||
};
|
||||
|
||||
SaLckCallbacksT lck_callbacks = {
|
||||
.saLckLockGrantCallback = lck_lock_callback,
|
||||
.saLckResourceUnlockCallback = lck_unlock_callback
|
||||
};
|
||||
|
||||
struct node_info
|
||||
{
|
||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
@@ -110,13 +103,6 @@ struct lock_info
|
||||
SaNameT lock_name;
|
||||
};
|
||||
|
||||
struct lock_wait
|
||||
{
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
int status;
|
||||
};
|
||||
|
||||
/* Set errno to something approximating the right value and return 0 or -1 */
|
||||
static int ais_to_errno(SaAisErrorT err)
|
||||
{
|
||||
@@ -209,7 +195,7 @@ static int ais_to_errno(SaAisErrorT err)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *print_csid(const char *csid)
|
||||
static char *print_openais_csid(const char *csid)
|
||||
{
|
||||
static char buf[128];
|
||||
int id;
|
||||
@@ -255,12 +241,13 @@ static void cpg_deliver_callback (cpg_handle_t handle,
|
||||
|
||||
memcpy(&target_nodeid, msg, OPENAIS_CSID_LEN);
|
||||
|
||||
DEBUGLOG("Got message from nodeid %d for %d. len %d\n",
|
||||
nodeid, target_nodeid, msg_len-4);
|
||||
DEBUGLOG("%u got message from nodeid %d for %d. len %d\n",
|
||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
||||
|
||||
if (target_nodeid == our_nodeid)
|
||||
process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
|
||||
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
|
||||
if (nodeid != our_nodeid)
|
||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
||||
process_message(cluster_client, (char *)msg+OPENAIS_CSID_LEN,
|
||||
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
|
||||
}
|
||||
|
||||
static void cpg_confchg_callback(cpg_handle_t handle,
|
||||
@@ -302,34 +289,27 @@ static void cpg_confchg_callback(cpg_handle_t handle,
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
num_nodes = joined_list_entries;
|
||||
}
|
||||
for (i=0; i<member_list_entries; i++) {
|
||||
if (member_list[i].nodeid == 0) continue;
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&member_list[i].nodeid,
|
||||
OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = member_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
OPENAIS_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
static void lck_lock_callback(SaInvocationT invocation,
|
||||
SaLckLockStatusT lockStatus,
|
||||
SaAisErrorT error)
|
||||
{
|
||||
struct lock_wait *lwait = (struct lock_wait *)(long)invocation;
|
||||
|
||||
DEBUGLOG("lck_lock_callback, error = %d\n", error);
|
||||
|
||||
lwait->status = error;
|
||||
pthread_mutex_lock(&lwait->mutex);
|
||||
pthread_cond_signal(&lwait->cond);
|
||||
pthread_mutex_unlock(&lwait->mutex);
|
||||
}
|
||||
|
||||
static void lck_unlock_callback(SaInvocationT invocation,
|
||||
SaAisErrorT error)
|
||||
{
|
||||
struct lock_wait *lwait = (struct lock_wait *)(long)invocation;
|
||||
|
||||
DEBUGLOG("lck_unlock_callback\n");
|
||||
|
||||
lwait->status = SA_AIS_OK;
|
||||
pthread_mutex_lock(&lwait->mutex);
|
||||
pthread_cond_signal(&lwait->cond);
|
||||
pthread_mutex_unlock(&lwait->mutex);
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
static int lck_dispatch(struct local_client *client, char *buf, int len,
|
||||
@@ -359,7 +339,7 @@ static int _init_cluster(void)
|
||||
}
|
||||
|
||||
err = saLckInitialize(&lck_handle,
|
||||
&lck_callbacks,
|
||||
NULL,
|
||||
&ver);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_initialize(&cpg_handle, &cpg_callbacks);
|
||||
@@ -402,7 +382,7 @@ static int _init_cluster(void)
|
||||
static void _cluster_closedown(void)
|
||||
{
|
||||
DEBUGLOG("cluster_closedown\n");
|
||||
unlock_all();
|
||||
destroy_lvhash();
|
||||
|
||||
saLckFinalize(lck_handle);
|
||||
cpg_finalize(cpg_handle);
|
||||
@@ -435,7 +415,7 @@ static int _name_from_csid(const char *csid, char *name)
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
||||
if (!ninfo)
|
||||
{
|
||||
sprintf(name, "UNKNOWN %s", print_csid(csid));
|
||||
sprintf(name, "UNKNOWN %s", print_openais_csid(csid));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -457,7 +437,7 @@ static void _add_up_node(const char *csid)
|
||||
ninfo = dm_hash_lookup_binary(node_hash, csid, OPENAIS_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
DEBUGLOG("openais_add_up_node no node_hash entry for csid %s\n",
|
||||
print_csid(csid));
|
||||
print_openais_csid(csid));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -475,6 +455,7 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
{
|
||||
struct dm_hash_node *hn;
|
||||
struct node_info *ninfo;
|
||||
int somedown = 0;
|
||||
|
||||
dm_hash_iterate(hn, node_hash)
|
||||
{
|
||||
@@ -488,22 +469,20 @@ static int _cluster_do_node_callback(struct local_client *master_client,
|
||||
|
||||
if (ninfo->state != NODE_DOWN)
|
||||
callback(master_client, csid, ninfo->state == NODE_CLVMD);
|
||||
if (ninfo->state != NODE_CLVMD)
|
||||
somedown = -1;
|
||||
}
|
||||
return 0;
|
||||
return somedown;
|
||||
}
|
||||
|
||||
/* Real locking */
|
||||
static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
{
|
||||
struct lock_wait lwait;
|
||||
struct lock_info *linfo;
|
||||
SaLckResourceHandleT res_handle;
|
||||
SaAisErrorT err;
|
||||
SaLckLockIdT lock_id;
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
SaLckLockStatusT lockStatus;
|
||||
|
||||
/* This needs to be converted from DLM/LVM2 value for OpenAIS LCK */
|
||||
if (flags & LCK_NONBLOCK) flags = SA_LCK_LOCK_NO_QUEUE;
|
||||
@@ -526,24 +505,24 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
err = saLckResourceLockAsync(res_handle,
|
||||
(SaInvocationT)(long)&lwait,
|
||||
&lock_id,
|
||||
mode,
|
||||
flags,
|
||||
0);
|
||||
if (err != SA_AIS_OK)
|
||||
err = saLckResourceLock(
|
||||
res_handle,
|
||||
&lock_id,
|
||||
mode,
|
||||
flags,
|
||||
0,
|
||||
SA_TIME_END,
|
||||
&lockStatus);
|
||||
if (err != SA_AIS_OK && lockStatus != SA_LCK_LOCK_GRANTED)
|
||||
{
|
||||
free(linfo);
|
||||
saLckResourceClose(res_handle);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", lwait.status,
|
||||
DEBUGLOG("lock_resource returning %d, lock_id=%llx\n", err,
|
||||
lock_id);
|
||||
|
||||
linfo->lock_id = lock_id;
|
||||
@@ -551,43 +530,34 @@ static int _lock_resource(char *resource, int mode, int flags, int *lockid)
|
||||
|
||||
dm_hash_insert(lock_hash, resource, linfo);
|
||||
|
||||
return ais_to_errno(lwait.status);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
|
||||
static int _unlock_resource(char *resource, int lockid)
|
||||
{
|
||||
struct lock_wait lwait;
|
||||
SaAisErrorT err;
|
||||
struct lock_info *linfo;
|
||||
|
||||
pthread_cond_init(&lwait.cond, NULL);
|
||||
pthread_mutex_init(&lwait.mutex, NULL);
|
||||
pthread_mutex_lock(&lwait.mutex);
|
||||
|
||||
DEBUGLOG("unlock_resource %s\n", resource);
|
||||
linfo = dm_hash_lookup(lock_hash, resource);
|
||||
if (!linfo)
|
||||
return 0;
|
||||
|
||||
DEBUGLOG("unlock_resource: lockid: %llx\n", linfo->lock_id);
|
||||
err = saLckResourceUnlockAsync((SaInvocationT)(long)&lwait, linfo->lock_id);
|
||||
err = saLckResourceUnlock(linfo->lock_id, SA_TIME_END);
|
||||
if (err != SA_AIS_OK)
|
||||
{
|
||||
DEBUGLOG("Unlock returned %d\n", err);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
/* Wait for it to complete */
|
||||
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||
pthread_mutex_unlock(&lwait.mutex);
|
||||
|
||||
/* Release the resource */
|
||||
dm_hash_remove(lock_hash, resource);
|
||||
saLckResourceClose(linfo->res_handle);
|
||||
free(linfo);
|
||||
|
||||
return ais_to_errno(lwait.status);
|
||||
return ais_to_errno(err);
|
||||
}
|
||||
|
||||
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -17,6 +17,12 @@
|
||||
* CLVMD: Cluster LVM daemon
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <libdevmapper.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -37,16 +43,16 @@
|
||||
#include <getopt.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <libdlm.h>
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
#include "clvm.h"
|
||||
#include "version.h"
|
||||
#include "lvm-version.h"
|
||||
#include "clvmd.h"
|
||||
#include "refresh_clvmd.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "lvm-logging.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
@@ -74,7 +80,7 @@ static unsigned max_cluster_member_name_len;
|
||||
|
||||
/* Structure of items on the LVM thread list */
|
||||
struct lvm_thread_cmd {
|
||||
struct list list;
|
||||
struct dm_list list;
|
||||
|
||||
struct local_client *client;
|
||||
struct clvm_header *msg;
|
||||
@@ -89,7 +95,7 @@ static pthread_t lvm_thread;
|
||||
static pthread_mutex_t lvm_thread_mutex;
|
||||
static pthread_cond_t lvm_thread_cond;
|
||||
static pthread_mutex_t lvm_start_mutex;
|
||||
static struct list lvm_cmd_head;
|
||||
static struct dm_list lvm_cmd_head;
|
||||
static volatile sig_atomic_t quit = 0;
|
||||
static volatile sig_atomic_t reread_config = 0;
|
||||
static int child_pipe[2];
|
||||
@@ -102,6 +108,8 @@ static int child_pipe[2];
|
||||
#define DFAIL_TIMEOUT 5
|
||||
#define SUCCESS 0
|
||||
|
||||
typedef enum {IF_AUTO, IF_CMAN, IF_GULM, IF_OPENAIS, IF_COROSYNC} if_type_t;
|
||||
|
||||
/* Prototypes for code further down */
|
||||
static void sigusr2_handler(int sig);
|
||||
static void sighup_handler(int sig);
|
||||
@@ -138,6 +146,7 @@ static void hton_clvm(struct clvm_header *hdr);
|
||||
static void ntoh_clvm(struct clvm_header *hdr);
|
||||
static void add_reply_to_list(struct local_client *client, int status,
|
||||
const char *csid, const char *buf, int len);
|
||||
static if_type_t parse_cluster_interface(char *ifname);
|
||||
|
||||
static void usage(char *prog, FILE *file)
|
||||
{
|
||||
@@ -146,10 +155,26 @@ static void usage(char *prog, FILE *file)
|
||||
fprintf(file, "\n");
|
||||
fprintf(file, " -V Show version of clvmd\n");
|
||||
fprintf(file, " -h Show this help information\n");
|
||||
fprintf(file, " -d Don't fork, run in the foreground\n");
|
||||
fprintf(file, " -d Set debug level\n");
|
||||
fprintf(file, " If starting clvmd then don't fork, run in the foreground\n");
|
||||
fprintf(file, " -R Tell all running clvmds in the cluster to reload their device cache\n");
|
||||
fprintf(file, " -C Sets debug level (from -d) on all clvmd instances clusterwide\n");
|
||||
fprintf(file, " -t<secs> Command timeout (default 60 seconds)\n");
|
||||
fprintf(file, " -T<secs> Startup timeout (default none)\n");
|
||||
fprintf(file, " -I<cmgr> Cluster manager (default: auto)\n");
|
||||
fprintf(file, " Available cluster managers: ");
|
||||
#ifdef USE_COROSYNC
|
||||
fprintf(file, "corosync ");
|
||||
#endif
|
||||
#ifdef USE_CMAN
|
||||
fprintf(file, "cman ");
|
||||
#endif
|
||||
#ifdef USE_OPENAIS
|
||||
fprintf(file, "openais ");
|
||||
#endif
|
||||
#ifdef USE_GULM
|
||||
fprintf(file, "gulm ");
|
||||
#endif
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
@@ -179,8 +204,10 @@ void debuglog(const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
if (debug == DEBUG_SYSLOG) {
|
||||
if (!syslog_init)
|
||||
if (!syslog_init) {
|
||||
openlog("clvmd", LOG_PID, LOG_DAEMON);
|
||||
syslog_init = 1;
|
||||
}
|
||||
|
||||
va_start(ap,fmt);
|
||||
vsyslog(LOG_DEBUG, fmt, ap);
|
||||
@@ -188,6 +215,61 @@ void debuglog(const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *decode_cmd(unsigned char cmdl)
|
||||
{
|
||||
static char buf[128];
|
||||
const char *command;
|
||||
|
||||
switch (cmdl) {
|
||||
case CLVMD_CMD_TEST:
|
||||
command = "TEST";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
command = "LOCK_VG";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
command = "LOCK_LV";
|
||||
break;
|
||||
case CLVMD_CMD_REFRESH:
|
||||
command = "REFRESH";
|
||||
break;
|
||||
case CLVMD_CMD_SET_DEBUG:
|
||||
command = "SET_DEBUG";
|
||||
break;
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
command = "GET_CLUSTERNAME";
|
||||
break;
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
command = "VG_BACKUP";
|
||||
break;
|
||||
case CLVMD_CMD_REPLY:
|
||||
command = "REPLY";
|
||||
break;
|
||||
case CLVMD_CMD_VERSION:
|
||||
command = "VERSION";
|
||||
break;
|
||||
case CLVMD_CMD_GOAWAY:
|
||||
command = "GOAWAY";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK:
|
||||
command = "LOCK";
|
||||
break;
|
||||
case CLVMD_CMD_UNLOCK:
|
||||
command = "UNLOCK";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK_QUERY:
|
||||
command = "LOCK_QUERY";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s (0x%x)", command, cmdl);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int local_sock;
|
||||
@@ -196,6 +278,7 @@ int main(int argc, char *argv[])
|
||||
signed char opt;
|
||||
int cmd_timeout = DEFAULT_CMD_TIMEOUT;
|
||||
int start_timeout = 0;
|
||||
if_type_t cluster_iface = IF_AUTO;
|
||||
sigset_t ss;
|
||||
int using_gulm = 0;
|
||||
int debug_opt = 0;
|
||||
@@ -204,7 +287,7 @@ int main(int argc, char *argv[])
|
||||
/* Deal with command-line arguments */
|
||||
opterr = 0;
|
||||
optind = 0;
|
||||
while ((opt = getopt(argc, argv, "?vVhd::t:RT:C")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "?vVhd::t:RT:CI:")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
usage(argv[0], stdout);
|
||||
@@ -237,6 +320,9 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
cluster_iface = parse_cluster_interface(optarg);
|
||||
break;
|
||||
case 'T':
|
||||
start_timeout = atoi(optarg);
|
||||
if (start_timeout <= 0) {
|
||||
@@ -289,13 +375,15 @@ int main(int argc, char *argv[])
|
||||
signal(SIGHUP, sighup_handler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/* Block SIGUSR2 in the main process */
|
||||
/* Block SIGUSR2/SIGINT/SIGTERM in process */
|
||||
sigemptyset(&ss);
|
||||
sigaddset(&ss, SIGUSR2);
|
||||
sigaddset(&ss, SIGINT);
|
||||
sigaddset(&ss, SIGTERM);
|
||||
sigprocmask(SIG_BLOCK, &ss, NULL);
|
||||
|
||||
/* Initialise the LVM thread variables */
|
||||
list_init(&lvm_cmd_head);
|
||||
dm_list_init(&lvm_cmd_head);
|
||||
pthread_mutex_init(&lvm_thread_mutex, NULL);
|
||||
pthread_cond_init(&lvm_thread_cond, NULL);
|
||||
pthread_mutex_init(&lvm_start_mutex, NULL);
|
||||
@@ -303,7 +391,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Start the cluster interface */
|
||||
#ifdef USE_CMAN
|
||||
if ((clops = init_cman_cluster())) {
|
||||
if ((cluster_iface == IF_AUTO || cluster_iface == IF_CMAN) && (clops = init_cman_cluster())) {
|
||||
max_csid_len = CMAN_MAX_CSID_LEN;
|
||||
max_cluster_message = CMAN_MAX_CLUSTER_MESSAGE;
|
||||
max_cluster_member_name_len = CMAN_MAX_NODENAME_LEN;
|
||||
@@ -312,7 +400,7 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
#ifdef USE_GULM
|
||||
if (!clops)
|
||||
if ((clops = init_gulm_cluster())) {
|
||||
if ((cluster_iface == IF_AUTO || cluster_iface == IF_GULM) && (clops = init_gulm_cluster())) {
|
||||
max_csid_len = GULM_MAX_CSID_LEN;
|
||||
max_cluster_message = GULM_MAX_CLUSTER_MESSAGE;
|
||||
max_cluster_member_name_len = GULM_MAX_CLUSTER_MEMBER_NAME_LEN;
|
||||
@@ -320,9 +408,18 @@ int main(int argc, char *argv[])
|
||||
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to GULM");
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_COROSYNC
|
||||
if (!clops)
|
||||
if (((cluster_iface == IF_AUTO || cluster_iface == IF_COROSYNC) && (clops = init_corosync_cluster()))) {
|
||||
max_csid_len = COROSYNC_CSID_LEN;
|
||||
max_cluster_message = COROSYNC_MAX_CLUSTER_MESSAGE;
|
||||
max_cluster_member_name_len = COROSYNC_MAX_CLUSTER_MEMBER_NAME_LEN;
|
||||
syslog(LOG_NOTICE, "Cluster LVM daemon started - connected to Corosync");
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_OPENAIS
|
||||
if (!clops)
|
||||
if ((clops = init_openais_cluster())) {
|
||||
if ((cluster_iface == IF_AUTO || cluster_iface == IF_OPENAIS) && (clops = init_openais_cluster())) {
|
||||
max_csid_len = OPENAIS_CSID_LEN;
|
||||
max_cluster_message = OPENAIS_MAX_CLUSTER_MESSAGE;
|
||||
max_cluster_member_name_len = OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN;
|
||||
@@ -361,6 +458,9 @@ int main(int argc, char *argv[])
|
||||
/* This needs to be started after cluster initialisation
|
||||
as it may need to take out locks */
|
||||
DEBUGLOG("starting LVM thread\n");
|
||||
|
||||
/* Don't let anyone else to do work until we are started */
|
||||
pthread_mutex_lock(&lvm_start_mutex);
|
||||
pthread_create(&lvm_thread, NULL, lvm_thread_fn,
|
||||
(void *)(long)using_gulm);
|
||||
|
||||
@@ -381,6 +481,8 @@ int main(int argc, char *argv[])
|
||||
/* Do some work */
|
||||
main_loop(local_sock, cmd_timeout);
|
||||
|
||||
destroy_lvm();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -527,7 +629,7 @@ static void timedout_callback(struct local_client *client, const char *csid,
|
||||
char nodename[max_cluster_member_name_len];
|
||||
|
||||
clops->name_from_csid(csid, nodename);
|
||||
DEBUGLOG("PJC: checking for a reply from %s\n", nodename);
|
||||
DEBUGLOG("Checking for a reply from %s\n", nodename);
|
||||
pthread_mutex_lock(&client->bits.localsock.reply_mutex);
|
||||
|
||||
reply = client->bits.localsock.replies;
|
||||
@@ -538,7 +640,7 @@ static void timedout_callback(struct local_client *client, const char *csid,
|
||||
pthread_mutex_unlock(&client->bits.localsock.reply_mutex);
|
||||
|
||||
if (!reply) {
|
||||
DEBUGLOG("PJC: node %s timed-out\n", nodename);
|
||||
DEBUGLOG("Node %s timed-out\n", nodename);
|
||||
add_reply_to_list(client, ETIMEDOUT, csid,
|
||||
"Command timed out", 18);
|
||||
}
|
||||
@@ -574,6 +676,11 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
{
|
||||
DEBUGLOG("Using timeout of %d seconds\n", cmd_timeout);
|
||||
|
||||
sigset_t ss;
|
||||
sigemptyset(&ss);
|
||||
sigaddset(&ss, SIGINT);
|
||||
sigaddset(&ss, SIGTERM);
|
||||
pthread_sigmask(SIG_UNBLOCK, &ss, NULL);
|
||||
/* Main loop */
|
||||
while (!quit) {
|
||||
fd_set in;
|
||||
@@ -630,7 +737,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
||||
}
|
||||
|
||||
if (FD_ISSET(thisfd->fd, &in)) {
|
||||
struct local_client *newfd;
|
||||
struct local_client *newfd = NULL;
|
||||
int ret;
|
||||
|
||||
/* Do callback */
|
||||
@@ -901,8 +1008,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
}
|
||||
|
||||
/* Free the command buffer */
|
||||
if (thisfd->bits.localsock.cmd)
|
||||
free(thisfd->bits.localsock.cmd);
|
||||
free(thisfd->bits.localsock.cmd);
|
||||
|
||||
/* Clear out the cross-link */
|
||||
if (thisfd->bits.localsock.pipe_client != NULL)
|
||||
@@ -937,8 +1043,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
}
|
||||
|
||||
/* Free any old buffer space */
|
||||
if (thisfd->bits.localsock.cmd)
|
||||
free(thisfd->bits.localsock.cmd);
|
||||
free(thisfd->bits.localsock.cmd);
|
||||
|
||||
/* See if we have the whole message */
|
||||
argslen =
|
||||
@@ -984,6 +1089,14 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise and lock the mutex so the subthread will wait after
|
||||
finishing the PRE routine */
|
||||
if (!thisfd->bits.localsock.threadid) {
|
||||
pthread_mutex_init(&thisfd->bits.localsock.mutex, NULL);
|
||||
pthread_cond_init(&thisfd->bits.localsock.cond, NULL);
|
||||
pthread_mutex_init(&thisfd->bits.localsock.reply_mutex, NULL);
|
||||
}
|
||||
|
||||
/* Only run the command if all the cluster nodes are running CLVMD */
|
||||
if (((inheader->flags & CLVMD_FLAG_LOCAL) == 0) &&
|
||||
(check_all_clvmds_running(thisfd) == -1)) {
|
||||
@@ -1055,12 +1168,6 @@ static int read_from_local_sock(struct local_client *thisfd)
|
||||
|
||||
thisfd->bits.localsock.pipe = comms_pipe[1];
|
||||
|
||||
/* Initialise and lock the mutex so the subthread will wait after
|
||||
finishing the PRE routine */
|
||||
pthread_mutex_init(&thisfd->bits.localsock.mutex, NULL);
|
||||
pthread_cond_init(&thisfd->bits.localsock.cond, NULL);
|
||||
pthread_mutex_init(&thisfd->bits.localsock.reply_mutex, NULL);
|
||||
|
||||
/* Make sure the thread has a copy of it's own ID */
|
||||
newfd->bits.pipe.threadid = thisfd->bits.localsock.threadid;
|
||||
|
||||
@@ -1166,8 +1273,8 @@ static void process_remote_command(struct clvm_header *msg, int msglen, int fd,
|
||||
/* Get the node name as we /may/ need it later */
|
||||
clops->name_from_csid(csid, nodename);
|
||||
|
||||
DEBUGLOG("process_remote_command %d for clientid 0x%x XID %d on node %s\n",
|
||||
msg->cmd, msg->clientid, msg->xid, nodename);
|
||||
DEBUGLOG("process_remote_command %s for clientid 0x%x XID %d on node %s\n",
|
||||
decode_cmd(msg->cmd), msg->clientid, msg->xid, nodename);
|
||||
|
||||
/* Check for GOAWAY and sulk */
|
||||
if (msg->cmd == CLVMD_CMD_GOAWAY) {
|
||||
@@ -1415,7 +1522,8 @@ next_pre:
|
||||
DEBUGLOG("Waiting for next pre command\n");
|
||||
|
||||
pthread_mutex_lock(&client->bits.localsock.mutex);
|
||||
if (client->bits.localsock.state != PRE_COMMAND) {
|
||||
if (client->bits.localsock.state != PRE_COMMAND &&
|
||||
!client->bits.localsock.finished) {
|
||||
pthread_cond_wait(&client->bits.localsock.cond,
|
||||
&client->bits.localsock.mutex);
|
||||
}
|
||||
@@ -1437,8 +1545,9 @@ static int process_local_command(struct clvm_header *msg, int msglen,
|
||||
int replylen = 0;
|
||||
int status;
|
||||
|
||||
DEBUGLOG("process_local_command: msg=%p, msglen =%d, client=%p\n", msg,
|
||||
msglen, client);
|
||||
DEBUGLOG("process_local_command: %s msg=%p, msglen =%d, client=%p\n",
|
||||
decode_cmd(msg->cmd), msg, msglen, client);
|
||||
|
||||
if (replybuf == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -1545,8 +1654,7 @@ static void send_local_reply(struct local_client *client, int status, int fd)
|
||||
}
|
||||
thisreply = thisreply->next;
|
||||
|
||||
if (tempreply->replymsg)
|
||||
free(tempreply->replymsg);
|
||||
free(tempreply->replymsg);
|
||||
free(tempreply);
|
||||
}
|
||||
|
||||
@@ -1577,8 +1685,7 @@ static void free_reply(struct local_client *client)
|
||||
|
||||
thisreply = thisreply->next;
|
||||
|
||||
if (tempreply->replymsg)
|
||||
free(tempreply->replymsg);
|
||||
free(tempreply->replymsg);
|
||||
free(tempreply);
|
||||
}
|
||||
client->bits.localsock.replies = NULL;
|
||||
@@ -1613,7 +1720,7 @@ static void send_version_message()
|
||||
static int send_message(void *buf, int msglen, const char *csid, int fd,
|
||||
const char *errtext)
|
||||
{
|
||||
int len;
|
||||
int len = 0;
|
||||
int saved_errno = 0;
|
||||
struct timespec delay;
|
||||
struct timespec remtime;
|
||||
@@ -1692,13 +1799,10 @@ static int process_work_item(struct lvm_thread_cmd *cmd)
|
||||
*/
|
||||
static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
|
||||
{
|
||||
struct list *cmdl, *tmp;
|
||||
struct dm_list *cmdl, *tmp;
|
||||
sigset_t ss;
|
||||
int using_gulm = (int)(long)arg;
|
||||
|
||||
/* Don't let anyone else to do work until we are started */
|
||||
pthread_mutex_lock(&lvm_start_mutex);
|
||||
|
||||
DEBUGLOG("LVM thread function started\n");
|
||||
|
||||
/* Ignore SIGUSR1 & 2 */
|
||||
@@ -1718,20 +1822,19 @@ static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
|
||||
DEBUGLOG("LVM thread waiting for work\n");
|
||||
|
||||
pthread_mutex_lock(&lvm_thread_mutex);
|
||||
if (list_empty(&lvm_cmd_head))
|
||||
if (dm_list_empty(&lvm_cmd_head))
|
||||
pthread_cond_wait(&lvm_thread_cond, &lvm_thread_mutex);
|
||||
|
||||
list_iterate_safe(cmdl, tmp, &lvm_cmd_head) {
|
||||
dm_list_iterate_safe(cmdl, tmp, &lvm_cmd_head) {
|
||||
struct lvm_thread_cmd *cmd;
|
||||
|
||||
cmd =
|
||||
list_struct_base(cmdl, struct lvm_thread_cmd, list);
|
||||
list_del(&cmd->list);
|
||||
dm_list_struct_base(cmdl, struct lvm_thread_cmd, list);
|
||||
dm_list_del(&cmd->list);
|
||||
pthread_mutex_unlock(&lvm_thread_mutex);
|
||||
|
||||
process_work_item(cmd);
|
||||
if (cmd->msg)
|
||||
free(cmd->msg);
|
||||
free(cmd->msg);
|
||||
free(cmd);
|
||||
|
||||
pthread_mutex_lock(&lvm_thread_mutex);
|
||||
@@ -1777,7 +1880,7 @@ static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
|
||||
("add_to_lvmqueue: cmd=%p. client=%p, msg=%p, len=%d, csid=%p, xid=%d\n",
|
||||
cmd, client, msg, msglen, csid, cmd->xid);
|
||||
pthread_mutex_lock(&lvm_thread_mutex);
|
||||
list_add(&lvm_cmd_head, &cmd->list);
|
||||
dm_list_add(&lvm_cmd_head, &cmd->list);
|
||||
pthread_cond_signal(&lvm_thread_cond);
|
||||
pthread_mutex_unlock(&lvm_thread_mutex);
|
||||
|
||||
@@ -1824,8 +1927,9 @@ static int open_local_sock()
|
||||
log_error("Can't create local socket: %m");
|
||||
return -1;
|
||||
}
|
||||
/* Set Close-on-exec */
|
||||
/* Set Close-on-exec & non-blocking */
|
||||
fcntl(local_socket, F_SETFD, 1);
|
||||
fcntl(local_socket, F_SETFL, fcntl(local_socket, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
|
||||
@@ -1937,3 +2041,20 @@ int sync_unlock(const char *resource, int lockid)
|
||||
return clops->sync_unlock(resource, lockid);
|
||||
}
|
||||
|
||||
static if_type_t parse_cluster_interface(char *ifname)
|
||||
{
|
||||
if_type_t iface = IF_AUTO;
|
||||
|
||||
if (!strcmp(ifname, "auto"))
|
||||
iface = IF_AUTO;
|
||||
if (!strcmp(ifname, "cman"))
|
||||
iface = IF_CMAN;
|
||||
if (!strcmp(ifname, "gulm"))
|
||||
iface = IF_GULM;
|
||||
if (!strcmp(ifname, "openais"))
|
||||
iface = IF_OPENAIS;
|
||||
if (!strcmp(ifname, "corosync"))
|
||||
iface = IF_COROSYNC;
|
||||
|
||||
return iface;
|
||||
}
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
||||
** Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
**
|
||||
** This copyrighted material is made available to anyone wishing to use,
|
||||
** modify, copy, or redistribute it subject to the terms and conditions
|
||||
** of the GNU General Public License v.2.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/* CMAN socket interface header,
|
||||
may be include by user or kernel code */
|
||||
|
||||
#ifndef __CNXMAN_SOCKET_H
|
||||
#define __CNXMAN_SOCKET_H
|
||||
|
||||
/* A currently unused number. TIPC also uses this number and you're unlikely
|
||||
to be using both.
|
||||
*/
|
||||
#define AF_CLUSTER 30
|
||||
#define PF_CLUSTER AF_CLUSTER
|
||||
|
||||
/* Protocol(socket) types */
|
||||
#define CLPROTO_MASTER 2
|
||||
#define CLPROTO_CLIENT 3
|
||||
|
||||
/* ioctls -- should register these properly */
|
||||
#define SIOCCLUSTER_NOTIFY _IOW('x', 0x01, int)
|
||||
#define SIOCCLUSTER_REMOVENOTIFY _IO( 'x', 0x02)
|
||||
#define SIOCCLUSTER_GETMEMBERS _IOR('x', 0x03, struct cl_cluster_nodelist)
|
||||
#define SIOCCLUSTER_SETEXPECTED_VOTES _IOW('x', 0x04, int)
|
||||
#define SIOCCLUSTER_ISQUORATE _IO( 'x', 0x05)
|
||||
#define SIOCCLUSTER_ISLISTENING _IOW('x', 0x06, struct cl_listen_request)
|
||||
#define SIOCCLUSTER_GETALLMEMBERS _IOR('x', 0x07, struct cl_cluster_nodelist)
|
||||
#define SIOCCLUSTER_SET_VOTES _IOW('x', 0x08, int)
|
||||
#define SIOCCLUSTER_GET_VERSION _IOR('x', 0x09, struct cl_version)
|
||||
#define SIOCCLUSTER_SET_VERSION _IOW('x', 0x0a, struct cl_version)
|
||||
#define SIOCCLUSTER_ISACTIVE _IO( 'x', 0x0b)
|
||||
#define SIOCCLUSTER_KILLNODE _IOW('x', 0x0c, int)
|
||||
#define SIOCCLUSTER_GET_JOINCOUNT _IO( 'x', 0x0d)
|
||||
#define SIOCCLUSTER_SERVICE_REGISTER _IOW('x', 0x0e, char)
|
||||
#define SIOCCLUSTER_SERVICE_UNREGISTER _IO('x', 0x0f)
|
||||
#define SIOCCLUSTER_SERVICE_JOIN _IO( 'x', 0x10)
|
||||
#define SIOCCLUSTER_SERVICE_LEAVE _IO( 'x', 0x20)
|
||||
#define SIOCCLUSTER_SERVICE_SETSIGNAL _IOW('x', 0x30, int)
|
||||
#define SIOCCLUSTER_SERVICE_STARTDONE _IOW('x', 0x40, unsigned int)
|
||||
#define SIOCCLUSTER_SERVICE_GETEVENT _IOR('x', 0x50, struct cl_service_event)
|
||||
#define SIOCCLUSTER_SERVICE_GETMEMBERS _IOR('x', 0x60, struct cl_cluster_nodelist)
|
||||
#define SIOCCLUSTER_SERVICE_GLOBALID _IOR('x', 0x70, uint32_t)
|
||||
#define SIOCCLUSTER_SERVICE_SETLEVEL _IOR('x', 0x80, int)
|
||||
#define SIOCCLUSTER_GETNODE _IOWR('x', 0x90, struct cl_cluster_node)
|
||||
#define SIOCCLUSTER_BARRIER _IOW('x', 0x0a0, struct cl_barrier_info)
|
||||
|
||||
/* These were setsockopts */
|
||||
#define SIOCCLUSTER_PASS_SOCKET _IOW('x', 0x0b0, struct cl_passed_sock)
|
||||
#define SIOCCLUSTER_SET_NODENAME _IOW('x', 0x0b1, char *)
|
||||
#define SIOCCLUSTER_SET_NODEID _IOW('x', 0x0b2, int)
|
||||
#define SIOCCLUSTER_JOIN_CLUSTER _IOW('x', 0x0b3, struct cl_join_cluster_info)
|
||||
#define SIOCCLUSTER_LEAVE_CLUSTER _IOW('x', 0x0b4, int)
|
||||
|
||||
|
||||
/* Maximum size of a cluster message */
|
||||
#define CMAN_MAX_CLUSTER_MESSAGE 1500
|
||||
#define CMAN_MAX_CLUSTER_MEMBER_NAME_LEN 255
|
||||
#define MAX_BARRIER_NAME_LEN 33
|
||||
#define MAX_SA_ADDR_LEN 12
|
||||
#define MAX_CLUSTER_NAME_LEN 16
|
||||
|
||||
/* Well-known cluster port numbers */
|
||||
#define CLUSTER_PORT_MEMBERSHIP 1 /* Mustn't block during cluster
|
||||
* transitions! */
|
||||
#define CLUSTER_PORT_SERVICES 2
|
||||
#define CLUSTER_PORT_SYSMAN 10 /* Remote execution daemon */
|
||||
#define CLUSTER_PORT_CLVMD 11 /* Cluster LVM daemon */
|
||||
#define CLUSTER_PORT_SLM 12 /* LVM SLM (simple lock manager) */
|
||||
|
||||
/* Port numbers above this will be blocked when the cluster is inquorate or in
|
||||
* transition */
|
||||
#define HIGH_PROTECTED_PORT 9
|
||||
|
||||
/* Reasons for leaving the cluster */
|
||||
#define CLUSTER_LEAVEFLAG_DOWN 0 /* Normal shutdown */
|
||||
#define CLUSTER_LEAVEFLAG_KILLED 1
|
||||
#define CLUSTER_LEAVEFLAG_PANIC 2
|
||||
#define CLUSTER_LEAVEFLAG_REMOVED 3 /* This one can reduce quorum */
|
||||
#define CLUSTER_LEAVEFLAG_REJECTED 4 /* Not allowed into the cluster in the
|
||||
* first place */
|
||||
#define CLUSTER_LEAVEFLAG_INCONSISTENT 5 /* Our view of the cluster is
|
||||
* in a minority */
|
||||
#define CLUSTER_LEAVEFLAG_DEAD 6 /* Discovered to be dead */
|
||||
#define CLUSTER_LEAVEFLAG_FORCE 0x10 /* Forced by command-line */
|
||||
|
||||
/* OOB messages sent to a local socket */
|
||||
#define CLUSTER_OOB_MSG_PORTCLOSED 1
|
||||
#define CLUSTER_OOB_MSG_STATECHANGE 2
|
||||
#define CLUSTER_OOB_MSG_SERVICEEVENT 3
|
||||
|
||||
/* Sendmsg flags, these are above the normal sendmsg flags so they don't
|
||||
* interfere */
|
||||
#define MSG_NOACK 0x010000 /* Don't need an ACK for this message */
|
||||
#define MSG_QUEUE 0x020000 /* Queue the message for sending later */
|
||||
#define MSG_MULTICAST 0x080000 /* Message was sent to all nodes in the cluster
|
||||
*/
|
||||
#define MSG_ALLINT 0x100000 /* Send out of all interfaces */
|
||||
#define MSG_REPLYEXP 0x200000 /* Reply is expected */
|
||||
|
||||
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
|
||||
NODESTATE_DEAD } nodestate_t;
|
||||
|
||||
|
||||
struct sockaddr_cl {
|
||||
unsigned short scl_family;
|
||||
unsigned char scl_flags;
|
||||
unsigned char scl_port;
|
||||
int scl_nodeid;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is how we pass the multicast & receive sockets into kernel space.
|
||||
*/
|
||||
struct cl_passed_sock {
|
||||
int fd; /* FD of master socket to do multicast on */
|
||||
int number; /* Socket number, to match up recvonly & bcast
|
||||
* sockets */
|
||||
int multicast; /* Is it multicast or receive ? */
|
||||
};
|
||||
|
||||
/* Cluster configuration info passed when we join the cluster */
|
||||
struct cl_join_cluster_info {
|
||||
unsigned char votes;
|
||||
unsigned int expected_votes;
|
||||
unsigned int two_node;
|
||||
unsigned int config_version;
|
||||
|
||||
char cluster_name[17];
|
||||
};
|
||||
|
||||
|
||||
/* This is the structure, per node, returned from the membership ioctl */
|
||||
struct cl_cluster_node {
|
||||
unsigned int size;
|
||||
unsigned int node_id;
|
||||
unsigned int us;
|
||||
unsigned int leave_reason;
|
||||
unsigned int incarnation;
|
||||
nodestate_t state;
|
||||
char name[CMAN_MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||
unsigned char votes;
|
||||
};
|
||||
|
||||
/* The struct passed to the membership ioctls */
|
||||
struct cl_cluster_nodelist {
|
||||
uint32_t max_members;
|
||||
struct cl_cluster_node *nodes;
|
||||
};
|
||||
|
||||
/* Structure passed to SIOCCLUSTER_ISLISTENING */
|
||||
struct cl_listen_request {
|
||||
unsigned char port;
|
||||
int nodeid;
|
||||
};
|
||||
|
||||
/* A Cluster PORTCLOSED message - received by a local user as an OOB message */
|
||||
struct cl_portclosed_oob {
|
||||
unsigned char cmd; /* CLUSTER_OOB_MSG_PORTCLOSED */
|
||||
unsigned char port;
|
||||
};
|
||||
|
||||
/* Get all version numbers or set the config version */
|
||||
struct cl_version {
|
||||
unsigned int major;
|
||||
unsigned int minor;
|
||||
unsigned int patch;
|
||||
unsigned int config;
|
||||
};
|
||||
|
||||
/* structure passed to barrier ioctls */
|
||||
struct cl_barrier_info {
|
||||
char cmd;
|
||||
char name[MAX_BARRIER_NAME_LEN];
|
||||
unsigned int flags;
|
||||
unsigned long arg;
|
||||
};
|
||||
|
||||
typedef enum { SERVICE_EVENT_STOP, SERVICE_EVENT_START, SERVICE_EVENT_FINISH,
|
||||
SERVICE_EVENT_LEAVEDONE } service_event_t;
|
||||
|
||||
typedef enum { SERVICE_START_FAILED, SERVICE_START_JOIN, SERVICE_START_LEAVE }
|
||||
service_start_t;
|
||||
|
||||
struct cl_service_event {
|
||||
service_event_t type;
|
||||
service_start_t start_type;
|
||||
unsigned int event_id;
|
||||
unsigned int last_stop;
|
||||
unsigned int last_start;
|
||||
unsigned int last_finish;
|
||||
unsigned int node_count;
|
||||
};
|
||||
|
||||
|
||||
/* Commands to the barrier ioctl */
|
||||
#define BARRIER_IOCTL_REGISTER 1
|
||||
#define BARRIER_IOCTL_CHANGE 2
|
||||
#define BARRIER_IOCTL_DELETE 3
|
||||
#define BARRIER_IOCTL_WAIT 4
|
||||
|
||||
/* Attributes of a barrier - bitmask */
|
||||
#define BARRIER_ATTR_AUTODELETE 1
|
||||
#define BARRIER_ATTR_MULTISTEP 2
|
||||
#define BARRIER_ATTR_MANUAL 4
|
||||
#define BARRIER_ATTR_ENABLED 8
|
||||
#define BARRIER_ATTR_CALLBACK 16
|
||||
|
||||
/* Attribute setting commands */
|
||||
#define BARRIER_SETATTR_AUTODELETE 1
|
||||
#define BARRIER_SETATTR_MULTISTEP 2
|
||||
#define BARRIER_SETATTR_ENABLED 3
|
||||
#define BARRIER_SETATTR_NODES 4
|
||||
#define BARRIER_SETATTR_CALLBACK 5
|
||||
#define BARRIER_SETATTR_TIMEOUT 6
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -13,6 +13,10 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
@@ -33,7 +37,6 @@
|
||||
#include <libdevmapper.h>
|
||||
#include <libdlm.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "lvm-types.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
@@ -43,7 +46,8 @@
|
||||
/* LVM2 headers */
|
||||
#include "toolcontext.h"
|
||||
#include "lvmcache.h"
|
||||
#include "log.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "lvm-globals.h"
|
||||
#include "activate.h"
|
||||
#include "locking.h"
|
||||
#include "archiver.h"
|
||||
@@ -61,37 +65,170 @@ struct lv_info {
|
||||
int lock_mode;
|
||||
};
|
||||
|
||||
static const char *decode_locking_cmd(unsigned char cmdl)
|
||||
{
|
||||
static char buf[128];
|
||||
const char *type;
|
||||
const char *scope;
|
||||
const char *command;
|
||||
|
||||
switch (cmdl & LCK_TYPE_MASK) {
|
||||
case LCK_NULL:
|
||||
type = "NULL";
|
||||
break;
|
||||
case LCK_READ:
|
||||
type = "READ";
|
||||
break;
|
||||
case LCK_PREAD:
|
||||
type = "PREAD";
|
||||
break;
|
||||
case LCK_WRITE:
|
||||
type = "WRITE";
|
||||
break;
|
||||
case LCK_EXCL:
|
||||
type = "EXCL";
|
||||
break;
|
||||
case LCK_UNLOCK:
|
||||
type = "UNLOCK";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmdl & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
scope = "VG";
|
||||
break;
|
||||
case LCK_LV:
|
||||
scope = "LV";
|
||||
break;
|
||||
default:
|
||||
scope = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cmdl & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE & LCK_MASK:
|
||||
command = "LCK_LV_EXCLUSIVE";
|
||||
break;
|
||||
case LCK_LV_SUSPEND & LCK_MASK:
|
||||
command = "LCK_LV_SUSPEND";
|
||||
break;
|
||||
case LCK_LV_RESUME & LCK_MASK:
|
||||
command = "LCK_LV_RESUME";
|
||||
break;
|
||||
case LCK_LV_ACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_ACTIVATE";
|
||||
break;
|
||||
case LCK_LV_DEACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_DEACTIVATE";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buf, "0x%x %s (%s|%s%s%s%s%s%s)", cmdl, command, type, scope,
|
||||
cmdl & LCK_NONBLOCK ? "|NONBLOCK" : "",
|
||||
cmdl & LCK_HOLD ? "|HOLD" : "",
|
||||
cmdl & LCK_LOCAL ? "|LOCAL" : "",
|
||||
cmdl & LCK_CLUSTER_VG ? "|CLUSTER_VG" : "",
|
||||
cmdl & LCK_CACHE ? "|CACHE" : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *decode_flags(unsigned char flags)
|
||||
{
|
||||
static char buf[128];
|
||||
|
||||
sprintf(buf, "0x%x (%s%s%s)", flags,
|
||||
flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE " : "",
|
||||
flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC " : "",
|
||||
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR " : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *get_last_lvm_error()
|
||||
{
|
||||
return last_error;
|
||||
}
|
||||
|
||||
/* Return the mode a lock is currently held at (or -1 if not held) */
|
||||
static int get_current_lock(char *resource)
|
||||
/*
|
||||
* Hash lock info helpers
|
||||
*/
|
||||
static struct lv_info *lookup_info(const char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = dm_hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (lvi) {
|
||||
|
||||
return lvi;
|
||||
}
|
||||
|
||||
static void insert_info(const char *resource, struct lv_info *lvi)
|
||||
{
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
dm_hash_insert(lv_hash, resource, lvi);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
static void remove_info(const char *resource)
|
||||
{
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
dm_hash_remove(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the mode a lock is currently held at (or -1 if not held)
|
||||
*/
|
||||
static int get_current_lock(char *resource)
|
||||
{
|
||||
struct lv_info *lvi;
|
||||
|
||||
if ((lvi = lookup_info(resource)))
|
||||
return lvi->lock_mode;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void init_lvhash()
|
||||
{
|
||||
/* Create hash table for keeping LV locks & status */
|
||||
lv_hash = dm_hash_create(100);
|
||||
pthread_mutex_init(&lv_hash_lock, NULL);
|
||||
pthread_mutex_init(&lvm_lock, NULL);
|
||||
}
|
||||
|
||||
/* Called at shutdown to tidy the lockspace */
|
||||
void unlock_all()
|
||||
void destroy_lvhash()
|
||||
{
|
||||
struct dm_hash_node *v;
|
||||
struct lv_info *lvi;
|
||||
char *resource;
|
||||
int status;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
dm_hash_iterate(v, lv_hash) {
|
||||
struct lv_info *lvi = dm_hash_get_data(lv_hash, v);
|
||||
|
||||
sync_unlock(dm_hash_get_key(lv_hash, v), lvi->lock_id);
|
||||
dm_hash_iterate(v, lv_hash) {
|
||||
lvi = dm_hash_get_data(lv_hash, v);
|
||||
resource = dm_hash_get_key(lv_hash, v);
|
||||
|
||||
if ((status = sync_unlock(resource, lvi->lock_id)))
|
||||
DEBUGLOG("unlock_all. unlock failed(%d): %s\n",
|
||||
status, strerror(errno));
|
||||
free(lvi);
|
||||
}
|
||||
|
||||
dm_hash_destroy(lv_hash);
|
||||
lv_hash = NULL;
|
||||
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
|
||||
@@ -104,10 +241,7 @@ int hold_lock(char *resource, int mode, int flags)
|
||||
|
||||
flags &= LKF_NOQUEUE; /* Only LKF_NOQUEUE is valid here */
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = dm_hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (lvi) {
|
||||
if ((lvi = lookup_info(resource))) {
|
||||
/* Already exists - convert it */
|
||||
status =
|
||||
sync_lock(resource, mode, LKF_CONVERT | flags,
|
||||
@@ -133,11 +267,9 @@ int hold_lock(char *resource, int mode, int flags)
|
||||
free(lvi);
|
||||
DEBUGLOG("hold_lock. lock at %d failed: %s\n", mode,
|
||||
strerror(errno));
|
||||
} else {
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
dm_hash_insert(lv_hash, resource, lvi);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
}
|
||||
} else
|
||||
insert_info(resource, lvi);
|
||||
|
||||
errno = saved_errno;
|
||||
}
|
||||
return status;
|
||||
@@ -150,10 +282,7 @@ int hold_unlock(char *resource)
|
||||
int status;
|
||||
int saved_errno;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = dm_hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
if (!lvi) {
|
||||
if (!(lvi = lookup_info(resource))) {
|
||||
DEBUGLOG("hold_unlock, lock not already held\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -161,9 +290,7 @@ int hold_unlock(char *resource)
|
||||
status = sync_unlock(resource, lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status) {
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
dm_hash_remove(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
remove_info(resource);
|
||||
free(lvi);
|
||||
} else {
|
||||
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
|
||||
@@ -306,35 +433,53 @@ static int do_deactivate_lv(char *resource, unsigned char lock_flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *do_lock_query(char *resource)
|
||||
{
|
||||
int mode;
|
||||
const char *type = NULL;
|
||||
|
||||
mode = get_current_lock(resource);
|
||||
switch (mode) {
|
||||
case LKM_NLMODE: type = "NL"; break;
|
||||
case LKM_CRMODE: type = "CR"; break;
|
||||
case LKM_CWMODE: type = "CW"; break;
|
||||
case LKM_PRMODE: type = "PR"; break;
|
||||
case LKM_PWMODE: type = "PW"; break;
|
||||
case LKM_EXMODE: type = "EX"; break;
|
||||
}
|
||||
|
||||
DEBUGLOG("do_lock_query: resource '%s', mode %i (%s)\n", resource, mode, type ?: "?");
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/* This is the LOCK_LV part that happens on all nodes in the cluster -
|
||||
it is responsible for the interaction with device-mapper and LVM */
|
||||
int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
|
||||
resource, command, lock_flags);
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||
/* Reinitialise various settings inc. logging, filters */
|
||||
if (!refresh_toolcontext(cmd)) {
|
||||
if (do_refresh_cache()) {
|
||||
log_error("Updated config file invalid. Aborting.");
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (lock_flags & LCK_PARTIAL_MODE)
|
||||
init_partial(1);
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||
init_mirror_in_sync(1);
|
||||
|
||||
if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
|
||||
init_dmeventd_monitor(0);
|
||||
|
||||
switch (command) {
|
||||
cmd->partial_activation = (lock_flags & LCK_PARTIAL_MODE) ? 1 : 0;
|
||||
|
||||
switch (command & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
|
||||
break;
|
||||
@@ -366,15 +511,14 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
break;
|
||||
}
|
||||
|
||||
if (lock_flags & LCK_PARTIAL_MODE)
|
||||
init_partial(0);
|
||||
|
||||
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
|
||||
init_mirror_in_sync(0);
|
||||
|
||||
if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
|
||||
init_dmeventd_monitor(DEFAULT_DMEVENTD_MONITOR);
|
||||
|
||||
cmd->partial_activation = 0;
|
||||
|
||||
/* clean the pool for another command */
|
||||
dm_pool_empty(cmd->mem);
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
@@ -391,8 +535,8 @@ int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
before suspending cluster-wide.
|
||||
*/
|
||||
if (command == LCK_LV_SUSPEND) {
|
||||
DEBUGLOG("pre_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||
resource, command, lock_flags);
|
||||
DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE))
|
||||
return errno;
|
||||
@@ -411,8 +555,8 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
int oldmode;
|
||||
|
||||
DEBUGLOG
|
||||
("post_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||
resource, command, lock_flags);
|
||||
("post_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
/* If the lock state is PW then restore it to what it was */
|
||||
oldmode = get_current_lock(resource);
|
||||
@@ -437,7 +581,7 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if a VG is un use by LVM1 so we don't stomp on it */
|
||||
/* Check if a VG is in use by LVM1 so we don't stomp on it */
|
||||
int do_check_lvm1(const char *vgname)
|
||||
{
|
||||
int status;
|
||||
@@ -453,9 +597,14 @@ int do_refresh_cache()
|
||||
DEBUGLOG("Refreshing context\n");
|
||||
log_notice("Refreshing context");
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
|
||||
ret = refresh_toolcontext(cmd);
|
||||
init_full_scan_done(0);
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
|
||||
return ret==1?0:-1;
|
||||
}
|
||||
@@ -470,9 +619,10 @@ static void drop_vg_locks()
|
||||
char line[255];
|
||||
FILE *vgs =
|
||||
popen
|
||||
("lvm pvs --nolocking --noheadings -o vg_name", "r");
|
||||
("lvm pvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_name", "r");
|
||||
|
||||
sync_unlock("P_orphans", LCK_EXCL);
|
||||
sync_unlock("P_" VG_ORPHANS, LCK_EXCL);
|
||||
sync_unlock("P_" VG_GLOBAL, LCK_EXCL);
|
||||
|
||||
if (!vgs)
|
||||
return;
|
||||
@@ -499,6 +649,17 @@ static void drop_vg_locks()
|
||||
DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop lvmcache metadata
|
||||
*/
|
||||
void drop_metadata(const char *vgname)
|
||||
{
|
||||
DEBUGLOG("Dropping metadata for VG %s\n", vgname);
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
lvmcache_drop_metadata(vgname);
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ideally, clvmd should be started before any LVs are active
|
||||
* but this may not be the case...
|
||||
@@ -511,7 +672,7 @@ static void *get_initial_state()
|
||||
char line[255];
|
||||
FILE *lvs =
|
||||
popen
|
||||
("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
|
||||
("lvm lvs --config 'log{command_names=0 prefix=\"\"}' --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
|
||||
"r");
|
||||
|
||||
if (!lvs)
|
||||
@@ -551,7 +712,7 @@ static void *get_initial_state()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void lvm2_log_fn(int level, const char *file, int line,
|
||||
static void lvm2_log_fn(int level, const char *file, int line, int dm_errno,
|
||||
const char *message)
|
||||
{
|
||||
|
||||
@@ -560,7 +721,7 @@ static void lvm2_log_fn(int level, const char *file, int line,
|
||||
We need to NULL the function ptr otherwise it will just call
|
||||
back into here! */
|
||||
init_log_fn(NULL);
|
||||
print_log(level, file, line, "%s", message);
|
||||
print_log(level, file, line, dm_errno, "%s", message);
|
||||
init_log_fn(lvm2_log_fn);
|
||||
|
||||
/*
|
||||
@@ -598,14 +759,6 @@ static void check_config()
|
||||
log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
|
||||
}
|
||||
|
||||
void init_lvhash()
|
||||
{
|
||||
/* Create hash table for keeping LV locks & status */
|
||||
lv_hash = dm_hash_create(100);
|
||||
pthread_mutex_init(&lv_hash_lock, NULL);
|
||||
pthread_mutex_init(&lvm_lock, NULL);
|
||||
}
|
||||
|
||||
/* Backups up the LVM metadata if it's changed */
|
||||
void lvm_do_backup(const char *vgname)
|
||||
{
|
||||
@@ -614,33 +767,38 @@ void lvm_do_backup(const char *vgname)
|
||||
|
||||
DEBUGLOG("Triggering backup of VG metadata for %s. suspended=%d\n", vgname, suspended);
|
||||
|
||||
vg = vg_read(cmd, vgname, NULL /*vgid*/, &consistent);
|
||||
if (vg) {
|
||||
if (consistent)
|
||||
check_current_backup(vg);
|
||||
}
|
||||
else {
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
|
||||
vg = vg_read_internal(cmd, vgname, NULL /*vgid*/, &consistent);
|
||||
|
||||
if (vg && consistent)
|
||||
check_current_backup(vg);
|
||||
else
|
||||
log_error("Error backing up metadata, can't find VG for group %s", vgname);
|
||||
}
|
||||
|
||||
vg_release(vg);
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
/* Called to initialise the LVM context of the daemon */
|
||||
int init_lvm(int using_gulm)
|
||||
{
|
||||
if (!(cmd = create_toolcontext(NULL, 0, 1))) {
|
||||
if (!(cmd = create_toolcontext(1, NULL))) {
|
||||
log_error("Failed to allocate command context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stored_errno()) {
|
||||
destroy_toolcontext(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
|
||||
init_syslog(LOG_DAEMON);
|
||||
openlog("clvmd", LOG_PID, LOG_DAEMON);
|
||||
init_debug(cmd->current_settings.debug);
|
||||
init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
|
||||
set_activation(cmd->current_settings.activation);
|
||||
archive_enable(cmd, cmd->current_settings.archive);
|
||||
backup_enable(cmd, cmd->current_settings.backup);
|
||||
cmd->cmd_line = (char *)"clvmd";
|
||||
cmd->cmd_line = "clvmd";
|
||||
|
||||
/* Check lvm.conf is setup for cluster-LVM */
|
||||
check_config();
|
||||
@@ -656,3 +814,10 @@ int init_lvm(int using_gulm)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void destroy_lvm(void)
|
||||
{
|
||||
if (cmd)
|
||||
destroy_toolcontext(cmd);
|
||||
cmd = NULL;
|
||||
}
|
||||
|
||||
@@ -22,16 +22,19 @@ extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern const char *do_lock_query(char *resource);
|
||||
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||
char *resource);
|
||||
extern int do_check_lvm1(const char *vgname);
|
||||
extern int do_refresh_cache(void);
|
||||
extern int init_lvm(int using_gulm);
|
||||
extern void destroy_lvm(void);
|
||||
extern void init_lvhash(void);
|
||||
extern void destroy_lvhash(void);
|
||||
extern void lvm_do_backup(const char *vgname);
|
||||
extern int hold_unlock(char *resource);
|
||||
extern int hold_lock(char *resource, int mode, int flags);
|
||||
extern void unlock_all(void);
|
||||
extern char *get_last_lvm_error(void);
|
||||
extern void drop_metadata(const char *vgname);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
@@ -26,6 +30,7 @@
|
||||
#include <libdevmapper.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "clvm.h"
|
||||
#include "refresh_clvmd.h"
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
It can also make outgoing connnections to the other clvmd nodes.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
@@ -17,23 +17,34 @@ VPATH = @srcdir@
|
||||
|
||||
SOURCES = libdevmapper-event.c
|
||||
|
||||
ifeq ("@STATIC_LINK@", "yes")
|
||||
LIB_STATIC = libdevmapper-event.a
|
||||
endif
|
||||
LIB_VERSION = $(LIB_VERSION_DM)
|
||||
|
||||
ifeq ("@LIB_SUFFIX@","dylib")
|
||||
LIB_SHARED = libdevmapper-event.dylib
|
||||
else
|
||||
LIB_SHARED = libdevmapper-event.so
|
||||
VERSIONED_SHLIB = $(LIB_SHARED).$(LIB_VERSION)
|
||||
endif
|
||||
|
||||
TARGETS = dmeventd
|
||||
CLEAN_TARGETS = dmeventd.o
|
||||
|
||||
include ../make.tmpl
|
||||
ifneq ($(MAKECMDGOALS),device-mapper)
|
||||
SUBDIRS+=plugins
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
all: dmeventd
|
||||
device-mapper: dmeventd $(LIB_STATIC)
|
||||
|
||||
LDFLAGS += -ldl -ldevmapper -lpthread
|
||||
CLDFLAGS += -ldl -ldevmapper -lpthread
|
||||
|
||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||
dmeventd: $(LIB_SHARED) $(VERSIONED_SHLIB) dmeventd.o
|
||||
$(CC) -o $@ dmeventd.o $(CFLAGS) $(LDFLAGS) \
|
||||
-L. -ldevmapper-event $(LIBS) -rdynamic
|
||||
|
||||
@@ -52,6 +63,8 @@ endif
|
||||
|
||||
install: $(INSTALL_TYPE) install_include install_dmeventd
|
||||
|
||||
install_device-mapper: $(INSTALL_TYPE) install_include install_dmeventd
|
||||
|
||||
install_include:
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \
|
||||
$(includedir)/libdevmapper-event.h
|
||||
@@ -74,6 +87,10 @@ install_static: libdevmapper-event.a
|
||||
$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
|
||||
$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
|
||||
|
||||
$(VERSIONED_SHLIB): $(LIB_SHARED)
|
||||
$(RM) -f $@
|
||||
$(LN_S) $(LIB_SHARED) $@
|
||||
|
||||
.PHONY: distclean_lib distclean
|
||||
|
||||
distclean_lib:
|
||||
|
||||
@@ -22,10 +22,9 @@
|
||||
#include "configure.h"
|
||||
#include "libdevmapper.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "list.h"
|
||||
#include "dmeventd.h"
|
||||
//#include "libmultilog.h"
|
||||
#include "log.h"
|
||||
#include "dm-logging.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
@@ -36,6 +35,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <arpa/inet.h> /* for htonl, ntohl */
|
||||
|
||||
#ifdef linux
|
||||
@@ -57,11 +57,11 @@ static volatile sig_atomic_t _thread_registries_empty = 1; /* registries are emp
|
||||
static int _debug = 0;
|
||||
|
||||
/* List (un)link macros. */
|
||||
#define LINK(x, head) list_add(head, &(x)->list)
|
||||
#define LINK(x, head) dm_list_add(head, &(x)->list)
|
||||
#define LINK_DSO(dso) LINK(dso, &_dso_registry)
|
||||
#define LINK_THREAD(thread) LINK(thread, &_thread_registry)
|
||||
|
||||
#define UNLINK(x) list_del(&(x)->list)
|
||||
#define UNLINK(x) dm_list_del(&(x)->list)
|
||||
#define UNLINK_DSO(x) UNLINK(x)
|
||||
#define UNLINK_THREAD(x) UNLINK(x)
|
||||
|
||||
@@ -100,7 +100,7 @@ static pthread_mutex_t _global_mutex;
|
||||
|
||||
/* Data kept about a DSO. */
|
||||
struct dso_data {
|
||||
struct list list;
|
||||
struct dm_list list;
|
||||
|
||||
char *dso_name; /* DSO name (eg, "evms", "dmraid", "lvm2"). */
|
||||
|
||||
@@ -142,7 +142,7 @@ struct dso_data {
|
||||
int (*unregister_device)(const char *device, const char *uuid,
|
||||
int major, int minor, void **user);
|
||||
};
|
||||
static LIST_INIT(_dso_registry);
|
||||
static DM_LIST_INIT(_dso_registry);
|
||||
|
||||
/* Structure to keep parsed register variables from client message. */
|
||||
struct message_data {
|
||||
@@ -167,7 +167,7 @@ struct message_data {
|
||||
* occurs and the event processing function of the DSO gets called.
|
||||
*/
|
||||
struct thread_status {
|
||||
struct list list;
|
||||
struct dm_list list;
|
||||
|
||||
pthread_t thread;
|
||||
|
||||
@@ -188,14 +188,14 @@ struct thread_status {
|
||||
struct dm_task *current_task;
|
||||
time_t next_time;
|
||||
uint32_t timeout;
|
||||
struct list timeout_list;
|
||||
struct dm_list timeout_list;
|
||||
void *dso_private; /* dso per-thread status variable */
|
||||
};
|
||||
static LIST_INIT(_thread_registry);
|
||||
static LIST_INIT(_thread_registry_unused);
|
||||
static DM_LIST_INIT(_thread_registry);
|
||||
static DM_LIST_INIT(_thread_registry_unused);
|
||||
|
||||
static int _timeout_running;
|
||||
static LIST_INIT(_timeout_registry);
|
||||
static DM_LIST_INIT(_timeout_registry);
|
||||
static pthread_mutex_t _timeout_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t _timeout_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
@@ -238,7 +238,7 @@ static struct thread_status *_alloc_thread_status(struct message_data *data,
|
||||
ret->dso_data = dso_data;
|
||||
ret->events = data->events.field;
|
||||
ret->timeout = data->timeout.secs;
|
||||
list_init(&ret->timeout_list);
|
||||
dm_list_init(&ret->timeout_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -458,7 +458,7 @@ static struct thread_status *_lookup_thread_status(struct message_data *data)
|
||||
{
|
||||
struct thread_status *thread;
|
||||
|
||||
list_iterate_items(thread, &_thread_registry)
|
||||
dm_list_iterate_items(thread, &_thread_registry)
|
||||
if (!strcmp(data->device_uuid, thread->device.uuid))
|
||||
return thread;
|
||||
|
||||
@@ -488,13 +488,13 @@ static void *_timeout_thread(void *unused __attribute((unused)))
|
||||
pthread_cleanup_push(_exit_timeout, NULL);
|
||||
pthread_mutex_lock(&_timeout_mutex);
|
||||
|
||||
while (!list_empty(&_timeout_registry)) {
|
||||
while (!dm_list_empty(&_timeout_registry)) {
|
||||
struct thread_status *thread;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
curr_time = time(NULL);
|
||||
|
||||
list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
|
||||
dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
|
||||
if (thread->next_time <= curr_time) {
|
||||
thread->next_time = curr_time + thread->timeout;
|
||||
pthread_kill(thread->thread, SIGALRM);
|
||||
@@ -521,8 +521,8 @@ static int _register_for_timeout(struct thread_status *thread)
|
||||
|
||||
thread->next_time = time(NULL) + thread->timeout;
|
||||
|
||||
if (list_empty(&thread->timeout_list)) {
|
||||
list_add(&_timeout_registry, &thread->timeout_list);
|
||||
if (dm_list_empty(&thread->timeout_list)) {
|
||||
dm_list_add(&_timeout_registry, &thread->timeout_list);
|
||||
if (_timeout_running)
|
||||
pthread_cond_signal(&_timeout_cond);
|
||||
}
|
||||
@@ -542,9 +542,9 @@ static int _register_for_timeout(struct thread_status *thread)
|
||||
static void _unregister_for_timeout(struct thread_status *thread)
|
||||
{
|
||||
pthread_mutex_lock(&_timeout_mutex);
|
||||
if (!list_empty(&thread->timeout_list)) {
|
||||
list_del(&thread->timeout_list);
|
||||
list_init(&thread->timeout_list);
|
||||
if (!dm_list_empty(&thread->timeout_list)) {
|
||||
dm_list_del(&thread->timeout_list);
|
||||
dm_list_init(&thread->timeout_list);
|
||||
}
|
||||
pthread_mutex_unlock(&_timeout_mutex);
|
||||
}
|
||||
@@ -697,7 +697,7 @@ static void _monitor_unregister(void *arg)
|
||||
}
|
||||
/* we may have been relinked to unused registry since we were
|
||||
called, so check that */
|
||||
list_iterate_items(thread_iter, &_thread_registry_unused)
|
||||
dm_list_iterate_items(thread_iter, &_thread_registry_unused)
|
||||
if (thread_iter == thread) {
|
||||
thread->status = DM_THREAD_DONE;
|
||||
_unlock_mutex();
|
||||
@@ -838,7 +838,7 @@ static struct dso_data *_lookup_dso(struct message_data *data)
|
||||
{
|
||||
struct dso_data *dso_data, *ret = NULL;
|
||||
|
||||
list_iterate_items(dso_data, &_dso_registry)
|
||||
dm_list_iterate_items(dso_data, &_dso_registry)
|
||||
if (!strcmp(data->dso_name, dso_data->dso_name)) {
|
||||
_lib_get(dso_data);
|
||||
ret = dso_data;
|
||||
@@ -1109,7 +1109,7 @@ static int _get_registered_dev(struct message_data *message_data, int next)
|
||||
_lock_mutex();
|
||||
|
||||
/* Iterate list of threads checking if we want a particular one. */
|
||||
list_iterate_items(thread, &_thread_registry)
|
||||
dm_list_iterate_items(thread, &_thread_registry)
|
||||
if (_want_registered_device(message_data->dso_name,
|
||||
message_data->device_uuid,
|
||||
thread)) {
|
||||
@@ -1132,10 +1132,10 @@ static int _get_registered_dev(struct message_data *message_data, int next)
|
||||
thread = hit;
|
||||
|
||||
while (1) {
|
||||
if (list_end(&_thread_registry, &thread->list))
|
||||
if (dm_list_end(&_thread_registry, &thread->list))
|
||||
goto out;
|
||||
|
||||
thread = list_item(thread->list.n, struct thread_status);
|
||||
thread = dm_list_item(thread->list.n, struct thread_status);
|
||||
if (_want_registered_device(message_data->dso_name, NULL, thread)) {
|
||||
hit = thread;
|
||||
break;
|
||||
@@ -1439,12 +1439,12 @@ static void _process_request(struct dm_event_fifos *fifos)
|
||||
static void _cleanup_unused_threads(void)
|
||||
{
|
||||
int ret;
|
||||
struct list *l;
|
||||
struct dm_list *l;
|
||||
struct thread_status *thread;
|
||||
|
||||
_lock_mutex();
|
||||
while ((l = list_first(&_thread_registry_unused))) {
|
||||
thread = list_item(l, struct thread_status);
|
||||
while ((l = dm_list_first(&_thread_registry_unused))) {
|
||||
thread = dm_list_item(l, struct thread_status);
|
||||
if (thread->processing)
|
||||
break; /* cleanup on the next round */
|
||||
|
||||
@@ -1469,7 +1469,7 @@ static void _cleanup_unused_threads(void)
|
||||
break;
|
||||
}
|
||||
|
||||
list_del(l);
|
||||
dm_list_del(l);
|
||||
syslog(LOG_ERR,
|
||||
"thread can't be on unused list unless !thread->events");
|
||||
thread->status = DM_THREAD_RUNNING;
|
||||
@@ -1479,7 +1479,7 @@ static void _cleanup_unused_threads(void)
|
||||
}
|
||||
|
||||
if (thread->status == DM_THREAD_DONE) {
|
||||
list_del(l);
|
||||
dm_list_del(l);
|
||||
pthread_join(thread->thread, NULL);
|
||||
_lib_put(thread->dso_data);
|
||||
_free_thread_status(thread);
|
||||
@@ -1740,8 +1740,8 @@ int main(int argc, char *argv[])
|
||||
while (!_exit_now) {
|
||||
_process_request(&fifos);
|
||||
_cleanup_unused_threads();
|
||||
if (!list_empty(&_thread_registry)
|
||||
|| !list_empty(&_thread_registry_unused))
|
||||
if (!dm_list_empty(&_thread_registry)
|
||||
|| !dm_list_empty(&_thread_registry_unused))
|
||||
_thread_registries_empty = 0;
|
||||
else
|
||||
_thread_registries_empty = 1;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "dmlib.h"
|
||||
#include "libdevmapper-event.h"
|
||||
//#include "libmultilog.h"
|
||||
#include "dmeventd.h"
|
||||
@@ -425,6 +425,12 @@ static int _start_daemon(struct dm_event_fifos *fifos)
|
||||
|
||||
start_server:
|
||||
/* server is not running */
|
||||
|
||||
if (!strncmp(DMEVENTD_PATH, "/", 1) && stat(DMEVENTD_PATH, &statbuf)) {
|
||||
log_error("Unable to find dmeventd.");
|
||||
return_0;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0)
|
||||
@@ -432,7 +438,7 @@ static int _start_daemon(struct dm_event_fifos *fifos)
|
||||
|
||||
else if (!pid) {
|
||||
execvp(DMEVENTD_PATH, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
_exit(EXIT_FAILURE);
|
||||
} else {
|
||||
if (waitpid(pid, &status, 0) < 0)
|
||||
log_error("Unable to start dmeventd: %s",
|
||||
|
||||
@@ -16,7 +16,7 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SUBDIRS += mirror
|
||||
SUBDIRS += mirror snapshot
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2008 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@@ -17,7 +17,7 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper @LVM2CMD_LIB@
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
@@ -27,10 +27,13 @@ else
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||
endif
|
||||
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
install_lvm2: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
install: install_lvm2
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
|
||||
#include <libdevmapper.h>
|
||||
#include <libdevmapper-event.h>
|
||||
@@ -125,8 +126,9 @@ out_parse:
|
||||
return ME_IGNORE;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file,
|
||||
int line, const char *format)
|
||||
static void _temporary_log_fn(int level, const char *file __attribute((unused)),
|
||||
int line __attribute((unused)),
|
||||
const char *format)
|
||||
{
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
@@ -151,7 +153,7 @@ static int _remove_failed_devices(const char *device)
|
||||
}
|
||||
|
||||
/* FIXME Is any sanity-checking required on %s? */
|
||||
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
|
||||
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "lvconvert --config devices{ignore_suspended_devices=1} --repair --use-policies %s/%s", vg, lv)) {
|
||||
/* this error should be caught above, but doesn't hurt to check again */
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||
@@ -160,11 +162,18 @@ static int _remove_failed_devices(const char *device)
|
||||
|
||||
r = lvm2_run(_lvm_handle, cmd_str);
|
||||
|
||||
if (r == ECMD_PROCESSED) {
|
||||
snprintf(cmd_str, CMD_SIZE, "vgreduce --removemissing %s", vg);
|
||||
if (lvm2_run(_lvm_handle, cmd_str) != 1)
|
||||
syslog(LOG_ERR, "Unable to remove failed PVs from VG %s", vg);
|
||||
}
|
||||
|
||||
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||
return (r == 1) ? 0 : -1;
|
||||
return (r == ECMD_PROCESSED) ? 0 : -1;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
void *next = NULL;
|
||||
@@ -222,8 +231,11 @@ void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
@@ -259,8 +271,11 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
@@ -17,20 +17,23 @@ top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper -llvm2cmd
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper @LVM2CMD_LIB@
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
SOURCES = dmeventd_snapshot.c
|
||||
|
||||
ifeq ("@LIB_SUFFIX@","dylib")
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
|
||||
LIB_SHARED = libdevmapper-event-lvm2snapshot.dylib
|
||||
else
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||
LIB_SHARED = libdevmapper-event-lvm2snapshot.so
|
||||
endif
|
||||
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
install_lvm2: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
install: install_lvm2
|
||||
213
daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
Normal file
213
daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "lvm2cmd.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
/* FIXME Missing openlog? */
|
||||
|
||||
/* First warning when snapshot is 80% full. */
|
||||
#define WARNING_THRESH 80
|
||||
/* Further warnings at 85%, 90% and 95% fullness. */
|
||||
#define WARNING_STEP 5
|
||||
|
||||
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
* Number of active registrations.
|
||||
*/
|
||||
static int _register_count = 0;
|
||||
|
||||
static struct dm_pool *_mem_pool = NULL;
|
||||
static void *_lvm_handle = NULL;
|
||||
|
||||
struct snap_status {
|
||||
int invalid;
|
||||
int used;
|
||||
int max;
|
||||
};
|
||||
|
||||
/*
|
||||
* Currently only one event can be processed at a time.
|
||||
*/
|
||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void _temporary_log_fn(int level,
|
||||
const char *file __attribute((unused)),
|
||||
int line __attribute((unused)),
|
||||
const char *format)
|
||||
{
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
else
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
/* FIXME possibly reconcile this with target_percent when we gain
|
||||
access to regular LVM library here. */
|
||||
static void _parse_snapshot_params(char *params, struct snap_status *stat)
|
||||
{
|
||||
char *p;
|
||||
/*
|
||||
* xx/xx -- fractions used/max
|
||||
* Invalid -- snapshot invalidated
|
||||
* Unknown -- status unknown
|
||||
*/
|
||||
stat->used = stat->max = 0;
|
||||
|
||||
if (!strncmp(params, "Invalid", 7)) {
|
||||
stat->invalid = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we return without setting non-zero max, the parent is
|
||||
* responsible for reporting errors.
|
||||
*/
|
||||
if (!strncmp(params, "Unknown", 7))
|
||||
return;
|
||||
|
||||
if (!(p = strstr(params, "/")))
|
||||
return;
|
||||
|
||||
*p = '\0';
|
||||
p++;
|
||||
|
||||
stat->used = atoi(params);
|
||||
stat->max = atoi(p);
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute((unused)),
|
||||
void **private)
|
||||
{
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
struct snap_status stat = { 0 };
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
int percent, *percent_warning = (int*)private;
|
||||
|
||||
/* No longer monitoring, waiting for remove */
|
||||
if (!*percent_warning)
|
||||
return;
|
||||
|
||||
if (pthread_mutex_trylock(&_event_mutex)) {
|
||||
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
|
||||
pthread_mutex_lock(&_event_mutex);
|
||||
}
|
||||
|
||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
if (!target_type)
|
||||
goto out;
|
||||
|
||||
_parse_snapshot_params(params, &stat);
|
||||
/*
|
||||
* If the snapshot has been invalidated or we failed to parse
|
||||
* the status string. Report the full status string to syslog.
|
||||
*/
|
||||
if (stat.invalid || !stat.max) {
|
||||
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
|
||||
*percent_warning = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
percent = 100 * stat.used / stat.max;
|
||||
if (percent >= *percent_warning) {
|
||||
syslog(LOG_WARNING, "Snapshot %s is now %i%% full.\n", device, percent);
|
||||
/* Print warning on the next multiple of WARNING_STEP. */
|
||||
*percent_warning = (percent / WARNING_STEP) * WARNING_STEP + WARNING_STEP;
|
||||
}
|
||||
out:
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **private)
|
||||
{
|
||||
int r = 0;
|
||||
int *percent_warning = (int*)private;
|
||||
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
/*
|
||||
* Need some space for allocations. 1024 should be more
|
||||
* than enough for what we need (device mapper name splitting)
|
||||
*/
|
||||
if (!_mem_pool && !(_mem_pool = dm_pool_create("snapshot_dso", 1024)))
|
||||
goto out;
|
||||
|
||||
*percent_warning = WARNING_THRESH; /* Print warning if snapshot is full */
|
||||
|
||||
if (!_lvm_handle) {
|
||||
lvm2_log_fn(_temporary_log_fn);
|
||||
if (!(_lvm_handle = lvm2_init())) {
|
||||
dm_pool_destroy(_mem_pool);
|
||||
_mem_pool = NULL;
|
||||
goto out;
|
||||
}
|
||||
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
|
||||
/* FIXME Temporary: move to dmeventd core */
|
||||
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "Monitoring snapshot %s\n", device);
|
||||
|
||||
_register_count++;
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
pthread_mutex_unlock(&_register_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device,
|
||||
const char *uuid __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
syslog(LOG_INFO, "No longer monitoring snapshot %s\n",
|
||||
device);
|
||||
|
||||
if (!--_register_count) {
|
||||
dm_pool_destroy(_mem_pool);
|
||||
_mem_pool = NULL;
|
||||
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||
lvm2_exit(_lvm_handle);
|
||||
_lvm_handle = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_register_mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
6
debian/README.Debian
vendored
6
debian/README.Debian
vendored
@@ -1,6 +0,0 @@
|
||||
LVM2 requires the device-mapper kernel module (dm-mod). This is
|
||||
available as a kernel patch for 2.4 (in kernel-patch-device-mapper), and
|
||||
is distributed with linux 2.5 and above. The LVM1 kernel module (lvm-mod)
|
||||
will not work with lvm2 packages. dm-mod and lvm-mod may both be loaded
|
||||
in the kernel at the same time with no problems. Without dm-mod, this
|
||||
package is pretty useless.
|
||||
82
debian/changelog
vendored
82
debian/changelog
vendored
@@ -1,82 +0,0 @@
|
||||
lvm2 (1.95.15-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Remove undocumented manpage symlinks.
|
||||
* Update description to be more informative. (Closes: #173499)
|
||||
* Add kernel-patch-device-mapper suggestion.
|
||||
* Update standards version.
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Sun, 16 Feb 2002 04:21:26 -0400
|
||||
|
||||
lvm2 (1.95.11-1) unstable; urgency=low
|
||||
|
||||
* New upstream release. (Closes: #171436)
|
||||
* Removed TODO and INTRO from debian/docs; added WHATS_NEW.
|
||||
* Remove vgcfgrestore.8 undocumented symlink.
|
||||
* Added a README.Debian, mentioning the device-mapper kernel module
|
||||
requirement that lvm2 has. (Closes: #171674, #163020)
|
||||
* Get rid of debian/conffiles (debhelper's smart enough to figure that out).
|
||||
* debian/copyright fix to appease lintian.
|
||||
* Fix typo in tools/commands.h that caused /usr/sbin/; to be created.
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Mon, 9 Dec 2002 02:51:02 -0400
|
||||
|
||||
lvm2 (1.95.10-2) unstable; urgency=low
|
||||
|
||||
* Fix software raid problems by ensuring lvm init script runs after
|
||||
raidtools init script. (Closes: #152569)
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Tue, 3 Sep 2002 04:05:43 -0400
|
||||
|
||||
lvm2 (1.95.10-1) unstable; urgency=low
|
||||
|
||||
* New upstream release (Beta 3.2).
|
||||
* Change all references to /dev/device-mapper/control to
|
||||
/dev/mapper/control.
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Sun, 1 Sep 2002 18:55:12 -0400
|
||||
|
||||
lvm2 (0.95.05-3) unstable; urgency=low
|
||||
|
||||
* Get rid of awk dependency in init script. (Closes: #146257)
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Sun, 12 May 2002 04:39:06 -0500
|
||||
|
||||
lvm2 (0.95.05-2) unstable; urgency=low
|
||||
|
||||
* Use ${shlibs:Depends} in Depends.
|
||||
* Get rid of postinst/postrm scripts, use debhelper's init script instead.
|
||||
* Add Conflicts against lvm10, lvm-common.
|
||||
* Fix endian issues on big-endian machines.
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Thu, 2 May 2002 23:53:53 -0500
|
||||
|
||||
lvm2 (0.95.05-1) unstable; urgency=low
|
||||
|
||||
* New release (Beta2).
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Thu, 25 Apr 2002 00:37:41 -0500
|
||||
|
||||
lvm2 (0.95.04cvs20020306-1) unstable; urgency=low
|
||||
|
||||
* CVS updated.
|
||||
* Convert from debian native package.
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Wed, 6 Mar 2002 00:43:21 -0500
|
||||
|
||||
lvm2 (0.95.04cvs20020304) unstable; urgency=low
|
||||
|
||||
* CVS updated.
|
||||
* Enhance init script; create devmapper control device, etc.
|
||||
* Add dmsetup as a suggestion.
|
||||
* Add /etc/lvm/lvm.conf conffile.
|
||||
* Add undocumented(7) for the commands missing manpages.
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Mon, 4 Mar 2002 04:51:26 -0500
|
||||
|
||||
lvm2 (0.95.02cvs20020220) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
-- Andres Salomon <dilinger@mp3revolution.net> Wed, 20 Feb 2002 03:17:25 -0500
|
||||
|
||||
24
debian/control
vendored
24
debian/control
vendored
@@ -1,24 +0,0 @@
|
||||
Source: lvm2
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Maintainer: Andres Salomon <dilinger@mp3revolution.net>
|
||||
Build-Depends: debhelper (>> 3.0.0), libdevmapper-dev (>= 0.96.04), libreadline4-dev
|
||||
Standards-Version: 3.5.8.0
|
||||
|
||||
Package: lvm2
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Conflicts: lvm10, lvm-common
|
||||
Replaces: lvm10, lvm-common
|
||||
Provides: lvm-binaries
|
||||
Suggests: dmsetup, kernel-patch-device-mapper
|
||||
Description: The Linux Logical Volume Manager
|
||||
This is LVM2, the rewrite of The Linux Logical Volume Manager. LVM
|
||||
supports enterprise level volume management of disk and disk subsystems
|
||||
by grouping arbitrary disks into volume groups. The total capacity of
|
||||
volume groups can be allocated to logical volumes, which are accessed as
|
||||
regular block devices.
|
||||
.
|
||||
LVM2 is currently stable, but has some unimplemented features (most notably,
|
||||
pvmove and e2fsadm). It is not yet recommended for production use. It is
|
||||
backwards-compatible with LVM1 (lvm10), and requires Linux kernel 2.4.
|
||||
25
debian/copyright
vendored
25
debian/copyright
vendored
@@ -1,25 +0,0 @@
|
||||
This package was debianized by Andres Salomon <dilinger@mp3revolution.net> on
|
||||
Wed, 20 Feb 2002 03:17:25 -0500.
|
||||
|
||||
It was downloaded from http://www.sistina.com/products_lvm.htm
|
||||
|
||||
Upstream Author: LVM Development Team
|
||||
|
||||
Copyright (c) 2001-2002 LVM Development Team
|
||||
|
||||
LVM2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
LVM2 is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
On Debian systems, the full text of the GPL can be found in
|
||||
/usr/share/common-licenses/GPL
|
||||
4
debian/dirs
vendored
4
debian/dirs
vendored
@@ -1,4 +0,0 @@
|
||||
etc/lvm
|
||||
usr/share/man/man5
|
||||
usr/share/man/man8
|
||||
sbin
|
||||
5
debian/docs
vendored
5
debian/docs
vendored
@@ -1,5 +0,0 @@
|
||||
BUGS
|
||||
README
|
||||
VERSION
|
||||
WHATS_NEW
|
||||
doc/*
|
||||
64
debian/init.d
vendored
64
debian/init.d
vendored
@@ -1,64 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# lvm2 This script handles LVM2 initialization/shutdown.
|
||||
#
|
||||
# Written by Andres Salomon <dilinger@mp3revolution.net>.
|
||||
#
|
||||
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||
NAME=lvm2
|
||||
DESC=LVM
|
||||
|
||||
test -x /sbin/vgchange || exit 0
|
||||
modprobe dm-mod >/dev/null 2>&1
|
||||
|
||||
# Create necessary files in /dev for device-mapper
|
||||
create_devfiles() {
|
||||
DIR="/dev/mapper"
|
||||
FILE="$DIR/control"
|
||||
major=$(grep "[0-9] misc$" /proc/devices | sed 's/[ ]\+misc//')
|
||||
minor=$(grep "[0-9] device-mapper$" /proc/misc | sed 's/[ ]\+device-mapper//')
|
||||
|
||||
if test ! -d $DIR; then
|
||||
mkdir --mode=755 $DIR >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
if test ! -c $FILE -a ! -z "$minor"; then
|
||||
mknod --mode=600 $FILE c $major $minor >/dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Initializing $DESC: "
|
||||
create_devfiles
|
||||
vgchange -a y
|
||||
|
||||
# # Mount all LVM devices
|
||||
# for vg in $( vgchange -a y 2>/dev/null | grep active | awk -F\" '{print $2}' ); do
|
||||
# MTPT=$( grep $vg /etc/fstab | awk '{print $2}' )
|
||||
# mount $MTPT
|
||||
# done
|
||||
echo "$NAME."
|
||||
;;
|
||||
stop)
|
||||
echo -n "Shutting down $DESC: "
|
||||
# We don't really try all that hard to shut it down; far too many
|
||||
# things that can keep it from successfully shutting down.
|
||||
vgchange -a n
|
||||
echo "$NAME."
|
||||
;;
|
||||
restart|force-reload)
|
||||
echo -n "Restarting $DESC: "
|
||||
vgchange -a n
|
||||
sleep 1
|
||||
vgchange -a y
|
||||
echo "$NAME."
|
||||
;;
|
||||
*)
|
||||
echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
26
debian/manpages
vendored
26
debian/manpages
vendored
@@ -1,26 +0,0 @@
|
||||
debian/lvm2/usr/share/man/man5/lvm.conf.5
|
||||
debian/lvm2/usr/share/man/man8/lvchange.8
|
||||
debian/lvm2/usr/share/man/man8/lvcreate.8
|
||||
debian/lvm2/usr/share/man/man8/lvdisplay.8
|
||||
debian/lvm2/usr/share/man/man8/lvextend.8
|
||||
debian/lvm2/usr/share/man/man8/lvm.8
|
||||
debian/lvm2/usr/share/man/man8/lvmchange.8
|
||||
debian/lvm2/usr/share/man/man8/lvreduce.8
|
||||
debian/lvm2/usr/share/man/man8/lvremove.8
|
||||
debian/lvm2/usr/share/man/man8/lvrename.8
|
||||
debian/lvm2/usr/share/man/man8/lvscan.8
|
||||
debian/lvm2/usr/share/man/man8/pvchange.8
|
||||
debian/lvm2/usr/share/man/man8/pvcreate.8
|
||||
debian/lvm2/usr/share/man/man8/pvdisplay.8
|
||||
debian/lvm2/usr/share/man/man8/pvscan.8
|
||||
debian/lvm2/usr/share/man/man8/vgcfgbackup.8
|
||||
debian/lvm2/usr/share/man/man8/vgchange.8
|
||||
debian/lvm2/usr/share/man/man8/vgck.8
|
||||
debian/lvm2/usr/share/man/man8/vgcreate.8
|
||||
debian/lvm2/usr/share/man/man8/vgdisplay.8
|
||||
debian/lvm2/usr/share/man/man8/vgextend.8
|
||||
debian/lvm2/usr/share/man/man8/vgmerge.8
|
||||
debian/lvm2/usr/share/man/man8/vgreduce.8
|
||||
debian/lvm2/usr/share/man/man8/vgremove.8
|
||||
debian/lvm2/usr/share/man/man8/vgrename.8
|
||||
debian/lvm2/usr/share/man/man8/vgscan.8
|
||||
119
debian/rules
vendored
119
debian/rules
vendored
@@ -1,119 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# GNU copyright 1997 by Joey Hess.
|
||||
#
|
||||
# This version is for a hypothetical package that builds an
|
||||
# architecture-dependant package, as well as an architecture-independent
|
||||
# package.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
# This is the debhelper compatibility version to use.
|
||||
export DH_COMPAT=3
|
||||
|
||||
# These are used for cross-compiling and for saving the configure script
|
||||
# from having to guess our platform (since we know it already)
|
||||
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
|
||||
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
|
||||
CFLAGS += -g
|
||||
endif
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
INSTALL_PROGRAM += -s
|
||||
endif
|
||||
|
||||
configure: configure-stamp
|
||||
configure-stamp:
|
||||
dh_testdir
|
||||
# Add here commands to configure the package.
|
||||
./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/ --mandir=\$${prefix}/usr/share/man --infodir=\$${prefix}/usr/share/info
|
||||
|
||||
touch configure-stamp
|
||||
|
||||
build-arch: configure-stamp build-arch-stamp
|
||||
build-arch-stamp:
|
||||
dh_testdir
|
||||
|
||||
# Add here command to compile/build the package.
|
||||
$(MAKE)
|
||||
|
||||
touch build-arch-stamp
|
||||
|
||||
build-indep: configure-stamp build-indep-stamp
|
||||
build-indep-stamp:
|
||||
dh_testdir
|
||||
|
||||
# Add here command to compile/build the arch indep package.
|
||||
# It's ok not to do anything here, if you don't need to build
|
||||
# anything for this package.
|
||||
#/usr/bin/docbook-to-man debian/lvm2.sgml > lvm2.1
|
||||
|
||||
touch build-indep-stamp
|
||||
|
||||
build: build-arch build-indep
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -f build-stamp configure-stamp
|
||||
|
||||
# Add here commands to clean up after the build process.
|
||||
-$(MAKE) distclean
|
||||
-test -r /usr/share/misc/config.sub && \
|
||||
cp -f /usr/share/misc/config.sub config.sub
|
||||
-test -r /usr/share/misc/config.guess && \
|
||||
cp -f /usr/share/misc/config.guess config.guess
|
||||
|
||||
|
||||
dh_clean
|
||||
|
||||
install: DH_OPTIONS=
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
|
||||
# Add here commands to install the package into debian/lvm2.
|
||||
$(MAKE) install prefix=$(CURDIR)/debian/lvm2
|
||||
install -m 0644 doc/example.conf debian/lvm2/etc/lvm/lvm.conf
|
||||
|
||||
|
||||
# Build architecture-independent files here.
|
||||
# Pass -i to all debhelper commands in this target to reduce clutter.
|
||||
binary-indep: build install
|
||||
# nada.
|
||||
|
||||
# Build architecture-dependent files here.
|
||||
binary-arch: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
|
||||
# dh_installdebconf
|
||||
dh_installdocs
|
||||
dh_installexamples
|
||||
# dh_installlogrotate -a
|
||||
# dh_installemacsen -a
|
||||
# dh_installpam -a
|
||||
# dh_installmime -a
|
||||
dh_installinit --update-rcd-params="start 26 S . start 50 0 6 ."
|
||||
dh_installcron
|
||||
dh_installman
|
||||
dh_installinfo
|
||||
dh_installchangelogs
|
||||
dh_strip
|
||||
dh_link
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
dh_makeshlibs
|
||||
dh_installdeb
|
||||
# dh_perl -a
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
|
||||
#include <libdevmapper.h>
|
||||
#include <libdevmapper-event.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||
/* FIXME Missing openlog? */
|
||||
|
||||
#define ME_IGNORE 0
|
||||
#define ME_INSYNC 1
|
||||
#define ME_FAILURE 2
|
||||
|
||||
/*
|
||||
* register_device() is called first and performs initialisation.
|
||||
* Only one device may be registered or unregistered at a time.
|
||||
*/
|
||||
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
* Number of active registrations.
|
||||
*/
|
||||
static int _register_count = 0;
|
||||
|
||||
static struct dm_pool *_mem_pool = NULL;
|
||||
static void *_lvm_handle = NULL;
|
||||
|
||||
/*
|
||||
* Currently only one event can be processed at a time.
|
||||
*/
|
||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
{
|
||||
int i, r = ME_INSYNC;
|
||||
char **args = NULL;
|
||||
char *dev_status_str;
|
||||
char *log_status_str;
|
||||
char *sync_str;
|
||||
char *p = NULL;
|
||||
int log_argc, num_devs;
|
||||
|
||||
/*
|
||||
* dm core parms: 0 409600 mirror
|
||||
* Mirror core parms: 2 253:4 253:5 400/400
|
||||
* New-style failure params: 1 AA
|
||||
* New-style log params: 3 cluster 253:3 A
|
||||
* or 3 disk 253:3 A
|
||||
* or 1 core
|
||||
*/
|
||||
|
||||
/* number of devices */
|
||||
if (!dm_split_words(params, 1, 0, &p))
|
||||
goto out_parse;
|
||||
|
||||
if (!(num_devs = atoi(p)))
|
||||
goto out_parse;
|
||||
p += strlen(p) + 1;
|
||||
|
||||
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
|
||||
args = dm_malloc((num_devs + 7) * sizeof(char *));
|
||||
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
|
||||
goto out_parse;
|
||||
|
||||
dev_status_str = args[2 + num_devs];
|
||||
log_argc = atoi(args[3 + num_devs]);
|
||||
log_status_str = args[3 + num_devs + log_argc];
|
||||
sync_str = args[num_devs];
|
||||
|
||||
/* Check for bad mirror devices */
|
||||
for (i = 0; i < num_devs; i++)
|
||||
if (dev_status_str[i] == 'D') {
|
||||
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
|
||||
r = ME_FAILURE;
|
||||
}
|
||||
|
||||
/* Check for bad disk log device */
|
||||
if (log_argc > 1 && log_status_str[0] == 'D') {
|
||||
syslog(LOG_ERR, "Log device, %s, has failed.\n",
|
||||
args[2 + num_devs + log_argc]);
|
||||
r = ME_FAILURE;
|
||||
}
|
||||
|
||||
if (r == ME_FAILURE)
|
||||
goto out;
|
||||
|
||||
p = strstr(sync_str, "/");
|
||||
if (p) {
|
||||
p[0] = '\0';
|
||||
if (strcmp(sync_str, p+1))
|
||||
r = ME_IGNORE;
|
||||
p[0] = '/';
|
||||
} else
|
||||
goto out_parse;
|
||||
|
||||
out:
|
||||
if (args)
|
||||
dm_free(args);
|
||||
return r;
|
||||
|
||||
out_parse:
|
||||
if (args)
|
||||
dm_free(args);
|
||||
syslog(LOG_ERR, "Unable to parse mirror status string.");
|
||||
return ME_IGNORE;
|
||||
}
|
||||
|
||||
static void _temporary_log_fn(int level, const char *file,
|
||||
int line, const char *format)
|
||||
{
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
else
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
{
|
||||
int r;
|
||||
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
||||
char cmd_str[CMD_SIZE];
|
||||
char *vg = NULL, *lv = NULL, *layer = NULL;
|
||||
|
||||
if (strlen(device) > 200) /* FIXME Use real restriction */
|
||||
return -ENAMETOOLONG; /* FIXME These return code distinctions are not used so remove them! */
|
||||
|
||||
if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
|
||||
syslog(LOG_ERR, "Unable to determine VG name from %s",
|
||||
device);
|
||||
return -ENOMEM; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||
}
|
||||
|
||||
/* FIXME Is any sanity-checking required on %s? */
|
||||
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
|
||||
/* this error should be caught above, but doesn't hurt to check again */
|
||||
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||
}
|
||||
|
||||
r = lvm2_run(_lvm_handle, cmd_str);
|
||||
|
||||
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||
return (r == 1) ? 0 : -1;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
|
||||
if (pthread_mutex_trylock(&_event_mutex)) {
|
||||
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
|
||||
pthread_mutex_lock(&_event_mutex);
|
||||
}
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
|
||||
if (!target_type) {
|
||||
syslog(LOG_INFO, "%s mapping lost.\n", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(target_type, "mirror")) {
|
||||
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(_get_mirror_event(params)) {
|
||||
case ME_INSYNC:
|
||||
/* FIXME: all we really know is that this
|
||||
_part_ of the device is in sync
|
||||
Also, this is not an error
|
||||
*/
|
||||
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
|
||||
break;
|
||||
case ME_FAILURE:
|
||||
syslog(LOG_ERR, "Device failure in %s\n", device);
|
||||
if (_remove_failed_devices(device))
|
||||
/* FIXME Why are all the error return codes unused? Get rid of them? */
|
||||
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
|
||||
device);
|
||||
/* Should check before warning user that device is now linear
|
||||
else
|
||||
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||
device);
|
||||
*/
|
||||
break;
|
||||
case ME_IGNORE:
|
||||
break;
|
||||
default:
|
||||
/* FIXME Provide value then! */
|
||||
syslog(LOG_INFO, "Unknown event received.\n");
|
||||
}
|
||||
} while (next);
|
||||
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device);
|
||||
|
||||
/*
|
||||
* Need some space for allocations. 1024 should be more
|
||||
* than enough for what we need (device mapper name splitting)
|
||||
*/
|
||||
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
|
||||
goto out;
|
||||
|
||||
if (!_lvm_handle) {
|
||||
lvm2_log_fn(_temporary_log_fn);
|
||||
if (!(_lvm_handle = lvm2_init())) {
|
||||
dm_pool_destroy(_mem_pool);
|
||||
_mem_pool = NULL;
|
||||
goto out;
|
||||
}
|
||||
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
|
||||
/* FIXME Temporary: move to dmeventd core */
|
||||
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||
}
|
||||
|
||||
_register_count++;
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
pthread_mutex_unlock(&_register_mutex);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
|
||||
device);
|
||||
|
||||
if (!--_register_count) {
|
||||
dm_pool_destroy(_mem_pool);
|
||||
_mem_pool = NULL;
|
||||
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||
lvm2_exit(_lvm_handle);
|
||||
_lvm_handle = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_register_mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -20,10 +20,11 @@ CONFDEST=lvm.conf
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install:
|
||||
install_lvm2:
|
||||
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||
echo "Installing $(CONFSRC) as $(confdir)/$(CONFDEST)"; \
|
||||
@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $(CONFSRC) \
|
||||
$(confdir)/$(CONFDEST); \
|
||||
fi
|
||||
|
||||
install: install_lvm2
|
||||
|
||||
111
doc/example.conf
111
doc/example.conf
@@ -25,7 +25,8 @@ devices {
|
||||
# list of regular expressions in turn and the first match is used.
|
||||
preferred_names = [ ]
|
||||
|
||||
# preferred_names = [ "^/dev/mpath/", "^/dev/[hs]d" ]
|
||||
# Try to avoid using undescriptive /dev/dm-N names, if present.
|
||||
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
|
||||
|
||||
# A filter that tells LVM2 to only use a restricted set of devices.
|
||||
# The filter consists of an array of regular expressions. These
|
||||
@@ -85,13 +86,45 @@ devices {
|
||||
# If sysfs is mounted (2.6 kernels) restrict device scanning to
|
||||
# the block devices it believes are valid.
|
||||
# 1 enables; 0 disables.
|
||||
sysfs_scan = 1
|
||||
sysfs_scan = 1
|
||||
|
||||
# By default, LVM2 will ignore devices used as components of
|
||||
# software RAID (md) devices by looking for md superblocks.
|
||||
# 1 enables; 0 disables.
|
||||
md_component_detection = 1
|
||||
|
||||
# By default, if a PV is placed directly upon an md device, LVM2
|
||||
# will align its data blocks with the md device's stripe-width.
|
||||
# 1 enables; 0 disables.
|
||||
md_chunk_alignment = 1
|
||||
|
||||
# By default, the start of a PV's data area will be a multiple of
|
||||
# the 'minimum_io_size' or 'optimal_io_size' exposed in sysfs.
|
||||
# - minimum_io_size - the smallest request the device can perform
|
||||
# w/o incurring a read-modify-write penalty (e.g. MD's chunk size)
|
||||
# - optimal_io_size - the device's preferred unit of receiving I/O
|
||||
# (e.g. MD's stripe width)
|
||||
# minimum_io_size is used if optimal_io_size is undefined (0).
|
||||
# If md_chunk_alignment is enabled, that detects the optimal_io_size.
|
||||
# This setting takes precedence over md_chunk_alignment.
|
||||
# 1 enables; 0 disables.
|
||||
data_alignment_detection = 1
|
||||
|
||||
# Alignment (in KB) of start of data area when creating a new PV.
|
||||
# If a PV is placed directly upon an md device and md_chunk_alignment or
|
||||
# data_alignment_detection is enabled this parameter is ignored.
|
||||
# Set to 0 for the default alignment of 64KB or page size, if larger.
|
||||
data_alignment = 0
|
||||
|
||||
# By default, the start of the PV's aligned data area will be shifted by
|
||||
# the 'alignment_offset' exposed in sysfs. This offset is often 0 but
|
||||
# may be non-zero; e.g.: certain 4KB sector drives that compensate for
|
||||
# windows partitioning will have an alignment_offset of 3584 bytes
|
||||
# (sector 7 is the lowest aligned logical block, the 4KB sectors start
|
||||
# at LBA -1, and consequently sector 63 is aligned on a 4KB boundary).
|
||||
# 1 enables; 0 disables.
|
||||
data_alignment_offset_detection = 1
|
||||
|
||||
# If, while scanning the system for PVs, LVM2 encounters a device-mapper
|
||||
# device that has its I/O suspended, it waits for it to become accessible.
|
||||
# Set this to 1 to skip such devices. This should only be needed
|
||||
@@ -123,7 +156,7 @@ log {
|
||||
# There are 6 syslog-like log levels currently in use - 2 to 7 inclusive.
|
||||
# 7 is the most verbose (LOG_DEBUG).
|
||||
level = 0
|
||||
|
||||
|
||||
# Format of output messages
|
||||
# Whether or not (1 or 0) to indent messages according to their severity
|
||||
indent = 1
|
||||
@@ -169,7 +202,7 @@ backup {
|
||||
# Where should archived files go ?
|
||||
# Remember to back up this directory regularly!
|
||||
archive_dir = "/etc/lvm/archive"
|
||||
|
||||
|
||||
# What is the minimum number of archive files you wish to keep ?
|
||||
retain_min = 10
|
||||
|
||||
@@ -187,7 +220,7 @@ shell {
|
||||
|
||||
# Miscellaneous global LVM2 settings
|
||||
global {
|
||||
|
||||
|
||||
# The file creation mask for any files and directories created.
|
||||
# Interpreted as octal if the first digit is zero.
|
||||
umask = 077
|
||||
@@ -235,6 +268,9 @@ global {
|
||||
# Type 3 uses built-in clustered locking.
|
||||
locking_type = 1
|
||||
|
||||
# Set to 0 to fail when a lock request cannot be satisfied immediately.
|
||||
wait_for_locks = 1
|
||||
|
||||
# If using external locking (type 2) and initialisation fails,
|
||||
# with this set to 1 an attempt will be made to use the built-in
|
||||
# clustered locking.
|
||||
@@ -265,11 +301,23 @@ global {
|
||||
}
|
||||
|
||||
activation {
|
||||
# Device used in place of missing stripes if activating incomplete volume.
|
||||
# For now, you need to set this up yourself first (e.g. with 'dmsetup')
|
||||
# For example, you could make it return I/O errors using the 'error'
|
||||
# target or make it return zeros.
|
||||
missing_stripe_filler = "/dev/ioerror"
|
||||
# Set to 0 to disable udev syncronisation (if compiled into the binaries).
|
||||
# Processes will not wait for notification from udev.
|
||||
# They will continue irrespective of any possible udev processing
|
||||
# in the background. You should only use this if udev is not running
|
||||
# or has rules that ignore the devices LVM2 creates.
|
||||
# The command line argument --nodevsync takes precedence over this setting.
|
||||
# If set to 1 when udev is not running, and there are LVM2 processes
|
||||
# waiting for udev, run 'dmsetup udevcomplete' manually to wake them up.
|
||||
udev_sync = 1
|
||||
|
||||
# How to fill in missing stripes if activating an incomplete volume.
|
||||
# Using "error" will make inaccessible parts of the device return
|
||||
# I/O errors on access. You can instead use a device path, in which
|
||||
# case, that device will be used to in place of missing stripes.
|
||||
# But note that using anything other than "error" with mirrored
|
||||
# or snapshotted volumes is likely to result in data corruption.
|
||||
missing_stripe_filler = "error"
|
||||
|
||||
# How much stack (in KB) to reserve for use while devices suspended
|
||||
reserved_stack = 256
|
||||
@@ -303,8 +351,10 @@ activation {
|
||||
# A disk log ensures that a mirror does not need to be re-synced
|
||||
# (all copies made the same) every time a machine reboots or crashes.
|
||||
#
|
||||
# In the event of a failure, the specified policy will be used to
|
||||
# determine what happens:
|
||||
# In the event of a failure, the specified policy will be used to determine
|
||||
# what happens. This applies to automatic repairs (when the mirror is being
|
||||
# monitored by dmeventd) and to manual lvconvert --repair when
|
||||
# --use-policies is given.
|
||||
#
|
||||
# "remove" - Simply remove the faulty device and run without it. If
|
||||
# the log device fails, the mirror would convert to using
|
||||
@@ -324,20 +374,13 @@ activation {
|
||||
# will preserve the mirror characteristic of the device.
|
||||
# This policy acts like "remove" if no suitable device and
|
||||
# space can be allocated for the replacement.
|
||||
# Currently this is not implemented properly and behaves
|
||||
# similarly to:
|
||||
#
|
||||
# "allocate_anywhere" - Operates like "allocate", but it does not
|
||||
# require that the new space being allocated be on a
|
||||
# device is not part of the mirror. For a log device
|
||||
# failure, this could mean that the log is allocated on
|
||||
# the same device as a mirror device. For a mirror
|
||||
# device, this could mean that the mirror device is
|
||||
# allocated on the same device as another mirror device.
|
||||
# This policy would not be wise for mirror devices
|
||||
# because it would break the redundant nature of the
|
||||
# mirror. This policy acts like "remove" if no suitable
|
||||
# device and space can be allocated for the replacement.
|
||||
# "allocate_anywhere" - Not yet implemented. Useful to place the log device
|
||||
# temporarily on same physical volume as one of the mirror
|
||||
# images. This policy is not recommended for mirror devices
|
||||
# since it would break the redundant nature of the mirror. This
|
||||
# policy acts like "remove" if no suitable device and space can
|
||||
# be allocated for the replacement.
|
||||
|
||||
mirror_log_fault_policy = "allocate"
|
||||
mirror_device_fault_policy = "remove"
|
||||
@@ -384,10 +427,20 @@ activation {
|
||||
# dmeventd {
|
||||
# mirror_library is the library used when monitoring a mirror device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2mirror.so" attempts to recover from failures.
|
||||
# It removes failed devices from a volume group and reconfigures a
|
||||
# mirror as necessary.
|
||||
#
|
||||
# "libdevmapper-event-lvm2mirror.so" attempts to recover from
|
||||
# failures. It removes failed devices from a volume group and
|
||||
# reconfigures a mirror as necessary. If no mirror library is
|
||||
# provided, mirrors are not monitored through dmeventd.
|
||||
|
||||
# mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||
|
||||
# snapshot_library is the library used when monitoring a snapshot device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2snapshot.so" monitors the filling of
|
||||
# snapshots and emits a warning through syslog, when the use of
|
||||
# snapshot exceedes 80%. The warning is repeated when 85%, 90% and
|
||||
# 95% of the snapshot are filled.
|
||||
|
||||
# snapshot_library = "libdevmapper-event-lvm2snapshot.so"
|
||||
#}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
#include "lvm2cmd.h"
|
||||
|
||||
/* All output gets passed to this function line-by-line */
|
||||
void test_log_fn(int level, const char *file, int line, const char *format)
|
||||
void test_log_fn(int level, int dm_errno, const char *file, int line,
|
||||
const char *format)
|
||||
{
|
||||
/* Extract and process output here rather than printing it */
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
../daemons/clvmd/clvm.h
|
||||
../daemons/dmeventd/libdevmapper-event.h
|
||||
../liblvm/lvm2app.h
|
||||
../lib/activate/activate.h
|
||||
../lib/activate/targets.h
|
||||
../lib/cache/lvmcache.h
|
||||
@@ -7,7 +9,6 @@
|
||||
../lib/config/config.h
|
||||
../lib/config/defaults.h
|
||||
../lib/datastruct/btree.h
|
||||
../lib/datastruct/list.h
|
||||
../lib/datastruct/lvm-types.h
|
||||
../lib/datastruct/str_list.h
|
||||
../lib/device/dev-cache.h
|
||||
@@ -28,6 +29,7 @@
|
||||
../lib/label/label.h
|
||||
../lib/locking/locking.h
|
||||
../lib/log/log.h
|
||||
../lib/log/lvm-logging.h
|
||||
../lib/metadata/lv_alloc.h
|
||||
../lib/metadata/metadata.h
|
||||
../lib/metadata/metadata-exported.h
|
||||
@@ -43,10 +45,16 @@
|
||||
../lib/misc/lib.h
|
||||
../lib/misc/lvm-exec.h
|
||||
../lib/misc/lvm-file.h
|
||||
../lib/misc/lvm-globals.h
|
||||
../lib/misc/lvm-string.h
|
||||
../lib/misc/lvm-version.h
|
||||
../lib/misc/lvm-wrappers.h
|
||||
../lib/misc/sharedlib.h
|
||||
../lib/report/report.h
|
||||
../lib/uuid/uuid.h
|
||||
../libdm/libdevmapper.h
|
||||
../libdm/misc/dm-ioctl.h
|
||||
../libdm/misc/dm-logging.h
|
||||
../libdm/misc/dmlib.h
|
||||
../libdm/misc/kdev_t.h
|
||||
../po/pogen.h
|
||||
../tools/version.h
|
||||
|
||||
@@ -20,7 +20,7 @@ VPATH = @srcdir@
|
||||
|
||||
LN_S = @LN_S@
|
||||
|
||||
.PHONY: clean distclean all install pofile install_cluster
|
||||
.PHONY: clean distclean all install pofile install_cluster install_device-mapper
|
||||
|
||||
all: .symlinks_created
|
||||
|
||||
@@ -35,11 +35,17 @@ distclean:
|
||||
|
||||
pofile: all
|
||||
|
||||
device-mapper: all
|
||||
|
||||
clean:
|
||||
|
||||
install:
|
||||
|
||||
install_cluster:
|
||||
|
||||
install_device-mapper:
|
||||
|
||||
install_lvm2:
|
||||
|
||||
cflow:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@@ -38,11 +38,11 @@ SOURCES =\
|
||||
commands/toolcontext.c \
|
||||
config/config.c \
|
||||
datastruct/btree.c \
|
||||
datastruct/list.c \
|
||||
datastruct/str_list.c \
|
||||
device/dev-cache.c \
|
||||
device/dev-io.c \
|
||||
device/dev-md.c \
|
||||
device/dev-swap.c \
|
||||
device/device.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
@@ -61,6 +61,7 @@ SOURCES =\
|
||||
format_text/import_vsn1.c \
|
||||
format_text/tags.c \
|
||||
format_text/text_label.c \
|
||||
freeseg/freeseg.c \
|
||||
label/label.c \
|
||||
locking/file_locking.c \
|
||||
locking/locking.c \
|
||||
@@ -77,6 +78,7 @@ SOURCES =\
|
||||
misc/crc.c \
|
||||
misc/lvm-exec.c \
|
||||
misc/lvm-file.c \
|
||||
misc/lvm-globals.c \
|
||||
misc/lvm-string.c \
|
||||
misc/lvm-wrappers.c \
|
||||
misc/timestamp.c \
|
||||
@@ -138,18 +140,19 @@ ifeq ("@DMEVENTD@", "yes")
|
||||
CLDFLAGS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
LIB_STATIC = liblvm.a
|
||||
LIB_NAME = liblvm-internal
|
||||
LIB_STATIC = $(LIB_NAME).a
|
||||
|
||||
$(SUBDIRS): $(LIB_STATIC)
|
||||
|
||||
CLEAN_TARGETS += liblvm.cflow
|
||||
CLEAN_TARGETS += $(LIB_NAME).cflow
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
liblvm.cflow: $(SOURCES)
|
||||
$(SUBDIRS): $(LIB_STATIC)
|
||||
|
||||
$(LIB_NAME).cflow: $(SOURCES)
|
||||
set -e; (echo -n "SOURCES += "; \
|
||||
echo $(SOURCES) | \
|
||||
sed "s/^/ /;s/ / $(top_srcdir)\/lib\//g;s/$$//"; \
|
||||
) > $@
|
||||
|
||||
cflow: liblvm.cflow
|
||||
cflow: $(LIB_NAME).cflow
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -52,11 +52,11 @@ int lvm1_present(struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
|
||||
struct list *modules)
|
||||
struct dm_list *modules)
|
||||
{
|
||||
unsigned int s;
|
||||
struct lv_segment *seg2, *snap_seg;
|
||||
struct list *snh;
|
||||
struct dm_list *snh;
|
||||
|
||||
if (seg->segtype->ops->modules_needed &&
|
||||
!seg->segtype->ops->modules_needed(mem, seg, modules)) {
|
||||
@@ -65,9 +65,9 @@ int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
|
||||
}
|
||||
|
||||
if (lv_is_origin(seg->lv))
|
||||
list_iterate(snh, &seg->lv->snapshot_segs)
|
||||
dm_list_iterate(snh, &seg->lv->snapshot_segs)
|
||||
if (!list_lv_modules(mem,
|
||||
list_struct_base(snh,
|
||||
dm_list_struct_base(snh,
|
||||
struct lv_segment,
|
||||
origin_list)->cow,
|
||||
modules))
|
||||
@@ -100,11 +100,11 @@ int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
|
||||
}
|
||||
|
||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
struct list *modules)
|
||||
struct dm_list *modules)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
|
||||
list_iterate_items(seg, &lv->segments)
|
||||
dm_list_iterate_items(seg, &lv->segments)
|
||||
if (!list_segment_modules(mem, seg, modules))
|
||||
return_0;
|
||||
|
||||
@@ -141,7 +141,8 @@ int target_version(const char *target_name, uint32_t *maj,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int target_present(const char *target_name, int use_modprobe)
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -264,7 +265,7 @@ static int _passes_activation_filter(struct cmd_context *cmd,
|
||||
|
||||
if (!(cn = find_config_tree_node(cmd, "activation/volume_list"))) {
|
||||
/* If no host tags defined, activate */
|
||||
if (list_empty(&cmd->tags))
|
||||
if (dm_list_empty(&cmd->tags))
|
||||
return 1;
|
||||
|
||||
/* If any host tag matches any LV or VG tag, activate */
|
||||
@@ -391,12 +392,32 @@ int target_version(const char *target_name, uint32_t *maj,
|
||||
return r;
|
||||
}
|
||||
|
||||
int target_present(const char *target_name, int use_modprobe)
|
||||
int module_present(struct cmd_context *cmd, const char *target_name)
|
||||
{
|
||||
uint32_t maj, min, patchlevel;
|
||||
int ret = 0;
|
||||
#ifdef MODPROBE_CMD
|
||||
char module[128];
|
||||
const char *argv[3];
|
||||
|
||||
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
|
||||
log_error("module_present module name too long: %s",
|
||||
target_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
argv[0] = MODPROBE_CMD;
|
||||
argv[1] = module;
|
||||
argv[2] = NULL;
|
||||
|
||||
ret = exec_cmd(cmd, argv);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe)
|
||||
{
|
||||
uint32_t maj, min, patchlevel;
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
@@ -406,14 +427,7 @@ int target_present(const char *target_name, int use_modprobe)
|
||||
if (target_version(target_name, &maj, &min, &patchlevel))
|
||||
return 1;
|
||||
|
||||
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name)
|
||||
< 0) {
|
||||
log_error("target_present module name too long: %s",
|
||||
target_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!exec_cmd(MODPROBE_CMD, module, "", ""))
|
||||
if (!module_present(cmd, target_name))
|
||||
return_0;
|
||||
}
|
||||
#endif
|
||||
@@ -508,6 +522,13 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct dev_manager *dm;
|
||||
struct lvinfo info;
|
||||
|
||||
/* If mirrored LV is temporarily shrinked to 1 area (= linear),
|
||||
* it should be considered in-sync. */
|
||||
if (dm_list_size(&lv->segments) == 1 && first_seg(lv)->area_count == 1) {
|
||||
*percent = 100.0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
@@ -568,7 +589,7 @@ static int _lv_activate_lv(struct logical_volume *lv)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _lv_preload(struct logical_volume *lv)
|
||||
static int _lv_preload(struct logical_volume *lv, int *flush_required)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -576,7 +597,7 @@ static int _lv_preload(struct logical_volume *lv)
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_preload(dm, lv)))
|
||||
if (!(r = dev_manager_preload(dm, lv, flush_required)))
|
||||
stack;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
@@ -598,7 +619,7 @@ static int _lv_deactivate(struct logical_volume *lv)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _lv_suspend_lv(struct logical_volume *lv, int lockfs)
|
||||
static int _lv_suspend_lv(struct logical_volume *lv, int lockfs, int flush_required)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -606,7 +627,7 @@ static int _lv_suspend_lv(struct logical_volume *lv, int lockfs)
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_suspend(dm, lv, lockfs)))
|
||||
if (!(r = dev_manager_suspend(dm, lv, lockfs, flush_required)))
|
||||
stack;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
@@ -625,8 +646,8 @@ static int _lvs_in_vg_activated(struct volume_group *vg, unsigned by_uuid_only)
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lvl->lv->status & VISIBLE_LV)
|
||||
dm_list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lv_is_visible(lvl->lv))
|
||||
count += (_lv_active(vg->cmd, lvl->lv, by_uuid_only) == 1);
|
||||
}
|
||||
|
||||
@@ -651,14 +672,49 @@ int lvs_in_vg_opened(const struct volume_group *vg)
|
||||
if (!activation())
|
||||
return 0;
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lvl->lv->status & VISIBLE_LV)
|
||||
dm_list_iterate_items(lvl, &vg->lvs) {
|
||||
if (lv_is_visible(lvl->lv))
|
||||
count += (_lv_open_count(vg->cmd, lvl->lv) > 0);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether an LV is active locally or in a cluster.
|
||||
* Assumes vg lock held.
|
||||
* Returns:
|
||||
* 0 - not active locally or on any node in cluster
|
||||
* 1 - active either locally or some node in the cluster
|
||||
*/
|
||||
int lv_is_active(struct logical_volume *lv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (_lv_active(lv->vg->cmd, lv, 0))
|
||||
return 1;
|
||||
|
||||
if (!vg_is_clustered(lv->vg))
|
||||
return 0;
|
||||
|
||||
if ((ret = remote_lock_held(lv->lvid.s)) >= 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Old compatibility code if locking doesn't support lock query
|
||||
* FIXME: check status to not deactivate already activate device
|
||||
*/
|
||||
if (activate_lv_excl(lv->vg->cmd, lv)) {
|
||||
deactivate_lv(lv->vg->cmd, lv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exclusive local activation failed so assume it is active elsewhere.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 if an attempt to (un)monitor the device failed.
|
||||
* Returns 1 otherwise.
|
||||
@@ -669,9 +725,10 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
#ifdef DMEVENTD
|
||||
int i, pending = 0, monitored;
|
||||
int r = 1;
|
||||
struct list *tmp;
|
||||
struct dm_list *tmp, *snh, *snht;
|
||||
struct lv_segment *seg;
|
||||
int (*monitor_fn) (struct lv_segment *s, int e);
|
||||
uint32_t s;
|
||||
|
||||
/* skip dmeventd code altogether */
|
||||
if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
|
||||
@@ -683,8 +740,43 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
if (monitor && !dmeventd_monitor_mode())
|
||||
return 1;
|
||||
|
||||
list_iterate(tmp, &lv->segments) {
|
||||
seg = list_item(tmp, struct lv_segment);
|
||||
/*
|
||||
* In case of a snapshot device, we monitor lv->snapshot->lv,
|
||||
* not the actual LV itself.
|
||||
*/
|
||||
if (lv_is_cow(lv))
|
||||
return monitor_dev_for_events(cmd, lv->snapshot->lv, monitor);
|
||||
|
||||
/*
|
||||
* In case this LV is a snapshot origin, we instead monitor
|
||||
* each of its respective snapshots (the origin itself does
|
||||
* not need to be monitored).
|
||||
*
|
||||
* TODO: This may change when snapshots of mirrors are allowed.
|
||||
*/
|
||||
if (lv_is_origin(lv)) {
|
||||
dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
||||
if (!monitor_dev_for_events(cmd, dm_list_struct_base(snh,
|
||||
struct lv_segment, origin_list)->cow, monitor))
|
||||
r = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
dm_list_iterate(tmp, &lv->segments) {
|
||||
seg = dm_list_item(tmp, struct lv_segment);
|
||||
|
||||
/* Recurse for AREA_LV */
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
if (seg_type(seg, s) != AREA_LV)
|
||||
continue;
|
||||
if (!monitor_dev_for_events(cmd, seg_lv(seg, s),
|
||||
monitor)) {
|
||||
log_error("Failed to %smonitor %s",
|
||||
monitor ? "" : "un",
|
||||
seg_lv(seg, s)->name);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!seg_monitored(seg) || (seg->status & PVMOVE))
|
||||
continue;
|
||||
@@ -754,36 +846,41 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
int error_if_not_suspended)
|
||||
{
|
||||
struct logical_volume *lv, *lv_pre;
|
||||
struct logical_volume *lv = NULL, *lv_pre = NULL;
|
||||
struct lvinfo info;
|
||||
int lockfs = 0;
|
||||
int r = 0, lockfs = 0, flush_required = 0;
|
||||
|
||||
if (!activation())
|
||||
return 1;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
return_0;
|
||||
goto_out;
|
||||
|
||||
/* Use precommitted metadata if present */
|
||||
if (!(lv_pre = lv_from_lvid(cmd, lvid_s, 1)))
|
||||
return_0;
|
||||
goto_out;
|
||||
|
||||
if (test_mode()) {
|
||||
_skip("Suspending '%s'.", lv->name);
|
||||
return 1;
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0, 0))
|
||||
return_0;
|
||||
goto_out;
|
||||
|
||||
if (!info.exists || info.suspended)
|
||||
return error_if_not_suspended ? 0 : 1;
|
||||
if (!info.exists || info.suspended) {
|
||||
r = error_if_not_suspended ? 0 : 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lv_calculate_readahead(lv, NULL);
|
||||
|
||||
/* If VG was precommitted, preload devices for the LV */
|
||||
if ((lv_pre->vg->status & PRECOMMITTED)) {
|
||||
if (!_lv_preload(lv_pre)) {
|
||||
if (!_lv_preload(lv_pre, &flush_required)) {
|
||||
/* FIXME Revert preloading */
|
||||
return_0;
|
||||
goto_out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,13 +893,20 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
if (lv_is_origin(lv_pre) || lv_is_cow(lv_pre))
|
||||
lockfs = 1;
|
||||
|
||||
if (!_lv_suspend_lv(lv, lockfs)) {
|
||||
if (!_lv_suspend_lv(lv, lockfs, flush_required)) {
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 1;
|
||||
r = 1;
|
||||
out:
|
||||
if (lv_pre)
|
||||
vg_release(lv_pre->vg);
|
||||
if (lv)
|
||||
vg_release(lv->vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Returns success if the device is not active */
|
||||
@@ -821,26 +925,30 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
int r = 0;
|
||||
|
||||
if (!activation())
|
||||
return 1;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
if (test_mode()) {
|
||||
_skip("Resuming '%s'.", lv->name);
|
||||
return 1;
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0, 0))
|
||||
return_0;
|
||||
goto_out;
|
||||
|
||||
if (!info.exists || !info.suspended)
|
||||
return error_if_not_active ? 0 : 1;
|
||||
if (!info.exists || !info.suspended) {
|
||||
r = error_if_not_active ? 0 : 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_lv_activate_lv(lv))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
@@ -848,7 +956,12 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
||||
if (!monitor_dev_for_events(cmd, lv, 1))
|
||||
stack;
|
||||
|
||||
return 1;
|
||||
r = 1;
|
||||
out:
|
||||
if (lv)
|
||||
vg_release(lv->vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Returns success if the device is not active */
|
||||
@@ -866,31 +979,36 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
int r;
|
||||
int r = 0;
|
||||
|
||||
if (!activation())
|
||||
return 1;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
if (test_mode()) {
|
||||
_skip("Deactivating '%s'.", lv->name);
|
||||
return 1;
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 1, 0))
|
||||
return_0;
|
||||
goto_out;
|
||||
|
||||
if (!info.exists)
|
||||
return 1;
|
||||
if (!info.exists) {
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (info.open_count && (lv->status & VISIBLE_LV)) {
|
||||
if (info.open_count && lv_is_visible(lv)) {
|
||||
log_error("LV %s/%s in use: not deactivating", lv->vg->name,
|
||||
lv->name);
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lv_calculate_readahead(lv, NULL);
|
||||
|
||||
if (!monitor_dev_for_events(cmd, lv, 0))
|
||||
stack;
|
||||
|
||||
@@ -899,6 +1017,10 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
out:
|
||||
if (lv)
|
||||
vg_release(lv->vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -907,23 +1029,28 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
int *activate_lv)
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
int r = 0;
|
||||
|
||||
if (!activation())
|
||||
goto activate;
|
||||
if (!activation()) {
|
||||
*activate_lv = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
if (!_passes_activation_filter(cmd, lv)) {
|
||||
log_verbose("Not activating %s/%s due to config file settings",
|
||||
lv->vg->name, lv->name);
|
||||
*activate_lv = 0;
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
*activate_lv = 1;
|
||||
r = 1;
|
||||
out:
|
||||
if (lv)
|
||||
vg_release(lv->vg);
|
||||
|
||||
activate:
|
||||
*activate_lv = 1;
|
||||
return 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
@@ -931,30 +1058,41 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
{
|
||||
struct logical_volume *lv;
|
||||
struct lvinfo info;
|
||||
int r;
|
||||
int r = 0;
|
||||
|
||||
if (!activation())
|
||||
return 1;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
if (filter && !_passes_activation_filter(cmd, lv)) {
|
||||
log_verbose("Not activating %s/%s due to config file settings",
|
||||
lv->vg->name, lv->name);
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((!lv->vg->cmd->partial_activation) && (lv->status & PARTIAL_LV)) {
|
||||
log_error("Refusing activation of partial LV %s. Use --partial to override.",
|
||||
lv->name);
|
||||
goto_out;
|
||||
}
|
||||
|
||||
if (test_mode()) {
|
||||
_skip("Activating '%s'.", lv->name);
|
||||
return 1;
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 0, 0))
|
||||
return_0;
|
||||
goto_out;
|
||||
|
||||
if (info.exists && !info.suspended && info.live_table)
|
||||
return 1;
|
||||
if (info.exists && !info.suspended && info.live_table) {
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lv_calculate_readahead(lv, NULL);
|
||||
|
||||
if (exclusive)
|
||||
lv->status |= ACTIVATE_EXCL;
|
||||
@@ -967,6 +1105,10 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||
if (r && !monitor_dev_for_events(cmd, lv, 1))
|
||||
stack;
|
||||
|
||||
out:
|
||||
if (lv)
|
||||
vg_release(lv->vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -996,9 +1138,10 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
if (!_lv_info(cmd, lv, 1, &info, 0, 0, 0))
|
||||
return_0;
|
||||
|
||||
if (info.exists)
|
||||
r = dev_manager_lv_mknodes(lv);
|
||||
else
|
||||
if (info.exists) {
|
||||
if (lv_is_visible(lv))
|
||||
r = dev_manager_lv_mknodes(lv);
|
||||
} else
|
||||
r = dev_manager_lv_rmnodes(lv);
|
||||
|
||||
fs_unlock();
|
||||
|
||||
@@ -30,6 +30,9 @@ struct lvinfo {
|
||||
uint32_t read_ahead;
|
||||
};
|
||||
|
||||
/* target attribute flags */
|
||||
#define MIRROR_LOG_CLUSTERED 0x00000001U
|
||||
|
||||
void set_activation(int activation);
|
||||
int activation(void);
|
||||
|
||||
@@ -37,13 +40,15 @@ int driver_version(char *version, size_t size);
|
||||
int library_version(char *version, size_t size);
|
||||
int lvm1_present(struct cmd_context *cmd);
|
||||
|
||||
int target_present(const char *target_name, int use_modprobe);
|
||||
int module_present(struct cmd_context *cmd, const char *target_name);
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe);
|
||||
int target_version(const char *target_name, uint32_t *maj,
|
||||
uint32_t *min, uint32_t *patchlevel);
|
||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
|
||||
struct list *modules);
|
||||
struct dm_list *modules);
|
||||
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
struct list *modules);
|
||||
struct dm_list *modules);
|
||||
|
||||
void activation_release(void);
|
||||
void activation_exit(void);
|
||||
@@ -87,6 +92,7 @@ int lvs_in_vg_activated(struct volume_group *vg);
|
||||
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
|
||||
int lvs_in_vg_opened(const struct volume_group *vg);
|
||||
|
||||
int lv_is_active(struct logical_volume *lv);
|
||||
|
||||
int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
struct logical_volume *lv, int do_reg);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -47,9 +47,9 @@ struct dev_manager {
|
||||
|
||||
struct cmd_context *cmd;
|
||||
|
||||
const char *stripe_filler;
|
||||
void *target_state;
|
||||
uint32_t pvmove_mirror_count;
|
||||
int flush_required;
|
||||
|
||||
char *vg_name;
|
||||
};
|
||||
@@ -59,8 +59,6 @@ struct lv_layer {
|
||||
const char *old_name;
|
||||
};
|
||||
|
||||
static const char *stripe_filler = NULL;
|
||||
|
||||
static char *_build_dlid(struct dm_pool *mem, const char *lvid, const char *layer)
|
||||
{
|
||||
char *dlid;
|
||||
@@ -96,14 +94,13 @@ static int _read_only_lv(struct logical_volume *lv)
|
||||
* Low level device-layer operations.
|
||||
*/
|
||||
static struct dm_task *_setup_task(const char *name, const char *uuid,
|
||||
uint32_t *event_nr, int task)
|
||||
uint32_t *event_nr, int task,
|
||||
uint32_t major, uint32_t minor)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
|
||||
if (!(dmt = dm_task_create(task))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(dmt = dm_task_create(task)))
|
||||
return_NULL;
|
||||
|
||||
if (name)
|
||||
dm_task_set_name(dmt, name);
|
||||
@@ -114,12 +111,15 @@ static struct dm_task *_setup_task(const char *name, const char *uuid,
|
||||
if (event_nr)
|
||||
dm_task_set_event_nr(dmt, *event_nr);
|
||||
|
||||
if (major)
|
||||
dm_task_set_major_minor(dmt, major, minor, 1);
|
||||
|
||||
return dmt;
|
||||
}
|
||||
|
||||
static int _info_run(const char *name, const char *dlid, struct dm_info *info,
|
||||
uint32_t *read_ahead, int mknodes, int with_open_count,
|
||||
int with_read_ahead)
|
||||
int with_read_ahead, uint32_t major, uint32_t minor)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
@@ -127,10 +127,8 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
|
||||
|
||||
dmtask = mknodes ? DM_DEVICE_MKNODES : DM_DEVICE_INFO;
|
||||
|
||||
if (!(dmt = _setup_task(name, dlid, 0, dmtask))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dmt = _setup_task(name, dlid, 0, dmtask, major, minor)))
|
||||
return_0;
|
||||
|
||||
if (!with_open_count)
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
@@ -142,7 +140,7 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
|
||||
if (!dm_task_get_info(dmt, info))
|
||||
goto_out;
|
||||
|
||||
if (with_read_ahead) {
|
||||
if (with_read_ahead && info->exists) {
|
||||
if (!dm_task_get_read_ahead(dmt, read_ahead))
|
||||
goto_out;
|
||||
} else if (read_ahead)
|
||||
@@ -160,9 +158,9 @@ int device_is_usable(dev_t dev)
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
const char *name;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
void *next = NULL;
|
||||
int r = 0;
|
||||
|
||||
@@ -171,7 +169,7 @@ int device_is_usable(dev_t dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev)))
|
||||
if (!dm_task_set_major_minor(dmt, MAJOR(dev), MINOR(dev), 1))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_run(dmt)) {
|
||||
@@ -190,13 +188,13 @@ int device_is_usable(dev_t dev)
|
||||
/* FIXME Also check for mirror block_on_error and mpath no paths */
|
||||
/* For now, we exclude all mirrors */
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
/* Skip if target type doesn't match */
|
||||
if (target_type && !strcmp(target_type, "mirror"))
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
/* Skip if target type doesn't match */
|
||||
if (target_type && !strcmp(target_type, "mirror"))
|
||||
goto out;
|
||||
} while (next);
|
||||
} while (next);
|
||||
|
||||
/* FIXME Also check dependencies? */
|
||||
|
||||
@@ -213,23 +211,28 @@ static int _info(const char *name, const char *dlid, int mknodes,
|
||||
{
|
||||
if (!mknodes && dlid && *dlid) {
|
||||
if (_info_run(NULL, dlid, info, read_ahead, 0, with_open_count,
|
||||
with_read_ahead) &&
|
||||
with_read_ahead, 0, 0) &&
|
||||
info->exists)
|
||||
return 1;
|
||||
else if (_info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
|
||||
read_ahead, 0, with_open_count,
|
||||
with_read_ahead) &&
|
||||
with_read_ahead, 0, 0) &&
|
||||
info->exists)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (name)
|
||||
return _info_run(name, NULL, info, read_ahead, mknodes,
|
||||
with_open_count, with_read_ahead);
|
||||
with_open_count, with_read_ahead, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _info_by_dev(uint32_t major, uint32_t minor, struct dm_info *info)
|
||||
{
|
||||
return _info_run(NULL, NULL, info, NULL, 0, 0, 0, major, minor);
|
||||
}
|
||||
|
||||
int dev_manager_info(struct dm_pool *mem, const char *name,
|
||||
const struct logical_volume *lv, int with_mknodes,
|
||||
int with_open_count, int with_read_ahead,
|
||||
@@ -259,10 +262,8 @@ static int _status_run(const char *name, const char *uuid,
|
||||
char *type = NULL;
|
||||
char *params = NULL;
|
||||
|
||||
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
@@ -339,7 +340,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
uint64_t start, length;
|
||||
char *type = NULL;
|
||||
char *params = NULL;
|
||||
struct list *segh = &lv->segments;
|
||||
struct dm_list *segh = &lv->segments;
|
||||
struct lv_segment *seg = NULL;
|
||||
struct segment_type *segtype;
|
||||
|
||||
@@ -348,10 +349,8 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
*percent = -1;
|
||||
|
||||
if (!(dmt = _setup_task(name, dlid, event_nr,
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
@@ -369,12 +368,12 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
next = dm_get_next_target(dmt, next, &start, &length, &type,
|
||||
¶ms);
|
||||
if (lv) {
|
||||
if (!(segh = list_next(&lv->segments, segh))) {
|
||||
if (!(segh = dm_list_next(&lv->segments, segh))) {
|
||||
log_error("Number of segments in active LV %s "
|
||||
"does not match metadata", lv->name);
|
||||
goto out;
|
||||
}
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
seg = dm_list_item(segh, struct lv_segment);
|
||||
}
|
||||
|
||||
if (!type || !params || strcmp(type, target_type))
|
||||
@@ -387,13 +386,12 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
!segtype->ops->target_percent(&dm->target_state, dm->mem,
|
||||
dm->cmd, seg, params,
|
||||
&total_numerator,
|
||||
&total_denominator,
|
||||
percent))
|
||||
&total_denominator))
|
||||
goto_out;
|
||||
|
||||
} while (next);
|
||||
|
||||
if (lv && (segh = list_next(&lv->segments, segh))) {
|
||||
if (lv && (segh = dm_list_next(&lv->segments, segh))) {
|
||||
log_error("Number of segments in active LV %s does not "
|
||||
"match metadata", lv->name);
|
||||
goto out;
|
||||
@@ -401,7 +399,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
|
||||
if (total_denominator)
|
||||
*percent = (float) total_numerator *100 / total_denominator;
|
||||
else if (*percent < 0)
|
||||
else
|
||||
*percent = 100;
|
||||
|
||||
log_debug("LV percent: %f", *percent);
|
||||
@@ -443,29 +441,22 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||
struct dm_pool *mem;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!(mem = dm_pool_create("dev_manager", 16 * 1024))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(mem = dm_pool_create("dev_manager", 16 * 1024)))
|
||||
return_NULL;
|
||||
|
||||
if (!(dm = dm_pool_alloc(mem, sizeof(*dm))))
|
||||
if (!(dm = dm_pool_zalloc(mem, sizeof(*dm))))
|
||||
goto_bad;
|
||||
|
||||
dm->cmd = cmd;
|
||||
dm->mem = mem;
|
||||
|
||||
if (!stripe_filler) {
|
||||
stripe_filler = find_config_tree_str(cmd,
|
||||
"activation/missing_stripe_filler",
|
||||
DEFAULT_STRIPE_FILLER);
|
||||
}
|
||||
dm->stripe_filler = stripe_filler;
|
||||
|
||||
if (!(dm->vg_name = dm_pool_strdup(dm->mem, vg_name)))
|
||||
goto_bad;
|
||||
|
||||
dm->target_state = NULL;
|
||||
|
||||
dm_udev_set_sync_support(cmd->current_settings.udev_sync);
|
||||
|
||||
return dm;
|
||||
|
||||
bad:
|
||||
@@ -509,10 +500,8 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
*/
|
||||
log_debug("Getting device status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
|
||||
NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
NULL)))
|
||||
return_0;
|
||||
|
||||
/* FIXME dm_pool_free ? */
|
||||
|
||||
@@ -544,10 +533,8 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
|
||||
log_debug("Getting device mirror status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
|
||||
event_nr))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
event_nr)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -601,7 +588,7 @@ static int _belong_to_vg(const char *vgname, const char *name)
|
||||
old_origin = snap_seg->origin;
|
||||
|
||||
/* Was this the last active snapshot with this origin? */
|
||||
list_iterate_items(lvl, active_head) {
|
||||
dm_list_iterate_items(lvl, active_head) {
|
||||
active = lvl->lv;
|
||||
if ((snap_seg = find_cow(active)) &&
|
||||
snap_seg->origin == old_origin) {
|
||||
@@ -635,7 +622,7 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
struct logical_volume *lv, const char *layer)
|
||||
{
|
||||
char *dlid, *name;
|
||||
struct dm_info info;
|
||||
struct dm_info info, info2;
|
||||
|
||||
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
|
||||
return_0;
|
||||
@@ -643,11 +630,35 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
|
||||
return_0;
|
||||
|
||||
log_debug("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(name, dlid, 0, 1, 0, &info, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
log_debug("Getting device info for %s [%s]", name, dlid);
|
||||
if (!_info(name, dlid, 0, 1, 0, &info, NULL)) {
|
||||
log_error("Failed to get info for %s [%s].", name, dlid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For top level volumes verify that existing device match
|
||||
* requested major/minor and that major/minor pair is available for use
|
||||
*/
|
||||
if (!layer && lv->major != -1 && lv->minor != -1) {
|
||||
/*
|
||||
* FIXME compare info.major with lv->major if multiple major support
|
||||
*/
|
||||
if (info.exists && (info.minor != lv->minor)) {
|
||||
log_error("Volume %s (%" PRIu32 ":%" PRIu32")"
|
||||
" differs from already active device "
|
||||
"(%" PRIu32 ":%" PRIu32")",
|
||||
lv->name, lv->major, lv->minor, info.major, info.minor);
|
||||
return 0;
|
||||
}
|
||||
if (!info.exists && _info_by_dev(lv->major, lv->minor, &info2) &&
|
||||
info2.exists) {
|
||||
log_error("The requested major:minor pair "
|
||||
"(%" PRIu32 ":%" PRIu32") is already used",
|
||||
lv->major, lv->minor);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (info.exists && !dm_tree_add_dev(dtree, info.major, info.minor)) {
|
||||
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
|
||||
@@ -682,7 +693,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree, struc
|
||||
static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logical_volume *lv)
|
||||
{
|
||||
struct dm_tree *dtree;
|
||||
struct list *snh, *snht;
|
||||
struct dm_list *snh, *snht;
|
||||
struct lv_segment *seg;
|
||||
uint32_t s;
|
||||
|
||||
@@ -691,35 +702,91 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_add_lv_to_dtree(dm, dtree, lv)) {
|
||||
stack;
|
||||
goto fail;
|
||||
}
|
||||
if (!_add_lv_to_dtree(dm, dtree, lv))
|
||||
goto_bad;
|
||||
|
||||
/* Add any snapshots of this LV */
|
||||
list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
||||
if (!_add_lv_to_dtree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow)) {
|
||||
stack;
|
||||
goto fail;
|
||||
}
|
||||
dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
||||
if (!_add_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow))
|
||||
goto_bad;
|
||||
|
||||
/* Add any LVs used by segments in this LV */
|
||||
list_iterate_items(seg, &lv->segments)
|
||||
dm_list_iterate_items(seg, &lv->segments)
|
||||
for (s = 0; s < seg->area_count; s++)
|
||||
if (seg_type(seg, s) == AREA_LV && seg_lv(seg, s)) {
|
||||
if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s))) {
|
||||
stack;
|
||||
goto fail;
|
||||
}
|
||||
if (!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s)))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
return dtree;
|
||||
|
||||
fail:
|
||||
bad:
|
||||
dm_tree_free(dtree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
struct lv_segment *seg, int s)
|
||||
{
|
||||
char *id, *name;
|
||||
char errid[32];
|
||||
struct dm_tree_node *node;
|
||||
struct lv_segment *seg_i;
|
||||
int segno = -1, i = 0;;
|
||||
uint64_t size = seg->len * seg->lv->vg->extent_size;
|
||||
|
||||
dm_list_iterate_items(seg_i, &seg->lv->segments) {
|
||||
if (seg == seg_i)
|
||||
segno = i;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (segno < 0) {
|
||||
log_error("_add_error_device called with bad segment");
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
sprintf(errid, "missing_%d_%d", segno, s);
|
||||
|
||||
if (!(id = build_dlid(dm, seg->lv->lvid.s, errid)))
|
||||
return_NULL;
|
||||
|
||||
if (!(name = build_dm_name(dm->mem, seg->lv->vg->name,
|
||||
seg->lv->name, errid)))
|
||||
return_NULL;
|
||||
if (!(node = dm_tree_add_new_dev(dtree, name, id, 0, 0, 0, 0, 0)))
|
||||
return_NULL;
|
||||
if (!dm_tree_node_add_error_target(node, size))
|
||||
return_NULL;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static int _add_error_area(struct dev_manager *dm, struct dm_tree_node *node,
|
||||
struct lv_segment *seg, int s)
|
||||
{
|
||||
char *dlid;
|
||||
uint64_t extent_size = seg->lv->vg->extent_size;
|
||||
|
||||
if (!strcmp(dm->cmd->stripe_filler, "error")) {
|
||||
/*
|
||||
* FIXME, the tree pointer is first field of dm_tree_node, but
|
||||
* we don't have the struct definition available.
|
||||
*/
|
||||
struct dm_tree **tree = (struct dm_tree **) node;
|
||||
dlid = _add_error_device(dm, *tree, seg, s);
|
||||
if (!dlid)
|
||||
return_0;
|
||||
dm_tree_node_add_target_area(node, NULL, dlid,
|
||||
extent_size * seg_le(seg, s));
|
||||
} else
|
||||
dm_tree_node_add_target_area(node,
|
||||
dm->cmd->stripe_filler,
|
||||
NULL, UINT64_C(0));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
struct dm_tree_node *node, uint32_t start_area,
|
||||
uint32_t areas)
|
||||
@@ -733,11 +800,10 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
(!seg_pvseg(seg, s) ||
|
||||
!seg_pv(seg, s) ||
|
||||
!seg_dev(seg, s))) ||
|
||||
(seg_type(seg, s) == AREA_LV && !seg_lv(seg, s)))
|
||||
dm_tree_node_add_target_area(node,
|
||||
dm->stripe_filler,
|
||||
NULL, UINT64_C(0));
|
||||
else if (seg_type(seg, s) == AREA_PV)
|
||||
(seg_type(seg, s) == AREA_LV && !seg_lv(seg, s))) {
|
||||
if (!_add_error_area(dm, node, seg, s))
|
||||
return_0;
|
||||
} else if (seg_type(seg, s) == AREA_PV)
|
||||
dm_tree_node_add_target_area(node,
|
||||
dev_name(seg_dev(seg, s)),
|
||||
NULL,
|
||||
@@ -832,7 +898,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
const char *layer)
|
||||
{
|
||||
uint32_t s;
|
||||
struct list *snh;
|
||||
struct dm_list *snh;
|
||||
struct lv_segment *seg_present;
|
||||
|
||||
/* Ensure required device-mapper targets are loaded */
|
||||
@@ -843,7 +909,8 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
layer ? "-" : "", layer ? : "");
|
||||
|
||||
if (seg_present->segtype->ops->target_present &&
|
||||
!seg_present->segtype->ops->target_present(seg_present)) {
|
||||
!seg_present->segtype->ops->target_present(seg_present->lv->vg->cmd,
|
||||
seg_present, NULL)) {
|
||||
log_error("Can't expand LV %s: %s target support missing "
|
||||
"from kernel?", seg->lv->name, seg_present->segtype->name);
|
||||
return 0;
|
||||
@@ -856,7 +923,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
|
||||
/* If this is a snapshot origin, add real LV */
|
||||
if (lv_is_origin(seg->lv) && !layer) {
|
||||
if (seg->lv->vg->status & CLUSTERED) {
|
||||
if (vg_is_clustered(seg->lv->vg)) {
|
||||
log_error("Clustered snapshots are not yet supported");
|
||||
return 0;
|
||||
}
|
||||
@@ -885,8 +952,8 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
|
||||
if (lv_is_origin(seg->lv) && !layer)
|
||||
/* Add any snapshots of this LV */
|
||||
list_iterate(snh, &seg->lv->snapshot_segs)
|
||||
if (!_add_new_lv_to_dtree(dm, dtree, list_struct_base(snh, struct lv_segment, origin_list)->cow, NULL))
|
||||
dm_list_iterate(snh, &seg->lv->snapshot_segs)
|
||||
if (!_add_new_lv_to_dtree(dm, dtree, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow, NULL))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
@@ -940,7 +1007,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
|
||||
/* Create table */
|
||||
dm->pvmove_mirror_count = 0u;
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
dm_list_iterate_items(seg, &lv->segments) {
|
||||
if (!_add_segment_to_dtree(dm, dtree, dnode, seg, layer))
|
||||
return_0;
|
||||
/* These aren't real segments in the LVM2 metadata */
|
||||
@@ -948,14 +1015,17 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
break;
|
||||
if (lv_is_cow(lv) && !layer)
|
||||
break;
|
||||
if (max_stripe_size < seg->stripe_size)
|
||||
max_stripe_size = seg->stripe_size;
|
||||
if (max_stripe_size < seg->stripe_size * seg->area_count)
|
||||
max_stripe_size = seg->stripe_size * seg->area_count;
|
||||
}
|
||||
|
||||
if (read_ahead == DM_READ_AHEAD_AUTO)
|
||||
read_ahead = max_stripe_size;
|
||||
else
|
||||
if (read_ahead == DM_READ_AHEAD_AUTO) {
|
||||
/* we need RA at least twice a whole stripe - see the comment in md/raid0.c */
|
||||
read_ahead = max_stripe_size * 2;
|
||||
if (!read_ahead)
|
||||
lv_calculate_readahead(lv, &read_ahead);
|
||||
read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG;
|
||||
}
|
||||
|
||||
dm_tree_node_set_read_ahead(dnode, read_ahead, read_ahead_flags);
|
||||
|
||||
@@ -974,7 +1044,8 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
void *handle = NULL;
|
||||
struct dm_tree_node *child;
|
||||
struct lv_layer *lvlayer;
|
||||
char *vgname, *lvname, *layer;
|
||||
char *old_vgname, *old_lvname, *old_layer;
|
||||
char *new_vgname, *new_lvname, *new_layer;
|
||||
const char *name;
|
||||
int r = 1;
|
||||
|
||||
@@ -986,12 +1057,24 @@ static int _create_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
name = dm_tree_node_get_name(child);
|
||||
|
||||
if (name && lvlayer->old_name && *lvlayer->old_name && strcmp(name, lvlayer->old_name)) {
|
||||
if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &vgname, &lvname, &layer)) {
|
||||
log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
|
||||
return 0;
|
||||
}
|
||||
fs_rename_lv(lvlayer->lv, name, lvname);
|
||||
} else if (!dev_manager_lv_mknodes(lvlayer->lv))
|
||||
if (!dm_split_lvm_name(dm->mem, lvlayer->old_name, &old_vgname, &old_lvname, &old_layer)) {
|
||||
log_error("_create_lv_symlinks: Couldn't split up old device name %s", lvlayer->old_name);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_split_lvm_name(dm->mem, name, &new_vgname, &new_lvname, &new_layer)) {
|
||||
log_error("_create_lv_symlinks: Couldn't split up new device name %s", name);
|
||||
return 0;
|
||||
}
|
||||
if (!fs_rename_lv(lvlayer->lv, name, old_vgname, old_lvname))
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
if (lv_is_visible(lvlayer->lv)) {
|
||||
if (!dev_manager_lv_mknodes(lvlayer->lv))
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
if (!dev_manager_lv_rmnodes(lvlayer->lv))
|
||||
r = 0;
|
||||
}
|
||||
|
||||
@@ -1009,11 +1092,14 @@ static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
int r = 1;
|
||||
|
||||
while ((child = dm_tree_next_child(&handle, root, 0))) {
|
||||
if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
|
||||
if (!dm_split_lvm_name(dm->mem, dm_tree_node_get_name(child), &vgname, &lvname, &layer)) {
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!*vgname)
|
||||
continue;
|
||||
|
||||
/* only top level layer has symlinks */
|
||||
if (*layer)
|
||||
continue;
|
||||
@@ -1030,6 +1116,7 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
|
||||
struct dm_tree_node *child;
|
||||
char *vgname, *lvname, *layer;
|
||||
const char *name, *uuid;
|
||||
int r;
|
||||
|
||||
while ((child = dm_tree_next_child(&handle, root, 0))) {
|
||||
if (!(name = dm_tree_node_get_name(child)))
|
||||
@@ -1038,16 +1125,21 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
|
||||
if (!(uuid = dm_tree_node_get_uuid(child)))
|
||||
continue;
|
||||
|
||||
if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
|
||||
log_error("_clean_tree: Couldn't split up device name %s.", name);
|
||||
return 0;
|
||||
}
|
||||
if (!dm_split_lvm_name(dm->mem, name, &vgname, &lvname, &layer)) {
|
||||
log_error("_clean_tree: Couldn't split up device name %s.", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Not meant to be top level? */
|
||||
if (!*layer)
|
||||
continue;
|
||||
|
||||
if (!dm_tree_deactivate_children(root, uuid, strlen(uuid)))
|
||||
dm_tree_set_cookie(root, 0);
|
||||
r = dm_tree_deactivate_children(root, uuid, strlen(uuid));
|
||||
if (!dm_udev_wait(dm_tree_get_cookie(root)))
|
||||
stack;
|
||||
|
||||
if (!r)
|
||||
return_0;
|
||||
}
|
||||
|
||||
@@ -1081,14 +1173,18 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
|
||||
break;
|
||||
case DEACTIVATE:
|
||||
/* Deactivate LV and all devices it references that nothing else has open. */
|
||||
if (!dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
|
||||
dm_tree_set_cookie(root, 0);
|
||||
r = dm_tree_deactivate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1);
|
||||
if (!dm_udev_wait(dm_tree_get_cookie(root)))
|
||||
stack;
|
||||
if (!r)
|
||||
goto_out;
|
||||
if (!_remove_lv_symlinks(dm, root))
|
||||
log_error("Failed to remove all device symlinks associated with %s.", lv->name);
|
||||
break;
|
||||
case SUSPEND:
|
||||
dm_tree_skip_lockfs(root);
|
||||
if ((lv->status & MIRRORED) && !(lv->status & PVMOVE))
|
||||
if (!dm->flush_required && (lv->status & MIRRORED) && !(lv->status & PVMOVE))
|
||||
dm_tree_use_no_flush_suspend(root);
|
||||
case SUSPEND_WITH_LOCKFS:
|
||||
if (!dm_tree_suspend_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
|
||||
@@ -1101,17 +1197,29 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv, actio
|
||||
goto_out;
|
||||
|
||||
/* Preload any devices required before any suspensions */
|
||||
if (!dm_tree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
|
||||
dm_tree_set_cookie(root, 0);
|
||||
r = dm_tree_preload_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1);
|
||||
if (!dm_udev_wait(dm_tree_get_cookie(root)))
|
||||
stack;
|
||||
if (!r)
|
||||
goto_out;
|
||||
|
||||
if ((action == ACTIVATE) &&
|
||||
!dm_tree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1))
|
||||
goto_out;
|
||||
if (dm_tree_node_size_changed(root))
|
||||
dm->flush_required = 1;
|
||||
|
||||
if (!_create_lv_symlinks(dm, root)) {
|
||||
log_error("Failed to create symlinks for %s.", lv->name);
|
||||
goto out;
|
||||
if (action == ACTIVATE) {
|
||||
dm_tree_set_cookie(root, 0);
|
||||
r = dm_tree_activate_children(root, dlid, ID_LEN + sizeof(UUID_PREFIX) - 1);
|
||||
if (!dm_udev_wait(dm_tree_get_cookie(root)))
|
||||
stack;
|
||||
if (!r)
|
||||
goto_out;
|
||||
if (!_create_lv_symlinks(dm, root)) {
|
||||
log_error("Failed to create symlinks for %s.", lv->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
log_error("_tree_action: Action %u not supported.", action);
|
||||
@@ -1134,13 +1242,19 @@ int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
|
||||
return _tree_action(dm, lv, CLEAN);
|
||||
}
|
||||
|
||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv)
|
||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv,
|
||||
int *flush_required)
|
||||
{
|
||||
/* FIXME Update the pvmove implementation! */
|
||||
if ((lv->status & PVMOVE) || (lv->status & LOCKED))
|
||||
return 1;
|
||||
|
||||
return _tree_action(dm, lv, PRELOAD);
|
||||
if (!_tree_action(dm, lv, PRELOAD))
|
||||
return 0;
|
||||
|
||||
*flush_required = dm->flush_required;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
|
||||
@@ -1155,8 +1269,10 @@ int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
|
||||
}
|
||||
|
||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
|
||||
int lockfs)
|
||||
int lockfs, int flush_required)
|
||||
{
|
||||
dm->flush_required = flush_required;
|
||||
|
||||
return _tree_action(dm, lv, lockfs ? SUSPEND_WITH_LOCKFS : SUSPEND);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,10 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, int wait,
|
||||
float *percent, uint32_t *event_nr);
|
||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
|
||||
int lockfs);
|
||||
int lockfs, int flush_required);
|
||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv);
|
||||
int dev_manager_preload(struct dev_manager *dm, struct logical_volume *lv,
|
||||
int *flush_required);
|
||||
int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv);
|
||||
|
||||
int dev_manager_lv_mknodes(const struct logical_volume *lv);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -107,7 +107,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
{
|
||||
char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX];
|
||||
char vg_path[PATH_MAX];
|
||||
struct stat buf;
|
||||
struct stat buf, buf_lp;
|
||||
|
||||
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
dev_dir, vg_name) == -1) {
|
||||
@@ -138,7 +138,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
}
|
||||
|
||||
/* To reach this point, the VG must have been locked.
|
||||
* As locking fails if the VG is active under LVM1, it's
|
||||
* As locking fails if the VG is active under LVM1, it's
|
||||
* now safe to remove any LVM1 devices we find here
|
||||
* (as well as any existing LVM2 symlink). */
|
||||
if (!lstat(lvm1_group_path, &buf)) {
|
||||
@@ -161,12 +161,34 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_udev_get_sync_support()) {
|
||||
/* Check udev created the correct link. */
|
||||
if (!stat(link_path, &buf_lp) &&
|
||||
!stat(lv_path, &buf)) {
|
||||
if (buf_lp.st_rdev == buf.st_rdev)
|
||||
return 1;
|
||||
else
|
||||
log_warn("Symlink %s that should have been "
|
||||
"created by udev does not have "
|
||||
"correct target. Falling back to "
|
||||
"direct link creation", lv_path);
|
||||
} else
|
||||
log_warn("Symlink %s that should have been "
|
||||
"created by udev could not be checked "
|
||||
"for its correctness. Falling back to "
|
||||
"direct link creation.", lv_path);
|
||||
|
||||
}
|
||||
|
||||
log_very_verbose("Removing %s", lv_path);
|
||||
if (unlink(lv_path) < 0) {
|
||||
log_sys_error("unlink", lv_path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (dm_udev_get_sync_support())
|
||||
log_warn("The link %s should had been created by udev "
|
||||
"but it was not found. Falling back to "
|
||||
"direct link creation.", lv_path);
|
||||
|
||||
log_very_verbose("Linking %s -> %s", lv_path, link_path);
|
||||
if (symlink(link_path, lv_path) < 0) {
|
||||
@@ -175,10 +197,8 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!dm_set_selinux_context(lv_path, S_IFLNK)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dm_set_selinux_context(lv_path, S_IFLNK))
|
||||
return_0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
@@ -196,9 +216,14 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
|
||||
if (errno == ENOENT)
|
||||
return 1;
|
||||
if (lstat(lv_path, &buf) && errno == ENOENT)
|
||||
return 1;
|
||||
else if (dm_udev_get_sync_support())
|
||||
log_warn("The link %s should have been removed by udev "
|
||||
"but it is still present. Falling back to "
|
||||
"direct link removal.", lv_path);
|
||||
|
||||
if (!S_ISLNK(buf.st_mode)) {
|
||||
log_error("%s not symbolic link - not removing", lv_path);
|
||||
return 0;
|
||||
}
|
||||
@@ -225,17 +250,13 @@ static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
switch (type) {
|
||||
case FS_ADD:
|
||||
if (!_mk_dir(dev_dir, vg_name) ||
|
||||
!_mk_link(dev_dir, vg_name, lv_name, dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!_mk_link(dev_dir, vg_name, lv_name, dev))
|
||||
return_0;
|
||||
break;
|
||||
case FS_DEL:
|
||||
if (!_rm_link(dev_dir, vg_name, lv_name) ||
|
||||
!_rm_dir(dev_dir, vg_name)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!_rm_dir(dev_dir, vg_name))
|
||||
return_0;
|
||||
break;
|
||||
/* FIXME Use rename() */
|
||||
case FS_RENAME:
|
||||
@@ -249,10 +270,10 @@ static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static LIST_INIT(_fs_ops);
|
||||
static DM_LIST_INIT(_fs_ops);
|
||||
|
||||
struct fs_op_parms {
|
||||
struct list list;
|
||||
struct dm_list list;
|
||||
fs_op_t type;
|
||||
char *dev_dir;
|
||||
char *vg_name;
|
||||
@@ -292,21 +313,21 @@ static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
_store_str(&pos, &fsp->dev, dev);
|
||||
_store_str(&pos, &fsp->old_lv_name, old_lv_name);
|
||||
|
||||
list_add(&_fs_ops, &fsp->list);
|
||||
dm_list_add(&_fs_ops, &fsp->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _pop_fs_ops(void)
|
||||
{
|
||||
struct list *fsph, *fspht;
|
||||
struct dm_list *fsph, *fspht;
|
||||
struct fs_op_parms *fsp;
|
||||
|
||||
list_iterate_safe(fsph, fspht, &_fs_ops) {
|
||||
fsp = list_item(fsph, struct fs_op_parms);
|
||||
dm_list_iterate_safe(fsph, fspht, &_fs_ops) {
|
||||
fsp = dm_list_item(fsph, struct fs_op_parms);
|
||||
_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
|
||||
fsp->dev, fsp->old_lv_name);
|
||||
list_del(&fsp->list);
|
||||
dm_list_del(&fsp->list);
|
||||
dm_free(fsp);
|
||||
}
|
||||
}
|
||||
@@ -316,10 +337,8 @@ static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
{
|
||||
if (memlock()) {
|
||||
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
|
||||
old_lv_name)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
old_lv_name))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -343,11 +362,17 @@ int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_na
|
||||
return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "");
|
||||
}
|
||||
|
||||
int fs_rename_lv(struct logical_volume *lv,
|
||||
const char *dev, const char *old_name)
|
||||
int fs_rename_lv(struct logical_volume *lv, const char *dev,
|
||||
const char *old_vgname, const char *old_lvname)
|
||||
{
|
||||
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, old_name);
|
||||
if (strcmp(old_vgname, lv->vg->name)) {
|
||||
return
|
||||
(_fs_op(FS_DEL, lv->vg->cmd->dev_dir, old_vgname, old_lvname, "", "") &&
|
||||
_fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name, dev, ""));
|
||||
}
|
||||
else
|
||||
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, old_lvname);
|
||||
}
|
||||
|
||||
void fs_unlock(void)
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
int fs_add_lv(const struct logical_volume *lv, const char *dev);
|
||||
int fs_del_lv(const struct logical_volume *lv);
|
||||
int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name);
|
||||
int fs_rename_lv(struct logical_volume *lv,
|
||||
const char *dev, const char *old_name);
|
||||
int fs_rename_lv(struct logical_volume *lv, const char *dev,
|
||||
const char *old_vgname, const char *old_lvname);
|
||||
void fs_unlock(void);
|
||||
|
||||
#endif
|
||||
|
||||
652
lib/cache/lvmcache.c
vendored
652
lib/cache/lvmcache.c
vendored
File diff suppressed because it is too large
Load Diff
34
lib/cache/lvmcache.h
vendored
34
lib/cache/lvmcache.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -20,7 +20,8 @@
|
||||
#include "uuid.h"
|
||||
#include "label.h"
|
||||
|
||||
#define ORPHAN ""
|
||||
#define ORPHAN_PREFIX "#"
|
||||
#define ORPHAN_VG_NAME(fmt) ORPHAN_PREFIX "orphans_" fmt
|
||||
|
||||
#define CACHE_INVALID 0x00000001
|
||||
#define CACHE_LOCKED 0x00000002
|
||||
@@ -34,8 +35,8 @@ struct volume_group;
|
||||
|
||||
/* One per VG */
|
||||
struct lvmcache_vginfo {
|
||||
struct list list; /* Join these vginfos together */
|
||||
struct list infos; /* List head for lvmcache_infos */
|
||||
struct dm_list list; /* Join these vginfos together */
|
||||
struct dm_list infos; /* List head for lvmcache_infos */
|
||||
const struct format_type *fmt;
|
||||
char *vgname; /* "" == orphan */
|
||||
uint32_t status;
|
||||
@@ -43,13 +44,15 @@ struct lvmcache_vginfo {
|
||||
char _padding[7];
|
||||
struct lvmcache_vginfo *next; /* Another VG with same name? */
|
||||
char *creation_host;
|
||||
char *vgmetadata; /* Copy of VG metadata as format_text string */
|
||||
unsigned precommitted; /* Is vgmetadata live or precommitted? */
|
||||
};
|
||||
|
||||
/* One per device */
|
||||
struct lvmcache_info {
|
||||
struct list list; /* Join VG members together */
|
||||
struct list mdas; /* list head for metadata areas */
|
||||
struct list das; /* list head for data areas */
|
||||
struct dm_list list; /* Join VG members together */
|
||||
struct dm_list mdas; /* list head for metadata areas */
|
||||
struct dm_list das; /* list head for data areas */
|
||||
struct lvmcache_vginfo *vginfo; /* NULL == unknown */
|
||||
struct label *label;
|
||||
const struct format_type *fmt;
|
||||
@@ -59,7 +62,7 @@ struct lvmcache_info {
|
||||
};
|
||||
|
||||
int lvmcache_init(void);
|
||||
void lvmcache_destroy(void);
|
||||
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans);
|
||||
|
||||
/* Set full_scan to 1 to reread every filtered device label or
|
||||
* 2 to rescan /dev for new devices */
|
||||
@@ -70,13 +73,14 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
struct device *dev,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus);
|
||||
int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
|
||||
void lvmcache_del(struct lvmcache_info *info);
|
||||
|
||||
/* Update things */
|
||||
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
const char *vgname, const char *vgid,
|
||||
uint32_t vgstatus, const char *hostname);
|
||||
int lvmcache_update_vg(struct volume_group *vg);
|
||||
int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted);
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
|
||||
void lvmcache_unlock_vgname(const char *vgname);
|
||||
@@ -86,7 +90,7 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
|
||||
const char *vgid);
|
||||
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid);
|
||||
struct lvmcache_info *info_from_pvid(const char *pvid, int valid_only);
|
||||
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
|
||||
int vgs_locked(void);
|
||||
@@ -94,14 +98,18 @@ int vgname_is_locked(const char *vgname);
|
||||
|
||||
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
|
||||
/* Set full_scan to 1 to reread every filtered device label */
|
||||
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
|
||||
struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
/* Returns list of struct str_lists containing pool-allocated copy of vgids */
|
||||
/* Set full_scan to 1 to reread every filtered device label */
|
||||
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
|
||||
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan);
|
||||
|
||||
/* Returns list of struct str_lists containing pool-allocated copy of pvids */
|
||||
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
const char *vgid);
|
||||
|
||||
/* Returns cached volume group metadata. */
|
||||
struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted);
|
||||
void lvmcache_drop_metadata(const char *vgname);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,4 +21,6 @@
|
||||
#define EINVALID_CMD_LINE 3
|
||||
#define ECMD_FAILED 5
|
||||
|
||||
/* FIXME Also returned by cmdlib. */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -64,7 +64,7 @@ static int _get_env_vars(struct cmd_context *cmd)
|
||||
|
||||
/* Set to "" to avoid using any system directory */
|
||||
if ((e = getenv("LVM_SYSTEM_DIR"))) {
|
||||
if (dm_snprintf(cmd->sys_dir, sizeof(cmd->sys_dir),
|
||||
if (dm_snprintf(cmd->system_dir, sizeof(cmd->system_dir),
|
||||
"%s", e) < 0) {
|
||||
log_error("LVM_SYSTEM_DIR environment variable "
|
||||
"is too long.");
|
||||
@@ -75,6 +75,49 @@ static int _get_env_vars(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _get_sysfs_dir(struct cmd_context *cmd)
|
||||
{
|
||||
static char proc_mounts[PATH_MAX];
|
||||
static char *split[4], buffer[PATH_MAX + 16];
|
||||
FILE *fp;
|
||||
char *sys_mnt = NULL;
|
||||
|
||||
cmd->sysfs_dir[0] = '\0';
|
||||
if (!*cmd->proc_dir) {
|
||||
log_debug("No proc filesystem found: skipping sysfs detection");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
|
||||
"%s/mounts", cmd->proc_dir) < 0) {
|
||||
log_error("Failed to create /proc/mounts string for sysfs detection");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(fp = fopen(proc_mounts, "r"))) {
|
||||
log_sys_error("_get_sysfs_dir: fopen %s", proc_mounts);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp)) {
|
||||
if (dm_split_words(buffer, 4, 0, split) == 4 &&
|
||||
!strcmp(split[2], "sysfs")) {
|
||||
sys_mnt = split[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(fp))
|
||||
log_sys_error("fclose", proc_mounts);
|
||||
|
||||
if (!sys_mnt) {
|
||||
log_error("Failed to find sysfs mount point");
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy(cmd->sysfs_dir, sys_mnt, sizeof(cmd->sysfs_dir));
|
||||
}
|
||||
|
||||
static void _init_logging(struct cmd_context *cmd)
|
||||
{
|
||||
int append = 1;
|
||||
@@ -119,6 +162,7 @@ static void _init_logging(struct cmd_context *cmd)
|
||||
/* Test mode */
|
||||
cmd->default_settings.test =
|
||||
find_config_tree_int(cmd, "global/test", 0);
|
||||
init_test(cmd->default_settings.test);
|
||||
|
||||
/* Settings for logging to file */
|
||||
if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE))
|
||||
@@ -146,7 +190,7 @@ static void _init_logging(struct cmd_context *cmd)
|
||||
|
||||
/* Tell device-mapper about our logging */
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
dm_log_init(print_log);
|
||||
dm_log_with_errno_init(print_log);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -154,6 +198,7 @@ static int _process_config(struct cmd_context *cmd)
|
||||
{
|
||||
mode_t old_umask;
|
||||
const char *read_ahead;
|
||||
struct stat st;
|
||||
|
||||
/* umask */
|
||||
cmd->default_settings.umask = find_config_tree_int(cmd,
|
||||
@@ -189,6 +234,8 @@ static int _process_config(struct cmd_context *cmd)
|
||||
cmd->proc_dir[0] = '\0';
|
||||
}
|
||||
|
||||
_get_sysfs_dir(cmd);
|
||||
|
||||
/* activation? */
|
||||
cmd->default_settings.activation = find_config_tree_int(cmd,
|
||||
"global/activation",
|
||||
@@ -218,6 +265,34 @@ static int _process_config(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd->default_settings.udev_sync = find_config_tree_int(cmd,
|
||||
"activation/udev_sync",
|
||||
DEFAULT_UDEV_SYNC);
|
||||
|
||||
cmd->stripe_filler = find_config_tree_str(cmd,
|
||||
"activation/missing_stripe_filler",
|
||||
DEFAULT_STRIPE_FILLER);
|
||||
|
||||
/* FIXME Missing error code checks from the stats, not log_warn?, notify if setting overridden, delay message/check till it is actually used (eg consider if lvm shell - file could appear later after this check)? */
|
||||
if (!strcmp(cmd->stripe_filler, "/dev/ioerror") &&
|
||||
stat(cmd->stripe_filler, &st))
|
||||
cmd->stripe_filler = "error";
|
||||
|
||||
if (strcmp(cmd->stripe_filler, "error")) {
|
||||
if (stat(cmd->stripe_filler, &st)) {
|
||||
log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
|
||||
"is invalid,", cmd->stripe_filler);
|
||||
log_warn(" stat failed: %s", strerror(errno));
|
||||
log_warn("Falling back to \"error\" missing_stripe_filler.");
|
||||
cmd->stripe_filler = "error";
|
||||
} else if (!S_ISBLK(st.st_mode)) {
|
||||
log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
|
||||
"is not a block device.", cmd->stripe_filler);
|
||||
log_warn("Falling back to \"error\" missing_stripe_filler.");
|
||||
cmd->stripe_filler = "error";
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -282,10 +357,8 @@ static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
|
||||
if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags",
|
||||
DEFAULT_HOSTTAGS)) {
|
||||
/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
|
||||
if (!_set_tag(cmd, cmd->hostname)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_set_tag(cmd, cmd->hostname))
|
||||
return_0;
|
||||
cmd->hosttags = 1;
|
||||
}
|
||||
|
||||
@@ -301,17 +374,13 @@ static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
|
||||
}
|
||||
if (cn->child) {
|
||||
passes = 0;
|
||||
if (!_check_host_filters(cmd, cn->child, &passes)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_check_host_filters(cmd, cn->child, &passes))
|
||||
return_0;
|
||||
if (!passes)
|
||||
continue;
|
||||
}
|
||||
if (!_set_tag(cmd, tag)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_set_tag(cmd, tag))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -328,7 +397,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
||||
filler = "_";
|
||||
|
||||
if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
|
||||
cmd->sys_dir, filler, tag) < 0) {
|
||||
cmd->system_dir, filler, tag) < 0) {
|
||||
log_error("LVM_SYSTEM_DIR or tag was too long");
|
||||
return 0;
|
||||
}
|
||||
@@ -346,7 +415,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
||||
/* Is there a config file? */
|
||||
if (stat(config_file, &info) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
list_add(&cmd->config_files, &cfl->list);
|
||||
dm_list_add(&cmd->config_files, &cfl->list);
|
||||
goto out;
|
||||
}
|
||||
log_sys_error("stat", config_file);
|
||||
@@ -361,7 +430,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_add(&cmd->config_files, &cfl->list);
|
||||
dm_list_add(&cmd->config_files, &cfl->list);
|
||||
|
||||
out:
|
||||
if (*tag)
|
||||
@@ -377,7 +446,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
||||
static int _init_lvm_conf(struct cmd_context *cmd)
|
||||
{
|
||||
/* No config file if LVM_SYSTEM_DIR is empty */
|
||||
if (!*cmd->sys_dir) {
|
||||
if (!*cmd->system_dir) {
|
||||
if (!(cmd->cft = create_config_tree(NULL, 0))) {
|
||||
log_error("Failed to create config tree");
|
||||
return 0;
|
||||
@@ -385,10 +454,8 @@ static int _init_lvm_conf(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_load_config_file(cmd, "")) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_load_config_file(cmd, ""))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -399,12 +466,9 @@ static int _init_tag_configs(struct cmd_context *cmd)
|
||||
struct str_list *sl;
|
||||
|
||||
/* Tag list may grow while inside this loop */
|
||||
list_iterate_items(sl, &cmd->tags) {
|
||||
if (!_load_config_file(cmd, sl->str)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(sl, &cmd->tags) {
|
||||
if (!_load_config_file(cmd, sl->str))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -422,12 +486,10 @@ static int _merge_config_files(struct cmd_context *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
dm_list_iterate_items(cfl, &cmd->config_files) {
|
||||
/* Merge all config trees into cmd->cft using merge/tag rules */
|
||||
if (!merge_config_tree(cmd, cmd->cft, cfl->cft)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!merge_config_tree(cmd, cmd->cft, cfl->cft))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -435,10 +497,10 @@ static int _merge_config_files(struct cmd_context *cmd)
|
||||
|
||||
static void _destroy_tags(struct cmd_context *cmd)
|
||||
{
|
||||
struct list *slh, *slht;
|
||||
struct dm_list *slh, *slht;
|
||||
|
||||
list_iterate_safe(slh, slht, &cmd->tags) {
|
||||
list_del(slh);
|
||||
dm_list_iterate_safe(slh, slht, &cmd->tags) {
|
||||
dm_list_del(slh);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +508,7 @@ int config_files_changed(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
dm_list_iterate_items(cfl, &cmd->config_files) {
|
||||
if (config_file_changed(cfl->cft))
|
||||
return 1;
|
||||
}
|
||||
@@ -458,16 +520,18 @@ static void _destroy_tag_configs(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_tree_list *cfl;
|
||||
|
||||
if (cmd->cft && cmd->cft->root) {
|
||||
dm_list_iterate_items(cfl, &cmd->config_files) {
|
||||
if (cfl->cft == cmd->cft)
|
||||
cmd->cft = NULL;
|
||||
destroy_config_tree(cfl->cft);
|
||||
}
|
||||
|
||||
if (cmd->cft) {
|
||||
destroy_config_tree(cmd->cft);
|
||||
cmd->cft = NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(cfl, &cmd->config_files) {
|
||||
destroy_config_tree(cfl->cft);
|
||||
}
|
||||
|
||||
list_init(&cmd->config_files);
|
||||
dm_list_init(&cmd->config_files);
|
||||
}
|
||||
|
||||
static int _init_dev_cache(struct cmd_context *cmd)
|
||||
@@ -542,12 +606,12 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
||||
|
||||
/*
|
||||
* sysfs filter. Only available on 2.6 kernels. Non-critical.
|
||||
* Listed first because it's very efficient at eliminating
|
||||
* Listed first because it's very efficient at eliminating
|
||||
* unavailable devices.
|
||||
*/
|
||||
if (find_config_tree_bool(cmd, "devices/sysfs_scan",
|
||||
DEFAULT_SYSFS_SCAN)) {
|
||||
if ((filters[nr_filt] = sysfs_filter_create(cmd->proc_dir)))
|
||||
if ((filters[nr_filt] = sysfs_filter_create(cmd->sysfs_dir)))
|
||||
nr_filt++;
|
||||
}
|
||||
|
||||
@@ -605,7 +669,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
|
||||
if (cache_dir || cache_file_prefix) {
|
||||
if (dm_snprintf(cache_file, sizeof(cache_file),
|
||||
"%s%s%s/%s.cache",
|
||||
cache_dir ? "" : cmd->sys_dir,
|
||||
cache_dir ? "" : cmd->system_dir,
|
||||
cache_dir ? "" : "/",
|
||||
cache_dir ? : DEFAULT_CACHE_SUBDIR,
|
||||
cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
|
||||
@@ -615,7 +679,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
|
||||
} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
|
||||
(dm_snprintf(cache_file, sizeof(cache_file),
|
||||
"%s/%s/%s.cache",
|
||||
cmd->sys_dir, DEFAULT_CACHE_SUBDIR,
|
||||
cmd->system_dir, DEFAULT_CACHE_SUBDIR,
|
||||
DEFAULT_CACHE_FILE_PREFIX) < 0)) {
|
||||
log_error("Persistent cache filename too long.");
|
||||
return 0;
|
||||
@@ -633,7 +697,7 @@ static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache
|
||||
if (find_config_tree_int(cmd, "devices/write_cache_state", 1))
|
||||
cmd->dump_filter = 1;
|
||||
|
||||
if (!*cmd->sys_dir)
|
||||
if (!*cmd->system_dir)
|
||||
cmd->dump_filter = 0;
|
||||
|
||||
/*
|
||||
@@ -668,19 +732,19 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
if (!(fmt = init_lvm1_format(cmd)))
|
||||
return 0;
|
||||
fmt->library = NULL;
|
||||
list_add(&cmd->formats, &fmt->list);
|
||||
dm_list_add(&cmd->formats, &fmt->list);
|
||||
#endif
|
||||
|
||||
#ifdef POOL_INTERNAL
|
||||
if (!(fmt = init_pool_format(cmd)))
|
||||
return 0;
|
||||
fmt->library = NULL;
|
||||
list_add(&cmd->formats, &fmt->list);
|
||||
dm_list_add(&cmd->formats, &fmt->list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
/* Load any formats in shared libs if not static */
|
||||
if (!cmd->is_static &&
|
||||
if (!is_static() &&
|
||||
(cn = find_config_tree_node(cmd, "global/format_libraries"))) {
|
||||
|
||||
struct config_value *cv;
|
||||
@@ -694,10 +758,8 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd, cv->v.str,
|
||||
"format", 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
"format", 0)))
|
||||
return_0;
|
||||
|
||||
if (!(init_format_fn = dlsym(lib, "init_format"))) {
|
||||
log_error("Shared library %s does not contain "
|
||||
@@ -709,7 +771,7 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
if (!(fmt = init_format_fn(cmd)))
|
||||
return 0;
|
||||
fmt->library = lib;
|
||||
list_add(&cmd->formats, &fmt->list);
|
||||
dm_list_add(&cmd->formats, &fmt->list);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -717,17 +779,18 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
if (!(fmt = create_text_format(cmd)))
|
||||
return 0;
|
||||
fmt->library = NULL;
|
||||
list_add(&cmd->formats, &fmt->list);
|
||||
dm_list_add(&cmd->formats, &fmt->list);
|
||||
|
||||
cmd->fmt_backup = fmt;
|
||||
|
||||
format = find_config_tree_str(cmd, "global/format",
|
||||
DEFAULT_FORMAT);
|
||||
|
||||
list_iterate_items(fmt, &cmd->formats) {
|
||||
dm_list_iterate_items(fmt, &cmd->formats) {
|
||||
if (!strcasecmp(fmt->name, format) ||
|
||||
(fmt->alias && !strcasecmp(fmt->alias, format))) {
|
||||
cmd->default_settings.fmt = fmt;
|
||||
cmd->fmt = cmd->default_settings.fmt;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -736,9 +799,68 @@ static int _init_formats(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_lvmcache_orphans(struct cmd_context *cmd)
|
||||
{
|
||||
struct format_type *fmt;
|
||||
|
||||
dm_list_iterate_items(fmt, &cmd->formats)
|
||||
if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct segtype_library {
|
||||
struct cmd_context *cmd;
|
||||
void *lib;
|
||||
const char *libname;
|
||||
};
|
||||
|
||||
int lvm_register_segtype(struct segtype_library *seglib,
|
||||
struct segment_type *segtype)
|
||||
{
|
||||
struct segment_type *segtype2;
|
||||
|
||||
segtype->library = seglib->lib;
|
||||
segtype->cmd = seglib->cmd;
|
||||
|
||||
dm_list_iterate_items(segtype2, &seglib->cmd->segtypes) {
|
||||
if (strcmp(segtype2->name, segtype->name))
|
||||
continue;
|
||||
log_error("Duplicate segment type %s: "
|
||||
"unloading shared library %s",
|
||||
segtype->name, seglib->libname);
|
||||
segtype->ops->destroy(segtype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_list_add(&seglib->cmd->segtypes, &segtype->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_single_segtype(struct cmd_context *cmd,
|
||||
struct segtype_library *seglib)
|
||||
{
|
||||
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
|
||||
struct segment_type *segtype;
|
||||
|
||||
if (!(init_segtype_fn = dlsym(seglib->lib, "init_segtype"))) {
|
||||
log_error("Shared library %s does not contain segment type "
|
||||
"functions", seglib->libname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(segtype = init_segtype_fn(seglib->cmd)))
|
||||
return_0;
|
||||
|
||||
return lvm_register_segtype(seglib, segtype);
|
||||
}
|
||||
|
||||
static int _init_segtypes(struct cmd_context *cmd)
|
||||
{
|
||||
struct segment_type *segtype;
|
||||
struct segtype_library seglib = { .cmd = cmd };
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
const struct config_node *cn;
|
||||
@@ -747,41 +869,45 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
if (!(segtype = init_striped_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
dm_list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
if (!(segtype = init_zero_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
dm_list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
if (!(segtype = init_error_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
dm_list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
if (!(segtype = init_free_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
dm_list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
#ifdef SNAPSHOT_INTERNAL
|
||||
if (!(segtype = init_snapshot_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
dm_list_add(&cmd->segtypes, &segtype->list);
|
||||
#endif
|
||||
|
||||
#ifdef MIRRORED_INTERNAL
|
||||
if (!(segtype = init_mirrored_segtype(cmd)))
|
||||
return 0;
|
||||
segtype->library = NULL;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
dm_list_add(&cmd->segtypes, &segtype->list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDL
|
||||
/* Load any formats in shared libs unless static */
|
||||
if (!cmd->is_static &&
|
||||
if (!is_static() &&
|
||||
(cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
|
||||
|
||||
struct config_value *cv;
|
||||
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
|
||||
void *lib;
|
||||
struct segment_type *segtype2;
|
||||
int (*init_multiple_segtypes_fn) (struct cmd_context *,
|
||||
struct segtype_library *);
|
||||
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != CFG_STRING) {
|
||||
@@ -789,34 +915,37 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
"global/segment_libraries");
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd, cv->v.str,
|
||||
"segment type", 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
seglib.libname = cv->v.str;
|
||||
if (!(seglib.lib = load_shared_library(cmd,
|
||||
seglib.libname,
|
||||
"segment type", 0)))
|
||||
return_0;
|
||||
|
||||
if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
|
||||
log_error("Shared library %s does not contain "
|
||||
"segment type functions", cv->v.str);
|
||||
dlclose(lib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(segtype = init_segtype_fn(cmd)))
|
||||
return 0;
|
||||
segtype->library = lib;
|
||||
list_add(&cmd->segtypes, &segtype->list);
|
||||
|
||||
list_iterate_items(segtype2, &cmd->segtypes) {
|
||||
if ((segtype == segtype2) ||
|
||||
strcmp(segtype2->name, segtype->name))
|
||||
continue;
|
||||
log_error("Duplicate segment type %s: "
|
||||
"unloading shared library %s",
|
||||
segtype->name, cv->v.str);
|
||||
list_del(&segtype->list);
|
||||
segtype->ops->destroy(segtype);
|
||||
dlclose(lib);
|
||||
if ((init_multiple_segtypes_fn =
|
||||
dlsym(seglib.lib, "init_multiple_segtypes"))) {
|
||||
if (dlsym(seglib.lib, "init_segtype"))
|
||||
log_warn("WARNING: Shared lib %s has "
|
||||
"conflicting init fns. Using"
|
||||
" init_multiple_segtypes().",
|
||||
seglib.libname);
|
||||
} else
|
||||
init_multiple_segtypes_fn =
|
||||
_init_single_segtype;
|
||||
|
||||
if (!init_multiple_segtypes_fn(cmd, &seglib)) {
|
||||
struct dm_list *sgtl, *tmp;
|
||||
log_error("init_multiple_segtypes() failed: "
|
||||
"Unloading shared library %s",
|
||||
seglib.libname);
|
||||
dm_list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
|
||||
segtype = dm_list_item(sgtl, struct segment_type);
|
||||
if (segtype->library == seglib.lib) {
|
||||
dm_list_del(&segtype->list);
|
||||
segtype->ops->destroy(segtype);
|
||||
}
|
||||
}
|
||||
dlclose(seglib.lib);
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -853,10 +982,10 @@ static int _init_backup(struct cmd_context *cmd)
|
||||
char default_dir[PATH_MAX];
|
||||
const char *dir;
|
||||
|
||||
if (!cmd->sys_dir) {
|
||||
if (!cmd->system_dir) {
|
||||
log_warn("WARNING: Metadata changes will NOT be backed up");
|
||||
backup_init(cmd, "");
|
||||
archive_init(cmd, "", 0, 0);
|
||||
backup_init(cmd, "", 0);
|
||||
archive_init(cmd, "", 0, 0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -872,18 +1001,19 @@ static int _init_backup(struct cmd_context *cmd)
|
||||
DEFAULT_ARCHIVE_NUMBER);
|
||||
|
||||
if (dm_snprintf
|
||||
(default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
|
||||
(default_dir, sizeof(default_dir), "%s/%s", cmd->system_dir,
|
||||
DEFAULT_ARCHIVE_SUBDIR) == -1) {
|
||||
log_err("Couldn't create default archive path '%s/%s'.",
|
||||
cmd->sys_dir, DEFAULT_ARCHIVE_SUBDIR);
|
||||
log_error("Couldn't create default archive path '%s/%s'.",
|
||||
cmd->system_dir, DEFAULT_ARCHIVE_SUBDIR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dir = find_config_tree_str(cmd, "backup/archive_dir",
|
||||
default_dir);
|
||||
|
||||
if (!archive_init(cmd, dir, days, min)) {
|
||||
log_debug("backup_init failed.");
|
||||
if (!archive_init(cmd, dir, days, min,
|
||||
cmd->default_settings.archive)) {
|
||||
log_debug("archive_init failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -893,16 +1023,16 @@ static int _init_backup(struct cmd_context *cmd)
|
||||
DEFAULT_BACKUP_ENABLED);
|
||||
|
||||
if (dm_snprintf
|
||||
(default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
|
||||
(default_dir, sizeof(default_dir), "%s/%s", cmd->system_dir,
|
||||
DEFAULT_BACKUP_SUBDIR) == -1) {
|
||||
log_err("Couldn't create default backup path '%s/%s'.",
|
||||
cmd->sys_dir, DEFAULT_BACKUP_SUBDIR);
|
||||
log_error("Couldn't create default backup path '%s/%s'.",
|
||||
cmd->system_dir, DEFAULT_BACKUP_SUBDIR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir);
|
||||
|
||||
if (!backup_init(cmd, dir)) {
|
||||
if (!backup_init(cmd, dir, cmd->default_settings.backup)) {
|
||||
log_debug("backup_init failed.");
|
||||
return 0;
|
||||
}
|
||||
@@ -910,9 +1040,24 @@ static int _init_backup(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _init_rand(struct cmd_context *cmd)
|
||||
{
|
||||
if (read_urandom(&cmd->rand_seed, sizeof(cmd->rand_seed)))
|
||||
return;
|
||||
|
||||
cmd->rand_seed = (unsigned) time(NULL) + (unsigned) getpid();
|
||||
}
|
||||
|
||||
static void _init_globals(struct cmd_context *cmd)
|
||||
{
|
||||
init_full_scan_done(0);
|
||||
init_mirror_in_sync(0);
|
||||
|
||||
}
|
||||
|
||||
/* Entry point */
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
|
||||
unsigned is_long_lived)
|
||||
struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
const char *system_dir)
|
||||
{
|
||||
struct cmd_context *cmd;
|
||||
|
||||
@@ -934,95 +1079,108 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
|
||||
return NULL;
|
||||
}
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->args = the_args;
|
||||
cmd->is_static = is_static;
|
||||
cmd->is_long_lived = is_long_lived;
|
||||
cmd->handles_missing_pvs = 0;
|
||||
cmd->hosttags = 0;
|
||||
list_init(&cmd->formats);
|
||||
list_init(&cmd->segtypes);
|
||||
list_init(&cmd->tags);
|
||||
list_init(&cmd->config_files);
|
||||
dm_list_init(&cmd->formats);
|
||||
dm_list_init(&cmd->segtypes);
|
||||
dm_list_init(&cmd->tags);
|
||||
dm_list_init(&cmd->config_files);
|
||||
|
||||
strcpy(cmd->sys_dir, DEFAULT_SYS_DIR);
|
||||
/* FIXME Make this configurable? */
|
||||
reset_lvm_errno(1);
|
||||
|
||||
/*
|
||||
* Environment variable LVM_SYSTEM_DIR overrides this below.
|
||||
*/
|
||||
if (system_dir)
|
||||
strncpy(cmd->system_dir, system_dir, sizeof(cmd->system_dir) - 1);
|
||||
else
|
||||
strcpy(cmd->system_dir, DEFAULT_SYS_DIR);
|
||||
|
||||
if (!_get_env_vars(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
/* Create system directory if it doesn't already exist */
|
||||
if (*cmd->sys_dir && !dm_create_dir(cmd->sys_dir)) {
|
||||
if (*cmd->system_dir && !dm_create_dir(cmd->system_dir)) {
|
||||
log_error("Failed to create LVM2 system dir for metadata backups, config "
|
||||
"files and internal cache.");
|
||||
log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
|
||||
"or empty string.");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) {
|
||||
log_error("Library memory pool creation failed");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_init_lvm_conf(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
_init_logging(cmd);
|
||||
|
||||
if (!_init_hostname(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!_init_tags(cmd, cmd->cft))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!_init_tag_configs(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!_merge_config_files(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!_process_config(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!_init_dev_cache(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!_init_filters(cmd, 1))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
|
||||
log_error("Command memory pool creation failed");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memlock_init(cmd);
|
||||
|
||||
if (!_init_formats(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!init_lvmcache_orphans(cmd))
|
||||
goto_out;
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
if (!_init_backup(cmd))
|
||||
goto error;
|
||||
goto_out;
|
||||
|
||||
_init_rand(cmd);
|
||||
|
||||
_init_globals(cmd);
|
||||
|
||||
cmd->default_settings.cache_vgmetadata = 1;
|
||||
cmd->current_settings = cmd->default_settings;
|
||||
|
||||
cmd->config_valid = 1;
|
||||
out:
|
||||
return cmd;
|
||||
|
||||
error:
|
||||
dm_free(cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _destroy_formats(struct list *formats)
|
||||
static void _destroy_formats(struct dm_list *formats)
|
||||
{
|
||||
struct list *fmtl, *tmp;
|
||||
struct dm_list *fmtl, *tmp;
|
||||
struct format_type *fmt;
|
||||
void *lib;
|
||||
|
||||
list_iterate_safe(fmtl, tmp, formats) {
|
||||
fmt = list_item(fmtl, struct format_type);
|
||||
list_del(&fmt->list);
|
||||
dm_list_iterate_safe(fmtl, tmp, formats) {
|
||||
fmt = dm_list_item(fmtl, struct format_type);
|
||||
dm_list_del(&fmt->list);
|
||||
lib = fmt->library;
|
||||
fmt->ops->destroy(fmt);
|
||||
#ifdef HAVE_LIBDL
|
||||
@@ -1032,20 +1190,30 @@ static void _destroy_formats(struct list *formats)
|
||||
}
|
||||
}
|
||||
|
||||
static void _destroy_segtypes(struct list *segtypes)
|
||||
static void _destroy_segtypes(struct dm_list *segtypes)
|
||||
{
|
||||
struct list *sgtl, *tmp;
|
||||
struct dm_list *sgtl, *tmp;
|
||||
struct segment_type *segtype;
|
||||
void *lib;
|
||||
|
||||
list_iterate_safe(sgtl, tmp, segtypes) {
|
||||
segtype = list_item(sgtl, struct segment_type);
|
||||
list_del(&segtype->list);
|
||||
dm_list_iterate_safe(sgtl, tmp, segtypes) {
|
||||
segtype = dm_list_item(sgtl, struct segment_type);
|
||||
dm_list_del(&segtype->list);
|
||||
lib = segtype->library;
|
||||
segtype->ops->destroy(segtype);
|
||||
#ifdef HAVE_LIBDL
|
||||
if (lib)
|
||||
/*
|
||||
* If no segtypes remain from this library, close it.
|
||||
*/
|
||||
if (lib) {
|
||||
struct segment_type *segtype2;
|
||||
dm_list_iterate_items(segtype2, segtypes)
|
||||
if (segtype2->library == lib)
|
||||
goto skip_dlclose;
|
||||
dlclose(lib);
|
||||
skip_dlclose:
|
||||
;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1060,7 +1228,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
*/
|
||||
|
||||
activation_release();
|
||||
lvmcache_destroy();
|
||||
lvmcache_destroy(cmd, 0);
|
||||
label_exit();
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(&cmd->formats);
|
||||
@@ -1102,6 +1270,9 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
if (!_init_formats(cmd))
|
||||
return 0;
|
||||
|
||||
if (!init_lvmcache_orphans(cmd))
|
||||
return 0;
|
||||
|
||||
if (!_init_segtypes(cmd))
|
||||
return 0;
|
||||
|
||||
@@ -1113,6 +1284,8 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
persistent_filter_dump(cmd->filter);
|
||||
|
||||
cmd->config_valid = 1;
|
||||
|
||||
reset_lvm_errno(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1123,20 +1296,24 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
|
||||
archive_exit(cmd);
|
||||
backup_exit(cmd);
|
||||
lvmcache_destroy();
|
||||
lvmcache_destroy(cmd, 0);
|
||||
label_exit();
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(&cmd->formats);
|
||||
cmd->filter->destroy(cmd->filter);
|
||||
dm_pool_destroy(cmd->mem);
|
||||
if (cmd->filter)
|
||||
cmd->filter->destroy(cmd->filter);
|
||||
if (cmd->mem)
|
||||
dm_pool_destroy(cmd->mem);
|
||||
dev_cache_exit();
|
||||
_destroy_tags(cmd);
|
||||
_destroy_tag_configs(cmd);
|
||||
dm_pool_destroy(cmd->libmem);
|
||||
if (cmd->libmem)
|
||||
dm_pool_destroy(cmd->libmem);
|
||||
dm_free(cmd);
|
||||
|
||||
release_log_memory();
|
||||
activation_exit();
|
||||
fin_log();
|
||||
fin_syslog();
|
||||
reset_lvm_errno(0);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -34,6 +34,8 @@ struct config_info {
|
||||
int archive; /* should we archive ? */
|
||||
int backup; /* should we backup ? */
|
||||
int read_ahead; /* DM_READ_AHEAD_NONE or _AUTO */
|
||||
int udev_sync;
|
||||
int cache_vgmetadata;
|
||||
const char *msg_prefix;
|
||||
struct format_type *fmt;
|
||||
uint64_t unit_factor;
|
||||
@@ -56,22 +58,23 @@ struct cmd_context {
|
||||
const struct format_type *fmt; /* Current format to use by default */
|
||||
struct format_type *fmt_backup; /* Format to use for backups */
|
||||
|
||||
struct list formats; /* Available formats */
|
||||
struct list segtypes; /* Available segment types */
|
||||
struct dm_list formats; /* Available formats */
|
||||
struct dm_list segtypes; /* Available segment types */
|
||||
const char *hostname;
|
||||
const char *kernel_vsn;
|
||||
|
||||
char *cmd_line;
|
||||
unsigned rand_seed;
|
||||
const char *cmd_line;
|
||||
struct command *command;
|
||||
struct arg *args;
|
||||
char **argv;
|
||||
unsigned is_static; /* Static binary? */
|
||||
unsigned is_long_lived; /* Optimises persistent_filter handling */
|
||||
unsigned is_long_lived:1; /* Optimises persistent_filter handling */
|
||||
unsigned handles_missing_pvs:1;
|
||||
unsigned partial_activation:1;
|
||||
|
||||
struct dev_filter *filter;
|
||||
int dump_filter; /* Dump filter when exiting? */
|
||||
|
||||
struct list config_files;
|
||||
struct dm_list config_files;
|
||||
int config_valid;
|
||||
struct config_tree *cft;
|
||||
struct config_tree *cft_override;
|
||||
@@ -80,19 +83,27 @@ struct cmd_context {
|
||||
|
||||
struct archive_params *archive_params;
|
||||
struct backup_params *backup_params;
|
||||
const char *stripe_filler;
|
||||
|
||||
/* List of defined tags */
|
||||
struct list tags;
|
||||
struct dm_list tags;
|
||||
int hosttags;
|
||||
|
||||
char sys_dir[PATH_MAX];
|
||||
char system_dir[PATH_MAX];
|
||||
char dev_dir[PATH_MAX];
|
||||
char proc_dir[PATH_MAX];
|
||||
char sysfs_dir[PATH_MAX];
|
||||
};
|
||||
|
||||
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
|
||||
/*
|
||||
* system_dir may be NULL to use the default value.
|
||||
* The environment variable LVM_SYSTEM_DIR always takes precedence.
|
||||
*/
|
||||
struct cmd_context *create_toolcontext(unsigned is_long_lived,
|
||||
const char *system_dir);
|
||||
void destroy_toolcontext(struct cmd_context *cmd);
|
||||
int refresh_toolcontext(struct cmd_context *cmd);
|
||||
int config_files_changed(struct cmd_context *cmd);
|
||||
int init_lvmcache_orphans(struct cmd_context *cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
enum {
|
||||
TOK_INT,
|
||||
TOK_FLOAT,
|
||||
TOK_STRING,
|
||||
TOK_STRING, /* Single quotes */
|
||||
TOK_STRING_ESCAPED, /* Double quotes */
|
||||
TOK_EQ,
|
||||
TOK_SECTION_B,
|
||||
TOK_SECTION_E,
|
||||
@@ -185,6 +186,17 @@ struct config_tree *create_config_tree_from_string(struct cmd_context *cmd __att
|
||||
return cft;
|
||||
}
|
||||
|
||||
int override_config_tree_from_string(struct cmd_context *cmd,
|
||||
const char *config_settings)
|
||||
{
|
||||
if (!(cmd->cft_override = create_config_tree_from_string(cmd,config_settings))) {
|
||||
log_error("Failed to set overridden configuration entries.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum)
|
||||
@@ -196,10 +208,8 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
off_t mmap_offset = 0;
|
||||
char *buf = NULL;
|
||||
|
||||
if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(p = dm_pool_alloc(c->mem, sizeof(*p))))
|
||||
return_0;
|
||||
p->mem = c->mem;
|
||||
|
||||
/* Only use mmap with regular files */
|
||||
@@ -217,10 +227,8 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
}
|
||||
p->fb = p->fb + mmap_offset;
|
||||
} else {
|
||||
if (!(buf = dm_malloc(size + size2))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(buf = dm_malloc(size + size2)))
|
||||
return_0;
|
||||
if (!dev_read_circular(dev, (uint64_t) offset, size,
|
||||
(uint64_t) offset2, size2, buf)) {
|
||||
goto out;
|
||||
@@ -237,10 +245,8 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
|
||||
p->fe = p->fb + size + size2;
|
||||
|
||||
if (!_parse_config_file(p, cft)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!_parse_config_file(p, cft))
|
||||
goto_out;
|
||||
|
||||
r = 1;
|
||||
|
||||
@@ -378,7 +384,7 @@ static int _line_append(struct output_line *outline, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
|
||||
if (!dm_pool_grow_object(outline->mem, &buf[0], strlen(buf))) {
|
||||
log_error("dm_pool_grew_object failed for config line");
|
||||
log_error("dm_pool_grow_object failed for config line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -407,9 +413,16 @@ static int _line_end(struct output_line *outline)
|
||||
|
||||
static int _write_value(struct output_line *outline, struct config_value *v)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
switch (v->type) {
|
||||
case CFG_STRING:
|
||||
line_append("\"%s\"", v->v.str);
|
||||
if (!(buf = alloca(escaped_len(v->v.str)))) {
|
||||
log_error("temporary stack allocation for a config "
|
||||
"string failed");
|
||||
return 0;
|
||||
}
|
||||
line_append("\"%s\"", escape_double_quotes(buf, v->v.str));
|
||||
break;
|
||||
|
||||
case CFG_FLOAT:
|
||||
@@ -455,9 +468,9 @@ static int _write_config(struct config_node *n, int only_one,
|
||||
line_append(" {");
|
||||
if (!_line_end(outline))
|
||||
return_0;
|
||||
_write_config(n->child, 0, outline, level + 1);
|
||||
if (!_line_start(outline))
|
||||
return_0;
|
||||
_write_config(n->child, 0, outline, level + 1);
|
||||
line_append("%s}", space);
|
||||
} else {
|
||||
/* it's a value */
|
||||
@@ -537,15 +550,14 @@ static struct config_node *_file(struct parser *p)
|
||||
{
|
||||
struct config_node *root = NULL, *n, *l = NULL;
|
||||
while (p->t != TOK_EOF) {
|
||||
if (!(n = _section(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(n = _section(p)))
|
||||
return_0;
|
||||
|
||||
if (!root)
|
||||
root = n;
|
||||
else
|
||||
l->sib = n;
|
||||
n->parent = root;
|
||||
l = n;
|
||||
}
|
||||
return root;
|
||||
@@ -555,39 +567,32 @@ static struct config_node *_section(struct parser *p)
|
||||
{
|
||||
/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
|
||||
struct config_node *root, *n, *l = NULL;
|
||||
if (!(root = _create_node(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(root = _create_node(p)))
|
||||
return_0;
|
||||
|
||||
if (!(root->key = _dup_tok(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(root->key = _dup_tok(p)))
|
||||
return_0;
|
||||
|
||||
match(TOK_IDENTIFIER);
|
||||
|
||||
if (p->t == TOK_SECTION_B) {
|
||||
match(TOK_SECTION_B);
|
||||
while (p->t != TOK_SECTION_E) {
|
||||
if (!(n = _section(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(n = _section(p)))
|
||||
return_0;
|
||||
|
||||
if (!root->child)
|
||||
root->child = n;
|
||||
else
|
||||
l->sib = n;
|
||||
n->parent = root;
|
||||
l = n;
|
||||
}
|
||||
match(TOK_SECTION_E);
|
||||
} else {
|
||||
match(TOK_EQ);
|
||||
if (!(root->v = _value(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(root->v = _value(p)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return root;
|
||||
@@ -600,10 +605,8 @@ static struct config_value *_value(struct parser *p)
|
||||
if (p->t == TOK_ARRAY_B) {
|
||||
match(TOK_ARRAY_B);
|
||||
while (p->t != TOK_ARRAY_E) {
|
||||
if (!(l = _type(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(l = _type(p)))
|
||||
return_0;
|
||||
|
||||
if (!h)
|
||||
h = l;
|
||||
@@ -656,14 +659,23 @@ static struct config_value *_type(struct parser *p)
|
||||
v->type = CFG_STRING;
|
||||
|
||||
p->tb++, p->te--; /* strip "'s */
|
||||
if (!(v->v.str = _dup_tok(p))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(v->v.str = _dup_tok(p)))
|
||||
return_0;
|
||||
p->te++;
|
||||
match(TOK_STRING);
|
||||
break;
|
||||
|
||||
case TOK_STRING_ESCAPED:
|
||||
v->type = CFG_STRING;
|
||||
|
||||
p->tb++, p->te--; /* strip "'s */
|
||||
if (!(v->v.str = _dup_tok(p)))
|
||||
return_0;
|
||||
unescape_double_quotes(v->v.str);
|
||||
p->te++;
|
||||
match(TOK_STRING_ESCAPED);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
|
||||
p->tb - p->fb + 1, p->line);
|
||||
@@ -734,7 +746,7 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
break;
|
||||
|
||||
case '"':
|
||||
p->t = TOK_STRING;
|
||||
p->t = TOK_STRING_ESCAPED;
|
||||
p->te++;
|
||||
while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) {
|
||||
if ((*p->te == '\\') && (p->te + 1 != p->fe) &&
|
||||
@@ -799,11 +811,9 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
static void _eat_space(struct parser *p)
|
||||
{
|
||||
while ((p->tb != p->fe) && (*p->tb)) {
|
||||
if (*p->te == '#') {
|
||||
if (*p->te == '#')
|
||||
while ((p->te != p->fe) && (*p->te) && (*p->te != '\n'))
|
||||
p->te++;
|
||||
p->line++;
|
||||
}
|
||||
|
||||
else if (isspace(*p->te)) {
|
||||
while ((p->te != p->fe) && (*p->te) && isspace(*p->te)) {
|
||||
@@ -847,10 +857,8 @@ static char *_dup_tok(struct parser *p)
|
||||
{
|
||||
size_t len = p->te - p->tb;
|
||||
char *str = dm_pool_alloc(p->mem, len + 1);
|
||||
if (!str) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!str)
|
||||
return_0;
|
||||
strncpy(str, p->tb, len);
|
||||
str[len] = '\0';
|
||||
return str;
|
||||
@@ -1016,7 +1024,7 @@ float find_config_tree_float(struct cmd_context *cmd, const char *path,
|
||||
return _find_config_float(cmd->cft_override ? cmd->cft_override->root : NULL, cmd->cft->root, path, fail);
|
||||
}
|
||||
|
||||
static int _str_in_array(const char *str, const char *values[])
|
||||
static int _str_in_array(const char *str, const char * const values[])
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1029,9 +1037,8 @@ static int _str_in_array(const char *str, const char *values[])
|
||||
|
||||
static int _str_to_bool(const char *str, int fail)
|
||||
{
|
||||
static const char *_true_values[] = { "y", "yes", "on", "true", NULL };
|
||||
static const char *_false_values[] =
|
||||
{ "n", "no", "off", "false", NULL };
|
||||
const char * const _true_values[] = { "y", "yes", "on", "true", NULL };
|
||||
const char * const _false_values[] = { "n", "no", "off", "false", NULL };
|
||||
|
||||
if (_str_in_array(str, _true_values))
|
||||
return 1;
|
||||
@@ -1171,7 +1178,7 @@ static void _merge_section(struct config_node *cn1, struct config_node *cn2)
|
||||
}
|
||||
}
|
||||
|
||||
static int _match_host_tags(struct list *tags, struct config_node *tn)
|
||||
static int _match_host_tags(struct dm_list *tags, struct config_node *tn)
|
||||
{
|
||||
struct config_value *tv;
|
||||
const char *str;
|
||||
@@ -1254,9 +1261,13 @@ static unsigned _count_tokens(const char *str, unsigned len, int type)
|
||||
|
||||
c = _token_type_to_char(type);
|
||||
|
||||
return count_chars_len(str, len, c);
|
||||
return count_chars(str, len, c);
|
||||
}
|
||||
|
||||
const char *config_parent_name(const struct config_node *n)
|
||||
{
|
||||
return (n->parent ? n->parent->key : "(root)");
|
||||
}
|
||||
/*
|
||||
* Heuristic function to make a quick guess as to whether a text
|
||||
* region probably contains a valid config "section". (Useful for
|
||||
@@ -1281,7 +1292,7 @@ unsigned maybe_config_section(const char *str, unsigned len)
|
||||
begin_count = _count_tokens(str, len, TOK_SECTION_B);
|
||||
end_count = _count_tokens(str, len, TOK_SECTION_E);
|
||||
|
||||
if (begin_count && end_count && (begin_count - end_count == 0))
|
||||
if (begin_count && end_count && (begin_count == end_count))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
@@ -40,7 +40,7 @@ struct config_value {
|
||||
|
||||
struct config_node {
|
||||
char *key;
|
||||
struct config_node *sib, *child;
|
||||
struct config_node *parent, *sib, *child;
|
||||
struct config_value *v;
|
||||
};
|
||||
|
||||
@@ -49,13 +49,15 @@ struct config_tree {
|
||||
};
|
||||
|
||||
struct config_tree_list {
|
||||
struct list list;
|
||||
struct dm_list list;
|
||||
struct config_tree *cft;
|
||||
};
|
||||
|
||||
struct config_tree *create_config_tree(const char *filename, int keep_open);
|
||||
struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
|
||||
const char *config_settings);
|
||||
int override_config_tree_from_string(struct cmd_context *cmd,
|
||||
const char *config_settings);
|
||||
void destroy_config_tree(struct config_tree *cft);
|
||||
|
||||
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const void *buf, uint32_t size);
|
||||
@@ -110,4 +112,6 @@ int get_config_str(const struct config_node *cn, const char *path,
|
||||
|
||||
unsigned maybe_config_section(const char *str, unsigned len);
|
||||
|
||||
const char *config_parent_name(const struct config_node *n);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -32,12 +32,16 @@
|
||||
#define DEFAULT_PROC_DIR "/proc"
|
||||
#define DEFAULT_SYSFS_SCAN 1
|
||||
#define DEFAULT_MD_COMPONENT_DETECTION 1
|
||||
#define DEFAULT_MD_CHUNK_ALIGNMENT 1
|
||||
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
|
||||
#define DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION 1
|
||||
#define DEFAULT_DATA_ALIGNMENT_DETECTION 1
|
||||
|
||||
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
|
||||
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"
|
||||
#define DEFAULT_FALLBACK_TO_LOCAL_LOCKING 1
|
||||
#define DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING 1
|
||||
#define DEFAULT_WAIT_FOR_LOCKS 1
|
||||
|
||||
#define DEFAULT_MIRRORLOG "disk"
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
@@ -64,6 +68,12 @@
|
||||
#define DEFAULT_PVMETADATACOPIES 1
|
||||
#define DEFAULT_LABELSECTOR UINT64_C(1)
|
||||
#define DEFAULT_READ_AHEAD "auto"
|
||||
#define DEFAULT_UDEV_SYNC 0
|
||||
#define DEFAULT_EXTENT_SIZE 4096 /* In KB */
|
||||
#define DEFAULT_MAX_PV 0
|
||||
#define DEFAULT_MAX_LV 0
|
||||
#define DEFAULT_ALLOC_POLICY ALLOC_NORMAL
|
||||
#define DEFAULT_CLUSTERED 0
|
||||
|
||||
#define DEFAULT_MSG_PREFIX " "
|
||||
#define DEFAULT_CMD_NAME 0
|
||||
@@ -90,7 +100,7 @@
|
||||
# define DEFAULT_ACTIVATION 0
|
||||
#endif
|
||||
|
||||
#define DEFAULT_STRIPE_FILLER "/dev/ioerror"
|
||||
#define DEFAULT_STRIPE_FILLER "error"
|
||||
#define DEFAULT_MIRROR_REGION_SIZE 512 /* KB */
|
||||
#define DEFAULT_INTERVAL 15
|
||||
|
||||
@@ -100,20 +110,23 @@
|
||||
|
||||
#define DEFAULT_REP_ALIGNED 1
|
||||
#define DEFAULT_REP_BUFFERED 1
|
||||
#define DEFAULT_REP_COLUMNS_AS_ROWS 0
|
||||
#define DEFAULT_REP_HEADINGS 1
|
||||
#define DEFAULT_REP_PREFIXES 0
|
||||
#define DEFAULT_REP_QUOTED 1
|
||||
#define DEFAULT_REP_SEPARATOR " "
|
||||
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent"
|
||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent,convert_lv"
|
||||
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
|
||||
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
|
||||
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
|
||||
#define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
|
||||
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,lv_uuid"
|
||||
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,convert_lv,lv_uuid"
|
||||
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
|
||||
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
|
||||
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
|
||||
#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
|
||||
#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size,lv_name,seg_start_pe,segtype,seg_pe_ranges"
|
||||
|
||||
#define DEFAULT_LVS_SORT "vg_name,lv_name"
|
||||
#define DEFAULT_VGS_SORT "vg_name"
|
||||
@@ -121,4 +134,7 @@
|
||||
#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
|
||||
#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
|
||||
|
||||
#define DEFAULT_MIRROR_DEVICE_FAULT_POLICY "remove"
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -87,10 +87,8 @@ int btree_insert(struct btree *t, uint32_t k, void *data)
|
||||
struct node *p, **c = _lookup(&t->root, key, &p), *n;
|
||||
|
||||
if (!*c) {
|
||||
if (!(n = dm_pool_alloc(t->mem, sizeof(*n)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(n = dm_pool_alloc(t->mem, sizeof(*n))))
|
||||
return_0;
|
||||
|
||||
n->key = key;
|
||||
n->data = data;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Initialise a list before use.
|
||||
* The list head's next and previous pointers point back to itself.
|
||||
*/
|
||||
void list_init(struct list *head)
|
||||
void dm_list_init(struct dm_list *head)
|
||||
{
|
||||
head->n = head->p = head;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ void list_init(struct list *head)
|
||||
* Insert an element before 'head'.
|
||||
* If 'head' is the list head, this adds an element to the end of the list.
|
||||
*/
|
||||
void list_add(struct list *head, struct list *elem)
|
||||
void dm_list_add(struct dm_list *head, struct dm_list *elem)
|
||||
{
|
||||
assert(head->n);
|
||||
|
||||
@@ -43,7 +43,7 @@ void list_add(struct list *head, struct list *elem)
|
||||
* Insert an element after 'head'.
|
||||
* If 'head' is the list head, this adds an element to the front of the list.
|
||||
*/
|
||||
void list_add_h(struct list *head, struct list *elem)
|
||||
void dm_list_add_h(struct dm_list *head, struct dm_list *elem)
|
||||
{
|
||||
assert(head->n);
|
||||
|
||||
@@ -59,16 +59,25 @@ void list_add_h(struct list *head, struct list *elem)
|
||||
* Note that this doesn't change the element itself - it may still be safe
|
||||
* to follow its pointers.
|
||||
*/
|
||||
void list_del(struct list *elem)
|
||||
void dm_list_del(struct dm_list *elem)
|
||||
{
|
||||
elem->n->p = elem->p;
|
||||
elem->p->n = elem->n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an element from existing list and insert before 'head'.
|
||||
*/
|
||||
void dm_list_move(struct dm_list *head, struct dm_list *elem)
|
||||
{
|
||||
dm_list_del(elem);
|
||||
dm_list_add(head, elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
*/
|
||||
int list_empty(const struct list *head)
|
||||
int dm_list_empty(const struct dm_list *head)
|
||||
{
|
||||
return head->n == head;
|
||||
}
|
||||
@@ -76,7 +85,7 @@ int list_empty(const struct list *head)
|
||||
/*
|
||||
* Is this the first element of the list?
|
||||
*/
|
||||
int list_start(const struct list *head, const struct list *elem)
|
||||
int dm_list_start(const struct dm_list *head, const struct dm_list *elem)
|
||||
{
|
||||
return elem->p == head;
|
||||
}
|
||||
@@ -84,7 +93,7 @@ int list_start(const struct list *head, const struct list *elem)
|
||||
/*
|
||||
* Is this the last element of the list?
|
||||
*/
|
||||
int list_end(const struct list *head, const struct list *elem)
|
||||
int dm_list_end(const struct dm_list *head, const struct dm_list *elem)
|
||||
{
|
||||
return elem->n == head;
|
||||
}
|
||||
@@ -92,44 +101,44 @@ int list_end(const struct list *head, const struct list *elem)
|
||||
/*
|
||||
* Return first element of the list or NULL if empty
|
||||
*/
|
||||
struct list *list_first(const struct list *head)
|
||||
struct dm_list *dm_list_first(const struct dm_list *head)
|
||||
{
|
||||
return (list_empty(head) ? NULL : head->n);
|
||||
return (dm_list_empty(head) ? NULL : head->n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return last element of the list or NULL if empty
|
||||
*/
|
||||
struct list *list_last(const struct list *head)
|
||||
struct dm_list *dm_list_last(const struct dm_list *head)
|
||||
{
|
||||
return (list_empty(head) ? NULL : head->p);
|
||||
return (dm_list_empty(head) ? NULL : head->p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the previous element of the list, or NULL if we've reached the start.
|
||||
*/
|
||||
struct list *list_prev(const struct list *head, const struct list *elem)
|
||||
struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem)
|
||||
{
|
||||
return (list_start(head, elem) ? NULL : elem->p);
|
||||
return (dm_list_start(head, elem) ? NULL : elem->p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next element of the list, or NULL if we've reached the end.
|
||||
*/
|
||||
struct list *list_next(const struct list *head, const struct list *elem)
|
||||
struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem)
|
||||
{
|
||||
return (list_end(head, elem) ? NULL : elem->n);
|
||||
return (dm_list_end(head, elem) ? NULL : elem->n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of elements in a list by walking it.
|
||||
*/
|
||||
unsigned int list_size(const struct list *head)
|
||||
unsigned int dm_list_size(const struct dm_list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
const struct dm_list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
dm_list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
|
||||
@@ -24,101 +24,106 @@
|
||||
* The list head's pointers point to the first and the last element.
|
||||
*/
|
||||
|
||||
struct list {
|
||||
struct list *n, *p;
|
||||
struct dm_list {
|
||||
struct dm_list *n, *p;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialise a list before use.
|
||||
* The list head's next and previous pointers point back to itself.
|
||||
*/
|
||||
#define LIST_INIT(name) struct list name = { &(name), &(name) }
|
||||
void list_init(struct list *head);
|
||||
#define DM_LIST_INIT(name) struct dm_list name = { &(name), &(name) }
|
||||
void dm_list_init(struct dm_list *head);
|
||||
|
||||
/*
|
||||
* Insert an element before 'head'.
|
||||
* If 'head' is the list head, this adds an element to the end of the list.
|
||||
*/
|
||||
void list_add(struct list *head, struct list *elem);
|
||||
void dm_list_add(struct dm_list *head, struct dm_list *elem);
|
||||
|
||||
/*
|
||||
* Insert an element after 'head'.
|
||||
* If 'head' is the list head, this adds an element to the front of the list.
|
||||
*/
|
||||
void list_add_h(struct list *head, struct list *elem);
|
||||
void dm_list_add_h(struct dm_list *head, struct dm_list *elem);
|
||||
|
||||
/*
|
||||
* Delete an element from its list.
|
||||
* Note that this doesn't change the element itself - it may still be safe
|
||||
* to follow its pointers.
|
||||
*/
|
||||
void list_del(struct list *elem);
|
||||
void dm_list_del(struct dm_list *elem);
|
||||
|
||||
/*
|
||||
* Remove an element from existing list and insert before 'head'.
|
||||
*/
|
||||
void dm_list_move(struct dm_list *head, struct dm_list *elem);
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
*/
|
||||
int list_empty(const struct list *head);
|
||||
int dm_list_empty(const struct dm_list *head);
|
||||
|
||||
/*
|
||||
* Is this the first element of the list?
|
||||
*/
|
||||
int list_start(const struct list *head, const struct list *elem);
|
||||
int dm_list_start(const struct dm_list *head, const struct dm_list *elem);
|
||||
|
||||
/*
|
||||
* Is this the last element of the list?
|
||||
*/
|
||||
int list_end(const struct list *head, const struct list *elem);
|
||||
int dm_list_end(const struct dm_list *head, const struct dm_list *elem);
|
||||
|
||||
/*
|
||||
* Return first element of the list or NULL if empty
|
||||
*/
|
||||
struct list *list_first(const struct list *head);
|
||||
struct dm_list *dm_list_first(const struct dm_list *head);
|
||||
|
||||
/*
|
||||
* Return last element of the list or NULL if empty
|
||||
*/
|
||||
struct list *list_last(const struct list *head);
|
||||
struct dm_list *dm_list_last(const struct dm_list *head);
|
||||
|
||||
/*
|
||||
* Return the previous element of the list, or NULL if we've reached the start.
|
||||
*/
|
||||
struct list *list_prev(const struct list *head, const struct list *elem);
|
||||
struct dm_list *dm_list_prev(const struct dm_list *head, const struct dm_list *elem);
|
||||
|
||||
/*
|
||||
* Return the next element of the list, or NULL if we've reached the end.
|
||||
*/
|
||||
struct list *list_next(const struct list *head, const struct list *elem);
|
||||
struct dm_list *dm_list_next(const struct dm_list *head, const struct dm_list *elem);
|
||||
|
||||
/*
|
||||
* Given the address v of an instance of 'struct list' called 'head'
|
||||
* Given the address v of an instance of 'struct dm_list' called 'head'
|
||||
* contained in a structure of type t, return the containing structure.
|
||||
*/
|
||||
#define list_struct_base(v, t, head) \
|
||||
#define dm_list_struct_base(v, t, head) \
|
||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->head))
|
||||
|
||||
/*
|
||||
* Given the address v of an instance of 'struct list list' contained in
|
||||
* Given the address v of an instance of 'struct dm_list list' contained in
|
||||
* a structure of type t, return the containing structure.
|
||||
*/
|
||||
#define list_item(v, t) list_struct_base((v), t, list)
|
||||
#define dm_list_item(v, t) dm_list_struct_base((v), t, list)
|
||||
|
||||
/*
|
||||
* Given the address v of one known element e in a known structure of type t,
|
||||
* return another element f.
|
||||
*/
|
||||
#define struct_field(v, t, e, f) \
|
||||
#define dm_struct_field(v, t, e, f) \
|
||||
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
|
||||
|
||||
/*
|
||||
* Given the address v of a known element e in a known structure of type t,
|
||||
* return the list head 'list'
|
||||
*/
|
||||
#define list_head(v, t, e) struct_field(v, t, e, list)
|
||||
#define dm_list_head(v, t, e) dm_struct_field(v, t, e, list)
|
||||
|
||||
/*
|
||||
* Set v to each element of a list in turn.
|
||||
*/
|
||||
#define list_iterate(v, head) \
|
||||
#define dm_list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
/*
|
||||
@@ -128,7 +133,7 @@ struct list *list_next(const struct list *head, const struct list *elem);
|
||||
* already-processed elements.
|
||||
* If 'start' is 'head' it walks the list backwards.
|
||||
*/
|
||||
#define list_uniterate(v, head, start) \
|
||||
#define dm_list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
/*
|
||||
@@ -136,68 +141,68 @@ struct list *list_next(const struct list *head, const struct list *elem);
|
||||
* the way.
|
||||
* t must be defined as a temporary variable of the same type as v.
|
||||
*/
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
#define dm_list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
/*
|
||||
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||
* The containing structure should be the same type as 'v'.
|
||||
* The 'struct list' variable within the containing structure is 'field'.
|
||||
* The 'struct dm_list' variable within the containing structure is 'field'.
|
||||
*/
|
||||
#define list_iterate_items_gen(v, head, field) \
|
||||
for (v = list_struct_base((head)->n, typeof(*v), field); \
|
||||
#define dm_list_iterate_items_gen(v, head, field) \
|
||||
for (v = dm_list_struct_base((head)->n, typeof(*v), field); \
|
||||
&v->field != (head); \
|
||||
v = list_struct_base(v->field.n, typeof(*v), field))
|
||||
v = dm_list_struct_base(v->field.n, typeof(*v), field))
|
||||
|
||||
/*
|
||||
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||
* The containing structure should be the same type as 'v'.
|
||||
* The list should be 'struct list list' within the containing structure.
|
||||
* The list should be 'struct dm_list list' within the containing structure.
|
||||
*/
|
||||
#define list_iterate_items(v, head) list_iterate_items_gen(v, (head), list)
|
||||
#define dm_list_iterate_items(v, head) dm_list_iterate_items_gen(v, (head), list)
|
||||
|
||||
/*
|
||||
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||
* The containing structure should be the same type as 'v'.
|
||||
* The 'struct list' variable within the containing structure is 'field'.
|
||||
* The 'struct dm_list' variable within the containing structure is 'field'.
|
||||
* t must be defined as a temporary variable of the same type as v.
|
||||
*/
|
||||
#define list_iterate_items_gen_safe(v, t, head, field) \
|
||||
for (v = list_struct_base((head)->n, typeof(*v), field), \
|
||||
t = list_struct_base(v->field.n, typeof(*v), field); \
|
||||
#define dm_list_iterate_items_gen_safe(v, t, head, field) \
|
||||
for (v = dm_list_struct_base((head)->n, typeof(*v), field), \
|
||||
t = dm_list_struct_base(v->field.n, typeof(*v), field); \
|
||||
&v->field != (head); \
|
||||
v = t, t = list_struct_base(v->field.n, typeof(*v), field))
|
||||
v = t, t = dm_list_struct_base(v->field.n, typeof(*v), field))
|
||||
/*
|
||||
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||
* The containing structure should be the same type as 'v'.
|
||||
* The list should be 'struct list list' within the containing structure.
|
||||
* The list should be 'struct dm_list list' within the containing structure.
|
||||
* t must be defined as a temporary variable of the same type as v.
|
||||
*/
|
||||
#define list_iterate_items_safe(v, t, head) \
|
||||
list_iterate_items_gen_safe(v, t, (head), list)
|
||||
#define dm_list_iterate_items_safe(v, t, head) \
|
||||
dm_list_iterate_items_gen_safe(v, t, (head), list)
|
||||
|
||||
/*
|
||||
* Walk a list backwards, setting 'v' in turn to the containing structure
|
||||
* of each item.
|
||||
* The containing structure should be the same type as 'v'.
|
||||
* The 'struct list' variable within the containing structure is 'field'.
|
||||
* The 'struct dm_list' variable within the containing structure is 'field'.
|
||||
*/
|
||||
#define list_iterate_back_items_gen(v, head, field) \
|
||||
for (v = list_struct_base((head)->p, typeof(*v), field); \
|
||||
#define dm_list_iterate_back_items_gen(v, head, field) \
|
||||
for (v = dm_list_struct_base((head)->p, typeof(*v), field); \
|
||||
&v->field != (head); \
|
||||
v = list_struct_base(v->field.p, typeof(*v), field))
|
||||
v = dm_list_struct_base(v->field.p, typeof(*v), field))
|
||||
|
||||
/*
|
||||
* Walk a list backwards, setting 'v' in turn to the containing structure
|
||||
* of each item.
|
||||
* The containing structure should be the same type as 'v'.
|
||||
* The list should be 'struct list list' within the containing structure.
|
||||
* The list should be 'struct dm_list list' within the containing structure.
|
||||
*/
|
||||
#define list_iterate_back_items(v, head) list_iterate_back_items_gen(v, (head), list)
|
||||
#define dm_list_iterate_back_items(v, head) dm_list_iterate_back_items_gen(v, (head), list)
|
||||
|
||||
/*
|
||||
* Return the number of elements in a list by walking it.
|
||||
*/
|
||||
unsigned int list_size(const struct list *head);
|
||||
unsigned int dm_list_size(const struct dm_list *head);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,17 +16,16 @@
|
||||
#ifndef _LVM_TYPES_H
|
||||
#define _LVM_TYPES_H
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/* Define some portable printing types */
|
||||
#define PRIsize_t "zu"
|
||||
#define PRIptrdiff_t "td"
|
||||
#define PRIpid_t PRId32
|
||||
|
||||
struct str_list {
|
||||
struct list list;
|
||||
struct dm_list list;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,68 +16,62 @@
|
||||
#include "lib.h"
|
||||
#include "str_list.h"
|
||||
|
||||
struct list *str_list_create(struct dm_pool *mem)
|
||||
struct dm_list *str_list_create(struct dm_pool *mem)
|
||||
{
|
||||
struct list *sl;
|
||||
struct dm_list *sl;
|
||||
|
||||
if (!(sl = dm_pool_alloc(mem, sizeof(struct list)))) {
|
||||
stack;
|
||||
if (!(sl = dm_pool_alloc(mem, sizeof(struct dm_list)))) {
|
||||
log_errno(ENOMEM, "str_list allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_init(sl);
|
||||
dm_list_init(sl);
|
||||
|
||||
return sl;
|
||||
}
|
||||
|
||||
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str)
|
||||
int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str)
|
||||
{
|
||||
struct str_list *sln;
|
||||
|
||||
if (!str) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!str)
|
||||
return_0;
|
||||
|
||||
/* Already in list? */
|
||||
if (str_list_match_item(sll, str))
|
||||
return 1;
|
||||
|
||||
if (!(sln = dm_pool_alloc(mem, sizeof(*sln)))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(sln = dm_pool_alloc(mem, sizeof(*sln))))
|
||||
return_0;
|
||||
|
||||
sln->str = str;
|
||||
list_add(sll, &sln->list);
|
||||
dm_list_add(sll, &sln->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int str_list_del(struct list *sll, const char *str)
|
||||
int str_list_del(struct dm_list *sll, const char *str)
|
||||
{
|
||||
struct list *slh, *slht;
|
||||
struct dm_list *slh, *slht;
|
||||
|
||||
list_iterate_safe(slh, slht, sll) {
|
||||
if (!strcmp(str, list_item(slh, struct str_list)->str))
|
||||
list_del(slh);
|
||||
dm_list_iterate_safe(slh, slht, sll) {
|
||||
if (!strcmp(str, dm_list_item(slh, struct str_list)->str))
|
||||
dm_list_del(slh);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int str_list_dup(struct dm_pool *mem, struct list *sllnew,
|
||||
const struct list *sllold)
|
||||
int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
|
||||
const struct dm_list *sllold)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
list_init(sllnew);
|
||||
dm_list_init(sllnew);
|
||||
|
||||
list_iterate_items(sl, sllold) {
|
||||
if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
dm_list_iterate_items(sl, sllold) {
|
||||
if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -86,11 +80,11 @@ int str_list_dup(struct dm_pool *mem, struct list *sllnew,
|
||||
/*
|
||||
* Is item on list?
|
||||
*/
|
||||
int str_list_match_item(const struct list *sll, const char *str)
|
||||
int str_list_match_item(const struct dm_list *sll, const char *str)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
list_iterate_items(sl, sll)
|
||||
dm_list_iterate_items(sl, sll)
|
||||
if (!strcmp(str, sl->str))
|
||||
return 1;
|
||||
|
||||
@@ -100,11 +94,11 @@ int str_list_match_item(const struct list *sll, const char *str)
|
||||
/*
|
||||
* Is at least one item on both lists?
|
||||
*/
|
||||
int str_list_match_list(const struct list *sll, const struct list *sll2)
|
||||
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
list_iterate_items(sl, sll)
|
||||
dm_list_iterate_items(sl, sll)
|
||||
if (str_list_match_item(sll2, sl->str))
|
||||
return 1;
|
||||
|
||||
@@ -114,14 +108,14 @@ int str_list_match_list(const struct list *sll, const struct list *sll2)
|
||||
/*
|
||||
* Do both lists contain the same set of items?
|
||||
*/
|
||||
int str_list_lists_equal(const struct list *sll, const struct list *sll2)
|
||||
int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2)
|
||||
{
|
||||
struct str_list *sl;
|
||||
|
||||
if (list_size(sll) != list_size(sll2))
|
||||
if (dm_list_size(sll) != dm_list_size(sll2))
|
||||
return 0;
|
||||
|
||||
list_iterate_items(sl, sll)
|
||||
dm_list_iterate_items(sl, sll)
|
||||
if (!str_list_match_item(sll2, sl->str))
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
#ifndef _LVM_STR_LIST_H
|
||||
#define _LVM_STR_LIST_H
|
||||
|
||||
struct list *str_list_create(struct dm_pool *mem);
|
||||
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str);
|
||||
int str_list_del(struct list *sll, const char *str);
|
||||
int str_list_match_item(const struct list *sll, const char *str);
|
||||
int str_list_match_list(const struct list *sll, const struct list *sll2);
|
||||
int str_list_lists_equal(const struct list *sll, const struct list *sll2);
|
||||
int str_list_dup(struct dm_pool *mem, struct list *sllnew,
|
||||
const struct list *sllold);
|
||||
struct dm_list *str_list_create(struct dm_pool *mem);
|
||||
int str_list_add(struct dm_pool *mem, struct dm_list *sll, const char *str);
|
||||
int str_list_del(struct dm_list *sll, const char *str);
|
||||
int str_list_match_item(const struct dm_list *sll, const char *str);
|
||||
int str_list_match_list(const struct dm_list *sll, const struct dm_list *sll2);
|
||||
int str_list_lists_equal(const struct dm_list *sll, const struct dm_list *sll2);
|
||||
int str_list_dup(struct dm_pool *mem, struct dm_list *sllnew,
|
||||
const struct dm_list *sllold);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -31,7 +31,7 @@ struct dev_iter {
|
||||
};
|
||||
|
||||
struct dir_list {
|
||||
struct list list;
|
||||
struct dm_list list;
|
||||
char dir[0];
|
||||
};
|
||||
|
||||
@@ -42,8 +42,8 @@ static struct {
|
||||
struct dm_regex *preferred_names_matcher;
|
||||
|
||||
int has_scanned;
|
||||
struct list dirs;
|
||||
struct list files;
|
||||
struct dm_list dirs;
|
||||
struct dm_list files;
|
||||
|
||||
} _cache;
|
||||
|
||||
@@ -97,15 +97,16 @@ struct device *dev_create_file(const char *filename, struct device *dev,
|
||||
}
|
||||
|
||||
dev->flags |= DEV_REGULAR;
|
||||
list_init(&dev->aliases);
|
||||
list_add(&dev->aliases, &alias->list);
|
||||
dm_list_init(&dev->aliases);
|
||||
dm_list_add(&dev->aliases, &alias->list);
|
||||
dev->end = UINT64_C(0);
|
||||
dev->dev = 0;
|
||||
dev->fd = -1;
|
||||
dev->open_count = 0;
|
||||
dev->block_size = -1;
|
||||
dev->read_ahead = -1;
|
||||
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||
list_init(&dev->open_list);
|
||||
dm_list_init(&dev->open_list);
|
||||
|
||||
return dev;
|
||||
}
|
||||
@@ -119,14 +120,15 @@ static struct device *_dev_create(dev_t d)
|
||||
return NULL;
|
||||
}
|
||||
dev->flags = 0;
|
||||
list_init(&dev->aliases);
|
||||
dm_list_init(&dev->aliases);
|
||||
dev->dev = d;
|
||||
dev->fd = -1;
|
||||
dev->open_count = 0;
|
||||
dev->block_size = -1;
|
||||
dev->read_ahead = -1;
|
||||
dev->end = UINT64_C(0);
|
||||
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||
list_init(&dev->open_list);
|
||||
dm_list_init(&dev->open_list);
|
||||
|
||||
return dev;
|
||||
}
|
||||
@@ -140,8 +142,8 @@ void dev_set_preferred_name(struct str_list *sl, struct device *dev)
|
||||
return;
|
||||
|
||||
log_debug("%s: New preferred name", sl->str);
|
||||
list_del(&sl->list);
|
||||
list_add_h(&dev->aliases, &sl->list);
|
||||
dm_list_del(&sl->list);
|
||||
dm_list_add_h(&dev->aliases, &sl->list);
|
||||
}
|
||||
|
||||
/* Return 1 if we prefer path1 else return 0 */
|
||||
@@ -236,26 +238,22 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
const char *oldpath;
|
||||
int prefer_old = 1;
|
||||
|
||||
if (!sl) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!sl)
|
||||
return_0;
|
||||
|
||||
/* Is name already there? */
|
||||
list_iterate_items(strl, &dev->aliases) {
|
||||
dm_list_iterate_items(strl, &dev->aliases) {
|
||||
if (!strcmp(strl->str, path)) {
|
||||
log_debug("%s: Already in device cache", path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(sl->str = dm_pool_strdup(_cache.mem, path))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(sl->str = dm_pool_strdup(_cache.mem, path)))
|
||||
return_0;
|
||||
|
||||
if (!list_empty(&dev->aliases)) {
|
||||
oldpath = list_item(dev->aliases.n, struct str_list)->str;
|
||||
if (!dm_list_empty(&dev->aliases)) {
|
||||
oldpath = dm_list_item(dev->aliases.n, struct str_list)->str;
|
||||
prefer_old = _compare_paths(path, oldpath);
|
||||
log_debug("%s: Aliased to %s in device cache%s",
|
||||
path, oldpath, prefer_old ? "" : " (preferred name)");
|
||||
@@ -264,9 +262,9 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
log_debug("%s: Added to device cache", path);
|
||||
|
||||
if (prefer_old)
|
||||
list_add(&dev->aliases, &sl->list);
|
||||
dm_list_add(&dev->aliases, &sl->list);
|
||||
else
|
||||
list_add_h(&dev->aliases, &sl->list);
|
||||
dm_list_add_h(&dev->aliases, &sl->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -294,29 +292,25 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
(uint32_t) d))) {
|
||||
/* create new device */
|
||||
if (loopfile) {
|
||||
if (!(dev = dev_create_file(path, NULL, NULL, 0))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
} else if (!(dev = _dev_create(d))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(dev = dev_create_file(path, NULL, NULL, 0)))
|
||||
return_0;
|
||||
} else if (!(dev = _dev_create(d)))
|
||||
return_0;
|
||||
|
||||
if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) {
|
||||
log_err("Couldn't insert device into binary tree.");
|
||||
log_error("Couldn't insert device into binary tree.");
|
||||
_free(dev);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!loopfile && !_add_alias(dev, path)) {
|
||||
log_err("Couldn't add alias to dev cache.");
|
||||
log_error("Couldn't add alias to dev cache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_hash_insert(_cache.names, path, dev)) {
|
||||
log_err("Couldn't add name to hash in dev cache.");
|
||||
log_error("Couldn't add name to hash in dev cache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -369,10 +363,8 @@ static int _insert_dir(const char *dir)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(path = _join(dir, dirent[n]->d_name))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(path = _join(dir, dirent[n]->d_name)))
|
||||
return_0;
|
||||
|
||||
_collapse_slashes(path);
|
||||
r &= _insert(path, 1);
|
||||
@@ -400,10 +392,8 @@ static int _insert_file(const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_insert_dev(path, 0)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_insert_dev(path, 0))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -439,10 +429,8 @@ static int _insert(const char *path, int rec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_insert_dev(path, info.st_rdev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!_insert_dev(path, info.st_rdev))
|
||||
return_0;
|
||||
|
||||
r = 1;
|
||||
}
|
||||
@@ -457,10 +445,10 @@ static void _full_scan(int dev_scan)
|
||||
if (_cache.has_scanned && !dev_scan)
|
||||
return;
|
||||
|
||||
list_iterate_items(dl, &_cache.dirs)
|
||||
dm_list_iterate_items(dl, &_cache.dirs)
|
||||
_insert_dir(dl->dir);
|
||||
|
||||
list_iterate_items(dl, &_cache.files)
|
||||
dm_list_iterate_items(dl, &_cache.files)
|
||||
_insert_file(dl->dir);
|
||||
|
||||
_cache.has_scanned = 1;
|
||||
@@ -502,7 +490,7 @@ static int _init_preferred_names(struct cmd_context *cmd)
|
||||
if (v->type != CFG_STRING) {
|
||||
log_error("preferred_names patterns must be enclosed in quotes");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
@@ -543,25 +531,22 @@ int dev_cache_init(struct cmd_context *cmd)
|
||||
_cache.names = NULL;
|
||||
_cache.has_scanned = 0;
|
||||
|
||||
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
|
||||
return_0;
|
||||
|
||||
if (!(_cache.names = dm_hash_create(128))) {
|
||||
stack;
|
||||
dm_pool_destroy(_cache.mem);
|
||||
_cache.mem = 0;
|
||||
return 0;
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!(_cache.devices = btree_create(_cache.mem))) {
|
||||
log_err("Couldn't create binary tree for dev-cache.");
|
||||
log_error("Couldn't create binary tree for dev-cache.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
list_init(&_cache.dirs);
|
||||
list_init(&_cache.files);
|
||||
dm_list_init(&_cache.dirs);
|
||||
dm_list_init(&_cache.files);
|
||||
|
||||
if (!_init_preferred_names(cmd))
|
||||
goto_bad;
|
||||
@@ -576,7 +561,7 @@ int dev_cache_init(struct cmd_context *cmd)
|
||||
static void _check_closed(struct device *dev)
|
||||
{
|
||||
if (dev->fd >= 0)
|
||||
log_err("Device '%s' has been left open.", dev_name(dev));
|
||||
log_error("Device '%s' has been left open.", dev_name(dev));
|
||||
}
|
||||
|
||||
static void _check_for_open_devices(void)
|
||||
@@ -604,8 +589,8 @@ void dev_cache_exit(void)
|
||||
|
||||
_cache.devices = NULL;
|
||||
_cache.has_scanned = 0;
|
||||
list_init(&_cache.dirs);
|
||||
list_init(&_cache.files);
|
||||
dm_list_init(&_cache.dirs);
|
||||
dm_list_init(&_cache.files);
|
||||
}
|
||||
|
||||
int dev_cache_add_dir(const char *path)
|
||||
@@ -630,7 +615,7 @@ int dev_cache_add_dir(const char *path)
|
||||
}
|
||||
|
||||
strcpy(dl->dir, path);
|
||||
list_add(&_cache.dirs, &dl->list);
|
||||
dm_list_add(&_cache.dirs, &dl->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -656,7 +641,7 @@ int dev_cache_add_loopfile(const char *path)
|
||||
}
|
||||
|
||||
strcpy(dl->dir, path);
|
||||
list_add(&_cache.files, &dl->list);
|
||||
dm_list_add(&_cache.files, &dl->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -673,7 +658,7 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
|
||||
if ((dev->flags & DEV_REGULAR))
|
||||
return dev_name(dev);
|
||||
|
||||
while ((r = stat(name = list_item(dev->aliases.n,
|
||||
while ((r = stat(name = dm_list_item(dev->aliases.n,
|
||||
struct str_list)->str, &buf)) ||
|
||||
(buf.st_rdev != dev->dev)) {
|
||||
if (r < 0) {
|
||||
@@ -697,14 +682,15 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
|
||||
/* Leave list alone if there isn't an alternative name */
|
||||
/* so dev_name will always find something to return. */
|
||||
/* Otherwise add the name to the correct device. */
|
||||
if (list_size(&dev->aliases) > 1) {
|
||||
list_del(dev->aliases.n);
|
||||
if (dm_list_size(&dev->aliases) > 1) {
|
||||
dm_list_del(dev->aliases.n);
|
||||
if (!r)
|
||||
_insert(name, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_error("Aborting - please provide new pathname for what "
|
||||
/* Scanning issues this inappropriately sometimes. */
|
||||
log_debug("Aborting - please provide new pathname for what "
|
||||
"used to be %s", name);
|
||||
return NULL;
|
||||
}
|
||||
@@ -792,6 +778,6 @@ int dev_fd(struct device *dev)
|
||||
|
||||
const char *dev_name(const struct device *dev)
|
||||
{
|
||||
return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
|
||||
return (dev) ? dm_list_item(dev->aliases.n, struct str_list)->str :
|
||||
"unknown device";
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static LIST_INIT(_open_devices);
|
||||
static DM_LIST_INIT(_open_devices);
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* The standard io loop that keeps submitting an io until it's
|
||||
@@ -170,10 +170,8 @@ static int _aligned_io(struct device_area *where, void *buffer,
|
||||
struct device_area widened;
|
||||
|
||||
if (!(where->dev->flags & DEV_REGULAR) &&
|
||||
!_get_block_size(where->dev, &block_size)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
!_get_block_size(where->dev, &block_size))
|
||||
return_0;
|
||||
|
||||
if (!block_size)
|
||||
block_size = lvm_getpagesize();
|
||||
@@ -200,10 +198,8 @@ static int _aligned_io(struct device_area *where, void *buffer,
|
||||
|
||||
/* channel the io through the bounce buffer */
|
||||
if (!_io(&widened, bounce, 0)) {
|
||||
if (!should_write) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!should_write)
|
||||
return_0;
|
||||
/* FIXME pre-extend the file */
|
||||
memset(bounce, '\n', widened.size);
|
||||
}
|
||||
@@ -266,18 +262,65 @@ static int _dev_get_size_dev(const struct device *dev, uint64_t *size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
|
||||
{
|
||||
long read_ahead_long;
|
||||
|
||||
if (dev->read_ahead != -1) {
|
||||
*read_ahead = (uint32_t) dev->read_ahead;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!dev_open(dev))
|
||||
return_0;
|
||||
|
||||
if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) {
|
||||
log_sys_error("ioctl BLKRAGET", dev_name(dev));
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
*read_ahead = (uint32_t) read_ahead_long;
|
||||
dev->read_ahead = read_ahead_long;
|
||||
|
||||
log_very_verbose("%s: read_ahead is %u sectors",
|
||||
dev_name(dev), *read_ahead);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* Public functions
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
int dev_get_size(const struct device *dev, uint64_t *size)
|
||||
{
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
if ((dev->flags & DEV_REGULAR))
|
||||
return _dev_get_size_file(dev, size);
|
||||
else
|
||||
return _dev_get_size_dev(dev, size);
|
||||
}
|
||||
|
||||
int dev_get_read_ahead(struct device *dev, uint32_t *read_ahead)
|
||||
{
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
if (dev->flags & DEV_REGULAR) {
|
||||
*read_ahead = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return _dev_read_ahead_dev(dev, read_ahead);
|
||||
}
|
||||
|
||||
/* FIXME Unused
|
||||
int dev_get_sectsize(struct device *dev, uint32_t *size)
|
||||
{
|
||||
@@ -340,7 +383,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
if (dev->open_count && !need_excl) {
|
||||
/* FIXME Ensure we never get here */
|
||||
log_debug("WARNING: %s already opened read-only",
|
||||
log_debug("WARNING: %s already opened read-only",
|
||||
dev_name(dev));
|
||||
dev->open_count++;
|
||||
}
|
||||
@@ -354,10 +397,8 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
|
||||
if (dev->flags & DEV_REGULAR)
|
||||
name = dev_name(dev);
|
||||
else if (!(name = dev_name_confirmed(dev, quiet))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
else if (!(name = dev_name_confirmed(dev, quiet)))
|
||||
return_0;
|
||||
|
||||
if (!(dev->flags & DEV_REGULAR)) {
|
||||
if (stat(name, &buf) < 0) {
|
||||
@@ -437,7 +478,7 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||
if ((flags & O_CREAT) && !(flags & O_TRUNC))
|
||||
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
|
||||
|
||||
list_add(&_open_devices, &dev->open_list);
|
||||
dm_list_add(&_open_devices, &dev->open_list);
|
||||
|
||||
log_debug("Opened %s %s%s%s", dev_name(dev),
|
||||
dev->flags & DEV_OPENED_RW ? "RW" : "RO",
|
||||
@@ -486,12 +527,12 @@ static void _close(struct device *dev)
|
||||
log_sys_error("close", dev_name(dev));
|
||||
dev->fd = -1;
|
||||
dev->block_size = -1;
|
||||
list_del(&dev->open_list);
|
||||
dm_list_del(&dev->open_list);
|
||||
|
||||
log_debug("Closed %s", dev_name(dev));
|
||||
|
||||
if (dev->flags & DEV_ALLOCED) {
|
||||
dm_free((void *) list_item(dev->aliases.n, struct str_list)->
|
||||
dm_free((void *) dm_list_item(dev->aliases.n, struct str_list)->
|
||||
str);
|
||||
dm_free(dev->aliases.n);
|
||||
dm_free(dev);
|
||||
@@ -522,8 +563,8 @@ static int _dev_close(struct device *dev, int immediate)
|
||||
|
||||
/* Close unless device is known to belong to a locked VG */
|
||||
if (immediate ||
|
||||
(dev->open_count < 1 &&
|
||||
(!(info = info_from_pvid(dev->pvid)) ||
|
||||
(dev->open_count < 1 &&
|
||||
(!(info = info_from_pvid(dev->pvid, 0)) ||
|
||||
!info->vginfo ||
|
||||
!vgname_is_locked(info->vginfo->vgname))))
|
||||
_close(dev);
|
||||
@@ -543,11 +584,11 @@ int dev_close_immediate(struct device *dev)
|
||||
|
||||
void dev_close_all(void)
|
||||
{
|
||||
struct list *doh, *doht;
|
||||
struct dm_list *doh, *doht;
|
||||
struct device *dev;
|
||||
|
||||
list_iterate_safe(doh, doht, &_open_devices) {
|
||||
dev = list_struct_base(doh, struct device, open_list);
|
||||
dm_list_iterate_safe(doh, doht, &_open_devices) {
|
||||
dev = dm_list_struct_base(doh, struct device, open_list);
|
||||
if (dev->open_count < 1)
|
||||
_close(dev);
|
||||
}
|
||||
@@ -557,10 +598,8 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct device_area where;
|
||||
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev->open_count)
|
||||
return_0;
|
||||
|
||||
where.dev = dev;
|
||||
where.start = offset;
|
||||
@@ -607,10 +646,8 @@ int dev_append(struct device *dev, size_t len, void *buffer)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev->open_count)
|
||||
return_0;
|
||||
|
||||
r = dev_write(dev, dev->end, len, buffer);
|
||||
dev->end += (uint64_t) len;
|
||||
@@ -625,10 +662,8 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||
{
|
||||
struct device_area where;
|
||||
|
||||
if (!dev->open_count) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev->open_count)
|
||||
return_0;
|
||||
|
||||
where.dev = dev;
|
||||
where.start = offset;
|
||||
@@ -644,10 +679,8 @@ int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
|
||||
size_t s;
|
||||
char buffer[4096] __attribute((aligned(8)));
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!dev_open(dev))
|
||||
return_0;
|
||||
|
||||
if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
|
||||
log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Luca Berra
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "lib.h"
|
||||
#include "metadata.h"
|
||||
#include "xlate.h"
|
||||
#include "filter.h"
|
||||
|
||||
#ifdef linux
|
||||
|
||||
@@ -48,18 +49,26 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
|
||||
* 1: At start of device
|
||||
* 2: 4K from start of device.
|
||||
*/
|
||||
static uint64_t _v1_sb_offset(uint64_t size, unsigned minor_version)
|
||||
typedef enum {
|
||||
MD_MINOR_VERSION_MIN,
|
||||
MD_MINOR_V0 = MD_MINOR_VERSION_MIN,
|
||||
MD_MINOR_V1,
|
||||
MD_MINOR_V2,
|
||||
MD_MINOR_VERSION_MAX = MD_MINOR_V2
|
||||
} md_minor_version_t;
|
||||
|
||||
static uint64_t _v1_sb_offset(uint64_t size, md_minor_version_t minor_version)
|
||||
{
|
||||
uint64_t sb_offset;
|
||||
uint64_t uninitialized_var(sb_offset);
|
||||
|
||||
switch(minor_version) {
|
||||
case 0:
|
||||
case MD_MINOR_V0:
|
||||
sb_offset = (size - 8 * 2) & ~(4 * 2 - 1ULL);
|
||||
break;
|
||||
case 1:
|
||||
case MD_MINOR_V1:
|
||||
sb_offset = 0;
|
||||
break;
|
||||
case 2:
|
||||
case MD_MINOR_V2:
|
||||
sb_offset = 4 * 2;
|
||||
break;
|
||||
}
|
||||
@@ -74,7 +83,7 @@ static uint64_t _v1_sb_offset(uint64_t size, unsigned minor_version)
|
||||
int dev_is_md(struct device *dev, uint64_t *sb)
|
||||
{
|
||||
int ret = 1;
|
||||
unsigned minor = 0;
|
||||
md_minor_version_t minor;
|
||||
uint64_t size, sb_offset;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
@@ -96,12 +105,13 @@ int dev_is_md(struct device *dev, uint64_t *sb)
|
||||
if (_dev_has_md_magic(dev, sb_offset))
|
||||
goto out;
|
||||
|
||||
minor = MD_MINOR_VERSION_MIN;
|
||||
/* Version 1, try v1.0 -> v1.2 */
|
||||
do {
|
||||
sb_offset = _v1_sb_offset(size, minor);
|
||||
if (_dev_has_md_magic(dev, sb_offset))
|
||||
goto out;
|
||||
} while (++minor <= 2);
|
||||
} while (++minor <= MD_MINOR_VERSION_MAX);
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -115,6 +125,197 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _md_sysfs_attribute_snprintf(char *path, size_t size,
|
||||
const char *sysfs_dir,
|
||||
struct device *blkdev,
|
||||
const char *attribute)
|
||||
{
|
||||
struct stat info;
|
||||
dev_t dev = blkdev->dev;
|
||||
int ret = -1;
|
||||
|
||||
if (!sysfs_dir || !*sysfs_dir)
|
||||
return ret;
|
||||
|
||||
check_md_major:
|
||||
if (MAJOR(dev) != md_major()) {
|
||||
if (get_primary_dev(sysfs_dir, blkdev, &dev))
|
||||
goto check_md_major;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dm_snprintf(path, size, "%s/dev/block/%d:%d/md/%s", sysfs_dir,
|
||||
(int)MAJOR(dev), (int)MINOR(dev), attribute);
|
||||
if (ret < 0) {
|
||||
log_error("dm_snprintf md %s failed", attribute);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (stat(path, &info) == -1) {
|
||||
if (errno != ENOENT) {
|
||||
log_sys_error("stat", path);
|
||||
return ret;
|
||||
}
|
||||
/* old sysfs structure */
|
||||
ret = dm_snprintf(path, size, "%s/block/md%d/md/%s",
|
||||
sysfs_dir, (int)MINOR(dev), attribute);
|
||||
if (ret < 0) {
|
||||
log_error("dm_snprintf old md %s failed", attribute);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _md_sysfs_attribute_scanf(const char *sysfs_dir,
|
||||
struct device *dev,
|
||||
const char *attribute_name,
|
||||
const char *attribute_fmt,
|
||||
void *attribute_value)
|
||||
{
|
||||
char path[PATH_MAX+1], buffer[64];
|
||||
FILE *fp;
|
||||
int ret = 0;
|
||||
|
||||
if (_md_sysfs_attribute_snprintf(path, PATH_MAX, sysfs_dir,
|
||||
dev, attribute_name) < 0)
|
||||
return ret;
|
||||
|
||||
if (!(fp = fopen(path, "r"))) {
|
||||
log_sys_error("fopen", path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
log_sys_error("fgets", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((ret = sscanf(buffer, attribute_fmt, attribute_value)) != 1) {
|
||||
log_error("%s sysfs attr %s not in expected format: %s",
|
||||
dev_name(dev), attribute_name, buffer);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (fclose(fp))
|
||||
log_sys_error("fclose", path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve chunk size from md device using sysfs.
|
||||
*/
|
||||
static unsigned long dev_md_chunk_size(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
const char *attribute = "chunk_size";
|
||||
unsigned long chunk_size_bytes = 0UL;
|
||||
|
||||
if (_md_sysfs_attribute_scanf(sysfs_dir, dev, attribute,
|
||||
"%lu", &chunk_size_bytes) != 1)
|
||||
return 0;
|
||||
|
||||
log_very_verbose("Device %s %s is %lu bytes.",
|
||||
dev_name(dev), attribute, chunk_size_bytes);
|
||||
|
||||
return chunk_size_bytes >> SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve level from md device using sysfs.
|
||||
*/
|
||||
static int dev_md_level(const char *sysfs_dir, struct device *dev)
|
||||
{
|
||||
const char *attribute = "level";
|
||||
int level = -1;
|
||||
|
||||
if (_md_sysfs_attribute_scanf(sysfs_dir, dev, attribute,
|
||||
"raid%d", &level) != 1)
|
||||
return -1;
|
||||
|
||||
log_very_verbose("Device %s %s is raid%d.",
|
||||
dev_name(dev), attribute, level);
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve raid_disks from md device using sysfs.
|
||||
*/
|
||||
static int dev_md_raid_disks(const char *sysfs_dir, struct device *dev)
|
||||
{
|
||||
const char *attribute = "raid_disks";
|
||||
int raid_disks = 0;
|
||||
|
||||
if (_md_sysfs_attribute_scanf(sysfs_dir, dev, attribute,
|
||||
"%d", &raid_disks) != 1)
|
||||
return 0;
|
||||
|
||||
log_very_verbose("Device %s %s is %d.",
|
||||
dev_name(dev), attribute, raid_disks);
|
||||
|
||||
return raid_disks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate stripe width of md device using its sysfs files.
|
||||
*/
|
||||
unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev)
|
||||
{
|
||||
unsigned long chunk_size_sectors = 0UL;
|
||||
unsigned long stripe_width_sectors = 0UL;
|
||||
int level, raid_disks, data_disks;
|
||||
|
||||
chunk_size_sectors = dev_md_chunk_size(sysfs_dir, dev);
|
||||
if (!chunk_size_sectors)
|
||||
return 0;
|
||||
|
||||
level = dev_md_level(sysfs_dir, dev);
|
||||
if (level < 0)
|
||||
return 0;
|
||||
|
||||
raid_disks = dev_md_raid_disks(sysfs_dir, dev);
|
||||
if (!raid_disks)
|
||||
return 0;
|
||||
|
||||
/* The raid level governs the number of data disks. */
|
||||
switch (level) {
|
||||
case 0:
|
||||
/* striped md does not have any parity disks */
|
||||
data_disks = raid_disks;
|
||||
break;
|
||||
case 1:
|
||||
case 10:
|
||||
/* mirrored md effectively has 1 data disk */
|
||||
data_disks = 1;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
/* both raid 4 and 5 have a single parity disk */
|
||||
data_disks = raid_disks - 1;
|
||||
break;
|
||||
case 6:
|
||||
/* raid 6 has 2 parity disks */
|
||||
data_disks = raid_disks - 2;
|
||||
break;
|
||||
default:
|
||||
log_error("Device %s has an unknown md raid level: %d",
|
||||
dev_name(dev), level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
stripe_width_sectors = chunk_size_sectors * data_disks;
|
||||
|
||||
log_very_verbose("Device %s stripe-width is %lu bytes.",
|
||||
dev_name(dev),
|
||||
stripe_width_sectors << SECTOR_SHIFT);
|
||||
|
||||
return stripe_width_sectors;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int dev_is_md(struct device *dev __attribute((unused)),
|
||||
@@ -123,4 +324,10 @@ int dev_is_md(struct device *dev __attribute((unused)),
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long dev_md_stripe_width(const char *sysfs_dir __attribute((unused)),
|
||||
struct device *dev __attribute((unused)))
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
87
lib/device/dev-swap.c
Normal file
87
lib/device/dev-swap.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "metadata.h"
|
||||
#include "xlate.h"
|
||||
#include "filter.h"
|
||||
|
||||
#ifdef linux
|
||||
|
||||
#define MAX_PAGESIZE (64 * 1024)
|
||||
#define SIGNATURE_SIZE 10
|
||||
|
||||
static int
|
||||
_swap_detect_signature(const char *buf)
|
||||
{
|
||||
if (memcmp(buf, "SWAP-SPACE", 10) == 0 ||
|
||||
memcmp(buf, "SWAPSPACE2", 10) == 0)
|
||||
return 1;
|
||||
|
||||
if (memcmp(buf, "S1SUSPEND", 9) == 0 ||
|
||||
memcmp(buf, "S2SUSPEND", 9) == 0 ||
|
||||
memcmp(buf, "ULSUSPEND", 9) == 0 ||
|
||||
memcmp(buf, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_is_swap(struct device *dev, uint64_t *signature)
|
||||
{
|
||||
char buf[10];
|
||||
uint64_t size;
|
||||
int page;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dev_open(dev)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*signature = 0;
|
||||
|
||||
for (page = 0x1000; page <= MAX_PAGESIZE; page <<= 1) {
|
||||
/*
|
||||
* skip 32k pagesize since this does not seem to be supported
|
||||
*/
|
||||
if (page == 0x8000)
|
||||
continue;
|
||||
if (size < page)
|
||||
break;
|
||||
if (!dev_read(dev, page - SIGNATURE_SIZE,
|
||||
SIGNATURE_SIZE, buf)) {
|
||||
stack;
|
||||
return -1;
|
||||
}
|
||||
if (_swap_detect_signature(buf)) {
|
||||
*signature = page - SIGNATURE_SIZE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev_close(dev))
|
||||
stack;
|
||||
|
||||
if (*signature)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -13,6 +13,7 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <libgen.h> /* dirname, basename */
|
||||
#include "lib.h"
|
||||
#include "lvm-types.h"
|
||||
#include "device.h"
|
||||
@@ -27,22 +28,26 @@
|
||||
#define PART_OFFSET UINT64_C(0x1BE)
|
||||
|
||||
struct partition {
|
||||
uint8_t boot_ind;
|
||||
uint8_t head;
|
||||
uint8_t sector;
|
||||
uint8_t cyl;
|
||||
uint8_t sys_ind; /* partition type */
|
||||
uint8_t end_head;
|
||||
uint8_t end_sector;
|
||||
uint8_t end_cyl;
|
||||
uint32_t start_sect;
|
||||
uint32_t nr_sects;
|
||||
uint8_t boot_ind;
|
||||
uint8_t head;
|
||||
uint8_t sector;
|
||||
uint8_t cyl;
|
||||
uint8_t sys_ind; /* partition type */
|
||||
uint8_t end_head;
|
||||
uint8_t end_sector;
|
||||
uint8_t end_cyl;
|
||||
uint32_t start_sect;
|
||||
uint32_t nr_sects;
|
||||
} __attribute__((packed));
|
||||
|
||||
static int _is_partitionable(struct device *dev)
|
||||
{
|
||||
int parts = max_partitions(MAJOR(dev->dev));
|
||||
|
||||
/* All MD devices are partitionable via blkext (as of 2.6.28) */
|
||||
if (MAJOR(dev->dev) == md_major())
|
||||
return 1;
|
||||
|
||||
if ((parts <= 1) || (MINOR(dev->dev) % parts))
|
||||
return 0;
|
||||
|
||||
@@ -62,10 +67,8 @@ static int _has_partition_table(struct device *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf)) {
|
||||
stack;
|
||||
goto out;
|
||||
}
|
||||
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf))
|
||||
goto_out;
|
||||
|
||||
/* FIXME Check for other types of partition table too */
|
||||
|
||||
@@ -280,3 +283,208 @@ int _get_partition_type(struct dev_mgr *dm, struct device *d)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef linux
|
||||
|
||||
int get_primary_dev(const char *sysfs_dir,
|
||||
struct device *dev, dev_t *result)
|
||||
{
|
||||
char path[PATH_MAX+1];
|
||||
char temp_path[PATH_MAX+1];
|
||||
char buffer[64];
|
||||
struct stat info;
|
||||
FILE *fp;
|
||||
uint32_t pri_maj, pri_min;
|
||||
int ret = 0;
|
||||
|
||||
/* check if dev is a partition */
|
||||
if (dm_snprintf(path, PATH_MAX, "%s/dev/block/%d:%d/partition",
|
||||
sysfs_dir, (int)MAJOR(dev->dev), (int)MINOR(dev->dev)) < 0) {
|
||||
log_error("dm_snprintf partition failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (stat(path, &info) == -1) {
|
||||
if (errno != ENOENT)
|
||||
log_sys_error("stat", path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* extract parent's path from the partition's symlink, e.g.:
|
||||
* - readlink /sys/dev/block/259:0 = ../../block/md0/md0p1
|
||||
* - dirname ../../block/md0/md0p1 = ../../block/md0
|
||||
* - basename ../../block/md0/md0 = md0
|
||||
* Parent's 'dev' sysfs attribute = /sys/block/md0/dev
|
||||
*/
|
||||
if (readlink(dirname(path), temp_path, PATH_MAX) < 0) {
|
||||
log_sys_error("readlink", path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dm_snprintf(path, PATH_MAX, "%s/block/%s/dev",
|
||||
sysfs_dir, basename(dirname(temp_path))) < 0) {
|
||||
log_error("dm_snprintf dev failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* finally, parse 'dev' attribute and create corresponding dev_t */
|
||||
if (stat(path, &info) == -1) {
|
||||
if (errno == ENOENT)
|
||||
log_error("sysfs file %s does not exist", path);
|
||||
else
|
||||
log_sys_error("stat", path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fp = fopen(path, "r");
|
||||
if (!fp) {
|
||||
log_sys_error("fopen", path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
log_sys_error("fgets", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sscanf(buffer, "%d:%d", &pri_maj, &pri_min) != 2) {
|
||||
log_error("sysfs file %s not in expected MAJ:MIN format: %s",
|
||||
path, buffer);
|
||||
goto out;
|
||||
}
|
||||
*result = MKDEV(pri_maj, pri_min);
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
if (fclose(fp))
|
||||
log_sys_error("fclose", path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long _dev_topology_attribute(const char *attribute,
|
||||
const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
const char *sysfs_fmt_str = "%s/dev/block/%d:%d/%s";
|
||||
char path[PATH_MAX+1], buffer[64];
|
||||
FILE *fp;
|
||||
struct stat info;
|
||||
dev_t uninitialized_var(primary);
|
||||
unsigned long result = 0UL;
|
||||
|
||||
if (!attribute || !*attribute)
|
||||
return_0;
|
||||
|
||||
if (!sysfs_dir || !*sysfs_dir)
|
||||
return_0;
|
||||
|
||||
if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev),
|
||||
attribute) < 0) {
|
||||
log_error("dm_snprintf %s failed", attribute);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if the desired sysfs attribute exists
|
||||
* - if not: either the kernel doesn't have topology support
|
||||
* or the device could be a partition
|
||||
*/
|
||||
if (stat(path, &info) == -1) {
|
||||
if (errno != ENOENT) {
|
||||
log_sys_error("stat", path);
|
||||
return 0;
|
||||
}
|
||||
if (!get_primary_dev(sysfs_dir, dev, &primary))
|
||||
return 0;
|
||||
|
||||
/* get attribute from partition's primary device */
|
||||
if (dm_snprintf(path, PATH_MAX, sysfs_fmt_str, sysfs_dir,
|
||||
(int)MAJOR(primary), (int)MINOR(primary),
|
||||
attribute) < 0) {
|
||||
log_error("primary dm_snprintf %s failed", attribute);
|
||||
return 0;
|
||||
}
|
||||
if (stat(path, &info) == -1) {
|
||||
if (errno != ENOENT)
|
||||
log_sys_error("stat", path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(fp = fopen(path, "r"))) {
|
||||
log_sys_error("fopen", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
log_sys_error("fgets", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sscanf(buffer, "%lu", &result) != 1) {
|
||||
log_error("sysfs file %s not in expected format: %s", path,
|
||||
buffer);
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_very_verbose("Device %s %s is %lu bytes.",
|
||||
dev_name(dev), attribute, result);
|
||||
|
||||
out:
|
||||
if (fclose(fp))
|
||||
log_sys_error("fclose", path);
|
||||
|
||||
return result >> SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
unsigned long dev_alignment_offset(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return _dev_topology_attribute("alignment_offset",
|
||||
sysfs_dir, dev);
|
||||
}
|
||||
|
||||
unsigned long dev_minimum_io_size(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return _dev_topology_attribute("queue/minimum_io_size",
|
||||
sysfs_dir, dev);
|
||||
}
|
||||
|
||||
unsigned long dev_optimal_io_size(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return _dev_topology_attribute("queue/optimal_io_size",
|
||||
sysfs_dir, dev);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int get_primary_dev(const char *sysfs_dir,
|
||||
struct device *dev, dev_t *result)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long dev_alignment_offset(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
unsigned long dev_minimum_io_size(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
unsigned long dev_optimal_io_size(const char *sysfs_dir,
|
||||
struct device *dev)
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,23 +33,24 @@
|
||||
* pointer comparisons are valid.
|
||||
*/
|
||||
struct device {
|
||||
struct list aliases; /* struct str_list from lvm-types.h */
|
||||
struct dm_list aliases; /* struct str_list from lvm-types.h */
|
||||
dev_t dev;
|
||||
|
||||
/* private */
|
||||
int fd;
|
||||
int open_count;
|
||||
int block_size;
|
||||
int read_ahead;
|
||||
uint32_t flags;
|
||||
uint64_t end;
|
||||
struct list open_list;
|
||||
struct dm_list open_list;
|
||||
|
||||
char pvid[ID_LEN + 1];
|
||||
char _padding[7];
|
||||
};
|
||||
|
||||
struct device_list {
|
||||
struct list list;
|
||||
struct dm_list list;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
@@ -64,6 +65,7 @@ struct device_area {
|
||||
*/
|
||||
int dev_get_size(const struct device *dev, uint64_t *size);
|
||||
int dev_get_sectsize(struct device *dev, uint32_t *size);
|
||||
int dev_get_read_ahead(struct device *dev, uint32_t *read_ahead);
|
||||
|
||||
/* Use quiet version if device number could change e.g. when opening LV */
|
||||
int dev_open(struct device *dev);
|
||||
@@ -93,12 +95,21 @@ const char *dev_name_confirmed(struct device *dev, int quiet);
|
||||
|
||||
/* Does device contain md superblock? If so, where? */
|
||||
int dev_is_md(struct device *dev, uint64_t *sb);
|
||||
|
||||
/* FIXME Check partition type if appropriate */
|
||||
|
||||
#define is_lvm_partition(a) 1
|
||||
/* int is_lvm_partition(const char *name); */
|
||||
int dev_is_swap(struct device *dev, uint64_t *signature);
|
||||
unsigned long dev_md_stripe_width(const char *sysfs_dir, struct device *dev);
|
||||
|
||||
int is_partitioned_dev(struct device *dev);
|
||||
|
||||
int get_primary_dev(const char *sysfs_dir,
|
||||
struct device *dev, dev_t *result);
|
||||
|
||||
unsigned long dev_alignment_offset(const char *sysfs_dir,
|
||||
struct device *dev);
|
||||
|
||||
unsigned long dev_minimum_io_size(const char *sysfs_dir,
|
||||
struct device *dev);
|
||||
|
||||
unsigned long dev_optimal_io_size(const char *sysfs_dir,
|
||||
struct device *dev);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
|
||||
|
||||
static struct {
|
||||
static const struct {
|
||||
alloc_policy_t alloc;
|
||||
const char *str;
|
||||
const char str[12]; /* must be changed when size extends 11 chars */
|
||||
} _policies[] = {
|
||||
{
|
||||
ALLOC_CONTIGUOUS, "contiguous"}, {
|
||||
@@ -36,7 +36,7 @@ static struct {
|
||||
ALLOC_INHERIT, "inherit"}
|
||||
};
|
||||
|
||||
static int _num_policies = sizeof(_policies) / sizeof(*_policies);
|
||||
static const int _num_policies = sizeof(_policies) / sizeof(*_policies);
|
||||
|
||||
uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||
{
|
||||
@@ -62,14 +62,14 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||
v = UINT64_C(1);
|
||||
*unit_type = *units;
|
||||
break;
|
||||
case 's':
|
||||
v *= SECTOR_SIZE;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
v *= UINT64_C(1);
|
||||
break;
|
||||
#define KILO UINT64_C(1024)
|
||||
case 's':
|
||||
v *= (KILO/2);
|
||||
break;
|
||||
case 'k':
|
||||
v *= KILO;
|
||||
break;
|
||||
@@ -90,6 +90,9 @@ uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||
break;
|
||||
#undef KILO
|
||||
#define KILO UINT64_C(1000)
|
||||
case 'S':
|
||||
v *= (KILO/2);
|
||||
break;
|
||||
case 'K':
|
||||
v *= KILO;
|
||||
break;
|
||||
@@ -155,7 +158,7 @@ static const char *_display_size(const struct cmd_context *cmd,
|
||||
uint64_t byte = UINT64_C(0);
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
const char *size_str[][3] = {
|
||||
const char * const size_str[][3] = {
|
||||
{" Exabyte", " EB", "E"},
|
||||
{" Petabyte", " PB", "P"},
|
||||
{" Terabyte", " TB", "T"},
|
||||
@@ -266,11 +269,11 @@ void pvdisplay_segments(const struct physical_volume *pv)
|
||||
if (pv->pe_size)
|
||||
log_print("--- Physical Segments ---");
|
||||
|
||||
list_iterate_items(pvseg, &pv->segments) {
|
||||
dm_list_iterate_items(pvseg, &pv->segments) {
|
||||
log_print("Physical extent %u to %u:",
|
||||
pvseg->pe, pvseg->pe + pvseg->len - 1);
|
||||
|
||||
if (pvseg->lvseg) {
|
||||
if (pvseg_is_allocated(pvseg)) {
|
||||
log_print(" Logical volume\t%s%s/%s",
|
||||
pvseg->lvseg->lv->vg->cmd->dev_dir,
|
||||
pvseg->lvseg->lv->vg->name,
|
||||
@@ -307,7 +310,8 @@ void pvdisplay_full(const struct cmd_context *cmd,
|
||||
|
||||
log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
|
||||
log_print("PV Name %s", pv_dev_name(pv));
|
||||
log_print("VG Name %s%s", pv->vg_name,
|
||||
log_print("VG Name %s%s",
|
||||
is_orphan(pv) ? "" : pv->vg_name,
|
||||
pv->status & EXPORTED_VG ? " (exported)" : "");
|
||||
|
||||
data_size = (uint64_t) pv->pe_count * pv->pe_size;
|
||||
@@ -360,10 +364,8 @@ int pvdisplay_short(const struct cmd_context *cmd __attribute((unused)),
|
||||
if (!pv)
|
||||
return 0;
|
||||
|
||||
if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
|
||||
log_print("PV Name %s ", pv_dev_name(pv));
|
||||
/* FIXME pv->pv_number); */
|
||||
@@ -407,10 +409,8 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
struct lv_segment *snap_seg = NULL;
|
||||
float snap_percent; /* fused, fsize; */
|
||||
|
||||
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
|
||||
inkernel = lv_info(cmd, lv, &info, 1, 1) && info.exists;
|
||||
|
||||
@@ -428,7 +428,7 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
if (lv_is_origin(lv)) {
|
||||
log_print("LV snapshot status source of");
|
||||
|
||||
list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
|
||||
dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
|
||||
origin_list) {
|
||||
if (inkernel &&
|
||||
(snap_active = lv_snapshot_percent(snap_seg->cow,
|
||||
@@ -486,7 +486,7 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
display_size(cmd, (uint64_t) snap_seg->chunk_size));
|
||||
}
|
||||
|
||||
log_print("Segments %u", list_size(&lv->segments));
|
||||
log_print("Segments %u", dm_list_size(&lv->segments));
|
||||
|
||||
/********* FIXME Stripes & stripesize for each segment
|
||||
log_print("Stripe size (KByte) %u", lv->stripesize / 2);
|
||||
@@ -554,7 +554,7 @@ int lvdisplay_segments(const struct logical_volume *lv)
|
||||
|
||||
log_print("--- Segments ---");
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
dm_list_iterate_items(seg, &lv->segments) {
|
||||
log_print("Logical extent %u to %u:",
|
||||
seg->le, seg->le + seg->len - 1);
|
||||
|
||||
@@ -575,14 +575,11 @@ void vgdisplay_extents(const struct volume_group *vg __attribute((unused)))
|
||||
|
||||
void vgdisplay_full(const struct volume_group *vg)
|
||||
{
|
||||
uint32_t access;
|
||||
uint32_t access_str;
|
||||
uint32_t active_pvs;
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (vg->status & PARTIAL_VG)
|
||||
active_pvs = list_size(&vg->pvs);
|
||||
else
|
||||
active_pvs = vg->pv_count;
|
||||
active_pvs = vg->pv_count - vg_missing_pv_count(vg);
|
||||
|
||||
log_print("--- Volume group ---");
|
||||
log_print("VG Name %s", vg->name);
|
||||
@@ -590,28 +587,29 @@ void vgdisplay_full(const struct volume_group *vg)
|
||||
log_print("Format %s", vg->fid->fmt->name);
|
||||
if (vg->fid->fmt->features & FMT_MDAS) {
|
||||
log_print("Metadata Areas %d",
|
||||
list_size(&vg->fid->metadata_areas));
|
||||
dm_list_size(&vg->fid->metadata_areas));
|
||||
log_print("Metadata Sequence No %d", vg->seqno);
|
||||
}
|
||||
access = vg->status & (LVM_READ | LVM_WRITE);
|
||||
access_str = vg->status & (LVM_READ | LVM_WRITE);
|
||||
log_print("VG Access %s%s%s%s",
|
||||
access == (LVM_READ | LVM_WRITE) ? "read/write" : "",
|
||||
access == LVM_READ ? "read" : "",
|
||||
access == LVM_WRITE ? "write" : "",
|
||||
access == 0 ? "error" : "");
|
||||
access_str == (LVM_READ | LVM_WRITE) ? "read/write" : "",
|
||||
access_str == LVM_READ ? "read" : "",
|
||||
access_str == LVM_WRITE ? "write" : "",
|
||||
access_str == 0 ? "error" : "");
|
||||
log_print("VG Status %s%sresizable",
|
||||
vg->status & EXPORTED_VG ? "exported/" : "",
|
||||
vg->status & RESIZEABLE_VG ? "" : "NOT ");
|
||||
/* vg number not part of LVM2 design
|
||||
log_print ("VG # %u\n", vg->vg_number);
|
||||
*/
|
||||
if (vg->status & CLUSTERED) {
|
||||
if (vg_is_clustered(vg)) {
|
||||
log_print("Clustered yes");
|
||||
log_print("Shared %s",
|
||||
vg->status & SHARED ? "yes" : "no");
|
||||
}
|
||||
|
||||
log_print("MAX LV %u", vg->max_lv);
|
||||
log_print("Cur LV %u", vg->lv_count + vg->snapshot_count);
|
||||
log_print("Cur LV %u", vg_visible_lvs(vg));
|
||||
log_print("Open LV %u", lvs_in_vg_opened(vg));
|
||||
/****** FIXME Max LV Size
|
||||
log_print ( "MAX LV Size %s",
|
||||
@@ -638,8 +636,7 @@ void vgdisplay_full(const struct volume_group *vg)
|
||||
vg->extent_size));
|
||||
|
||||
log_print("Free PE / Size %u / %s", vg->free_count,
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->free_count * vg->extent_size));
|
||||
display_size(vg->cmd, vg_free(vg)));
|
||||
|
||||
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
@@ -655,26 +652,23 @@ void vgdisplay_full(const struct volume_group *vg)
|
||||
void vgdisplay_colons(const struct volume_group *vg)
|
||||
{
|
||||
uint32_t active_pvs;
|
||||
const char *access;
|
||||
const char *access_str;
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
|
||||
if (vg->status & PARTIAL_VG)
|
||||
active_pvs = list_size(&vg->pvs);
|
||||
else
|
||||
active_pvs = vg->pv_count;
|
||||
active_pvs = vg->pv_count - vg_missing_pv_count(vg);
|
||||
|
||||
switch (vg->status & (LVM_READ | LVM_WRITE)) {
|
||||
case LVM_READ | LVM_WRITE:
|
||||
access = "r/w";
|
||||
access_str = "r/w";
|
||||
break;
|
||||
case LVM_READ:
|
||||
access = "r";
|
||||
access_str = "r";
|
||||
break;
|
||||
case LVM_WRITE:
|
||||
access = "w";
|
||||
access_str = "w";
|
||||
break;
|
||||
default:
|
||||
access = "";
|
||||
access_str = "";
|
||||
}
|
||||
|
||||
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
|
||||
@@ -685,11 +679,11 @@ void vgdisplay_colons(const struct volume_group *vg)
|
||||
log_print("%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
|
||||
":%u:%u:%u:%s",
|
||||
vg->name,
|
||||
access,
|
||||
access_str,
|
||||
vg->status,
|
||||
/* internal volume group number; obsolete */
|
||||
vg->max_lv,
|
||||
vg->lv_count,
|
||||
vg_visible_lvs(vg),
|
||||
lvs_in_vg_opened(vg),
|
||||
/* FIXME: maximum logical volume size */
|
||||
vg->max_pv,
|
||||
@@ -698,7 +692,7 @@ void vgdisplay_colons(const struct volume_group *vg)
|
||||
(uint64_t) vg->extent_count * (vg->extent_size / 2),
|
||||
vg->extent_size / 2,
|
||||
vg->extent_count,
|
||||
vg->extent_count - vg->free_count,
|
||||
vg->extent_count - vg->free_count,
|
||||
vg->free_count,
|
||||
uuid[0] ? uuid : "none");
|
||||
return;
|
||||
@@ -713,8 +707,7 @@ void vgdisplay_short(const struct volume_group *vg)
|
||||
display_size(vg->cmd,
|
||||
((uint64_t) vg->extent_count -
|
||||
vg->free_count) * vg->extent_size),
|
||||
display_size(vg->cmd,
|
||||
(uint64_t) vg->free_count * vg->extent_size));
|
||||
display_size(vg->cmd, vg_free(vg)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -722,7 +715,7 @@ void display_formats(const struct cmd_context *cmd)
|
||||
{
|
||||
const struct format_type *fmt;
|
||||
|
||||
list_iterate_items(fmt, &cmd->formats) {
|
||||
dm_list_iterate_items(fmt, &cmd->formats) {
|
||||
log_print("%s", fmt->name);
|
||||
}
|
||||
}
|
||||
@@ -731,7 +724,7 @@ void display_segtypes(const struct cmd_context *cmd)
|
||||
{
|
||||
const struct segment_type *segtype;
|
||||
|
||||
list_iterate_items(segtype, &cmd->segtypes) {
|
||||
dm_list_iterate_items(segtype, &cmd->segtypes) {
|
||||
log_print("%s", segtype->name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,14 +51,17 @@ static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
|
||||
return dm_tree_node_add_error_target(node, len);
|
||||
}
|
||||
|
||||
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
|
||||
static int _errseg_target_present(struct cmd_context *cmd,
|
||||
const struct lv_segment *seg __attribute((unused)),
|
||||
unsigned *attributes __attribute((unused)))
|
||||
{
|
||||
static int _errseg_checked = 0;
|
||||
static int _errseg_present = 0;
|
||||
|
||||
/* Reported truncated in older kernels */
|
||||
if (!_errseg_checked &&
|
||||
(target_present("error", 0) || target_present("erro", 0)))
|
||||
(target_present(cmd, "error", 0) ||
|
||||
target_present(cmd, "erro", 0)))
|
||||
_errseg_present = 1;
|
||||
|
||||
_errseg_checked = 1;
|
||||
@@ -68,7 +71,7 @@ static int _errseg_target_present(const struct lv_segment *seg __attribute((unus
|
||||
|
||||
static int _errseg_modules_needed(struct dm_pool *mem,
|
||||
const struct lv_segment *seg __attribute((unused)),
|
||||
struct list *modules)
|
||||
struct dm_list *modules)
|
||||
{
|
||||
if (!str_list_add(mem, modules, "error")) {
|
||||
log_error("error module string list allocation failed");
|
||||
@@ -77,7 +80,7 @@ static int _errseg_modules_needed(struct dm_pool *mem,
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void _errseg_destroy(const struct segment_type *segtype)
|
||||
{
|
||||
dm_free((void *)segtype);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -50,10 +50,8 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
||||
{
|
||||
struct dev_filter **filters_copy, *cft;
|
||||
|
||||
if (!filters) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!filters)
|
||||
return_NULL;
|
||||
|
||||
if (!(filters_copy = dm_malloc(sizeof(*filters) * (n + 1)))) {
|
||||
log_error("composite filters allocation failed");
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
#ifdef linux
|
||||
|
||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
|
||||
static int _ignore_md(struct dev_filter *f __attribute((unused)),
|
||||
struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "dev-cache.h"
|
||||
#include "filter-persistent.h"
|
||||
#include "lvm-file.h"
|
||||
#include "lvm-string.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -42,10 +43,8 @@ static int _init_hash(struct pfilter *pf)
|
||||
if (pf->devices)
|
||||
dm_hash_destroy(pf->devices);
|
||||
|
||||
if (!(pf->devices = dm_hash_create(128))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(pf->devices = dm_hash_create(128)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -99,13 +98,13 @@ int persistent_filter_load(struct dev_filter *f, struct config_tree **cft_out)
|
||||
{
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
struct config_tree *cft;
|
||||
struct stat info;
|
||||
struct stat info;
|
||||
int r = 0;
|
||||
|
||||
if (!stat(pf->file, &info))
|
||||
if (!stat(pf->file, &info))
|
||||
pf->ctime = info.st_ctime;
|
||||
else {
|
||||
log_very_verbose("%s: stat failed: %s", pf->file,
|
||||
log_very_verbose("%s: stat failed: %s", pf->file,
|
||||
strerror(errno));
|
||||
return_0;
|
||||
}
|
||||
@@ -144,6 +143,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
|
||||
{
|
||||
void *d;
|
||||
int first = 1;
|
||||
char *buf, *str;
|
||||
struct dm_hash_node *n;
|
||||
|
||||
for (n = dm_hash_get_first(pf->devices); n;
|
||||
@@ -160,7 +160,13 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
|
||||
first = 0;
|
||||
}
|
||||
|
||||
fprintf(fp, "\t\t\"%s\"", dm_hash_get_key(pf->devices, n));
|
||||
str = dm_hash_get_key(pf->devices, n);
|
||||
if (!(buf = alloca(escaped_len(str)))) {
|
||||
log_error("persistent filter device path stack "
|
||||
"allocation failed");
|
||||
return;
|
||||
}
|
||||
fprintf(fp, "\t\t\"%s\"", escape_double_quotes(buf, str));
|
||||
}
|
||||
|
||||
if (!first)
|
||||
@@ -171,7 +177,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
|
||||
|
||||
int persistent_filter_dump(struct dev_filter *f)
|
||||
{
|
||||
struct pfilter *pf = (struct pfilter *) f->private;
|
||||
struct pfilter *pf;
|
||||
char *tmp_file;
|
||||
struct stat info, info2;
|
||||
struct config_tree *cft = NULL;
|
||||
@@ -179,6 +185,10 @@ int persistent_filter_dump(struct dev_filter *f)
|
||||
int lockfd;
|
||||
int r = 0;
|
||||
|
||||
if (!f)
|
||||
return_0;
|
||||
pf = (struct pfilter *) f->private;
|
||||
|
||||
if (!dm_hash_get_num_entries(pf->devices)) {
|
||||
log_very_verbose("Internal persistent device cache empty "
|
||||
"- not writing to %s", pf->file);
|
||||
@@ -267,7 +277,7 @@ static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||
l = pf->real->passes_filter(pf->real, dev) ?
|
||||
PF_GOOD_DEVICE : PF_BAD_DEVICE;
|
||||
|
||||
list_iterate_items(sl, &dev->aliases)
|
||||
dm_list_iterate_items(sl, &dev->aliases)
|
||||
dm_hash_insert(pf->devices, sl->str, l);
|
||||
|
||||
} else if (l == PF_BAD_DEVICE)
|
||||
@@ -293,10 +303,8 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
||||
struct pfilter *pf;
|
||||
struct dev_filter *f = NULL;
|
||||
|
||||
if (!(pf = dm_malloc(sizeof(*pf)))) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!(pf = dm_malloc(sizeof(*pf))))
|
||||
return_NULL;
|
||||
memset(pf, 0, sizeof(*pf));
|
||||
|
||||
if (!(pf->file = dm_malloc(strlen(file) + 1)))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
@@ -70,10 +70,8 @@ static int _extract_pattern(struct dm_pool *mem, const char *pat,
|
||||
/*
|
||||
* copy the regex
|
||||
*/
|
||||
if (!(r = dm_pool_strdup(mem, pat))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
if (!(r = dm_pool_strdup(mem, pat)))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* trim the trailing character, having checked it's sep.
|
||||
@@ -153,7 +151,7 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
||||
struct rfilter *rf = (struct rfilter *) f->private;
|
||||
struct str_list *sl;
|
||||
|
||||
list_iterate_items(sl, &dev->aliases) {
|
||||
dm_list_iterate_items(sl, &dev->aliases) {
|
||||
m = dm_regex_match(rf->engine, sl->str);
|
||||
|
||||
if (m >= 0) {
|
||||
@@ -192,10 +190,8 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
|
||||
struct rfilter *rf;
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!mem) {
|
||||
stack;
|
||||
return NULL;
|
||||
}
|
||||
if (!mem)
|
||||
return_NULL;
|
||||
|
||||
if (!(rf = dm_pool_alloc(mem, sizeof(*rf))))
|
||||
goto_bad;
|
||||
|
||||
@@ -20,47 +20,11 @@
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
static int _locate_sysfs_blocks(const char *proc, char *path, size_t len,
|
||||
static int _locate_sysfs_blocks(const char *sysfs_dir, char *path, size_t len,
|
||||
unsigned *sysfs_depth)
|
||||
{
|
||||
char proc_mounts[PATH_MAX];
|
||||
FILE *fp;
|
||||
char *split[4], buffer[PATH_MAX + 16];
|
||||
const char *sys_mnt = NULL;
|
||||
struct stat info;
|
||||
|
||||
if (!*proc) {
|
||||
log_verbose("No proc filesystem found: skipping sysfs filter");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
|
||||
"%s/mounts", proc) < 0) {
|
||||
log_error("Failed to create /proc/mounts string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(fp = fopen(proc_mounts, "r"))) {
|
||||
log_sys_error("fopen %s", proc_mounts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp)) {
|
||||
if (dm_split_words(buffer, 4, 0, split) == 4 &&
|
||||
!strcmp(split[2], "sysfs")) {
|
||||
sys_mnt = split[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(fp))
|
||||
log_sys_error("fclose", proc_mounts);
|
||||
|
||||
if (!sys_mnt) {
|
||||
log_error("Failed to find sysfs mount point");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* unified classification directory for all kernel subsystems
|
||||
*
|
||||
@@ -70,7 +34,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len,
|
||||
* `-- sr0 -> ../../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
|
||||
*
|
||||
*/
|
||||
if (dm_snprintf(path, len, "%s/%s", sys_mnt,
|
||||
if (dm_snprintf(path, len, "%s/%s", sysfs_dir,
|
||||
"subsystem/block/devices") >= 0) {
|
||||
if (!stat(path, &info)) {
|
||||
*sysfs_depth = 0;
|
||||
@@ -87,7 +51,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len,
|
||||
* `-- sr0 -> ../../devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0/block/sr0
|
||||
*
|
||||
*/
|
||||
if (dm_snprintf(path, len, "%s/%s", sys_mnt, "class/block") >= 0) {
|
||||
if (dm_snprintf(path, len, "%s/%s", sysfs_dir, "class/block") >= 0) {
|
||||
if (!stat(path, &info)) {
|
||||
*sysfs_depth = 0;
|
||||
return 1;
|
||||
@@ -112,7 +76,7 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len,
|
||||
* ...
|
||||
*
|
||||
*/
|
||||
if (dm_snprintf(path, len, "%s/%s", sys_mnt, "block") >= 0) {
|
||||
if (dm_snprintf(path, len, "%s/%s", sysfs_dir, "block") >= 0) {
|
||||
if (!stat(path, &info)) {
|
||||
*sysfs_depth = 1;
|
||||
return 1;
|
||||
@@ -236,21 +200,21 @@ static int _read_dev(const char *file, dev_t *result)
|
||||
*/
|
||||
static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
|
||||
{
|
||||
struct dirent *d;
|
||||
DIR *dr;
|
||||
struct dirent *d;
|
||||
DIR *dr;
|
||||
struct stat info;
|
||||
char path[PATH_MAX];
|
||||
char file[PATH_MAX];
|
||||
dev_t dev = { 0 };
|
||||
int r = 1;
|
||||
|
||||
if (!(dr = opendir(dir))) {
|
||||
log_sys_error("opendir", dir);
|
||||
return 0;
|
||||
}
|
||||
if (!(dr = opendir(dir))) {
|
||||
log_sys_error("opendir", dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((d = readdir(dr))) {
|
||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||
while ((d = readdir(dr))) {
|
||||
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
|
||||
@@ -278,8 +242,8 @@ static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
|
||||
}
|
||||
}
|
||||
|
||||
if (closedir(dr))
|
||||
log_sys_error("closedir", dir);
|
||||
if (closedir(dr))
|
||||
log_sys_error("closedir", dir);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -321,7 +285,7 @@ static void _destroy(struct dev_filter *f)
|
||||
dm_pool_destroy(ds->mem);
|
||||
}
|
||||
|
||||
struct dev_filter *sysfs_filter_create(const char *proc)
|
||||
struct dev_filter *sysfs_filter_create(const char *sysfs_dir)
|
||||
{
|
||||
char sys_block[PATH_MAX];
|
||||
unsigned sysfs_depth;
|
||||
@@ -329,7 +293,12 @@ struct dev_filter *sysfs_filter_create(const char *proc)
|
||||
struct dev_set *ds;
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block), &sysfs_depth))
|
||||
if (!*sysfs_dir) {
|
||||
log_verbose("No proc filesystem found: skipping sysfs filter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_locate_sysfs_blocks(sysfs_dir, sys_block, sizeof(sys_block), &sysfs_depth))
|
||||
return NULL;
|
||||
|
||||
if (!(mem = dm_pool_create("sysfs", 256))) {
|
||||
@@ -357,7 +326,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
|
||||
|
||||
#else
|
||||
|
||||
struct dev_filter *sysfs_filter_create(const char *proc __attribute((unused)))
|
||||
struct dev_filter *sysfs_filter_create(const char *sysfs_dir __attribute((unused)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@
|
||||
#include "config.h"
|
||||
#include "dev-cache.h"
|
||||
|
||||
struct dev_filter *sysfs_filter_create(const char *proc);
|
||||
struct dev_filter *sysfs_filter_create(const char *sysfs_dir);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -57,6 +57,7 @@ static const device_info_t device_info[] = {
|
||||
{"ide", 64}, /* IDE disk */
|
||||
{"sd", 16}, /* SCSI disk */
|
||||
{"md", 1}, /* Multiple Disk driver (SoftRAID) */
|
||||
{"mdp", 1}, /* Partitionable MD */
|
||||
{"loop", 1}, /* Loop device */
|
||||
{"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
|
||||
{"dac960", 8}, /* DAC960 */
|
||||
@@ -77,6 +78,9 @@ static const device_info_t device_info[] = {
|
||||
{"xvd", 16}, /* Xen virtual block device */
|
||||
{"vdisk", 8}, /* SUN's LDOM virtual block device */
|
||||
{"ps3disk", 16}, /* PlayStation 3 internal disk */
|
||||
{"virtblk", 8}, /* VirtIO disk */
|
||||
{"mmc", 16}, /* MMC block device */
|
||||
{"blkext", 1}, /* Extended device partitions */
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
@@ -277,9 +281,8 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||
f->private = NULL;
|
||||
|
||||
if (!_scan_proc_dev(proc, cn)) {
|
||||
stack;
|
||||
dm_free(f);
|
||||
return NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user