mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-25 20:23:49 +03:00
Compare commits
1242 Commits
dm_v1_02_2
...
old-v2_02_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
448f8c4240 | ||
|
|
5a414c6ad1 | ||
|
|
65a942f01f | ||
|
|
6df32fed62 | ||
|
|
1199b48cd7 | ||
|
|
c493f56e1b | ||
|
|
2e65b8ce5f | ||
|
|
42a6d954d3 | ||
|
|
8f73b4c3ae | ||
|
|
adcd06fccb | ||
|
|
c40380f72a | ||
|
|
8e44e884a2 | ||
|
|
e2368be912 | ||
|
|
7986fd4db7 | ||
|
|
6107f4a02a | ||
|
|
2ce63814e9 | ||
|
|
8ba508f8f7 | ||
|
|
2100490424 | ||
|
|
7e7639e39a | ||
|
|
3555d0ecd5 | ||
|
|
ecb9a01cfa | ||
|
|
ca352ebfba | ||
|
|
29c73eb67b | ||
|
|
2a598ff24d | ||
|
|
f6d5837e5e | ||
|
|
dac8cee72c | ||
|
|
e01a2f8324 | ||
|
|
a092ccb82b | ||
|
|
e894d07b92 | ||
|
|
befef6eb00 | ||
|
|
162224979d | ||
|
|
a90f6e2dda | ||
|
|
e449bfd741 | ||
|
|
8ecc1eb99d | ||
|
|
1fb910411e | ||
|
|
3141b86d01 | ||
|
|
f8ff64c87e | ||
|
|
c71b834aad | ||
|
|
a78e7d0287 | ||
|
|
09cf0fe6b9 | ||
|
|
13713bc147 | ||
|
|
9c17cf4edf | ||
|
|
938b25b986 | ||
|
|
040b76f1e6 | ||
|
|
66226207ce | ||
|
|
999b4168c1 | ||
|
|
9bfc452487 | ||
|
|
df675ed9fb | ||
|
|
4a13ae4c95 | ||
|
|
5287c71d68 | ||
|
|
827f1a3d30 | ||
|
|
f6d95e19c4 | ||
|
|
3eb93f161f | ||
|
|
801eff0c52 | ||
|
|
c1993e76c2 | ||
|
|
c23f56b9cb | ||
|
|
44e17e2aa9 | ||
|
|
84758667c1 | ||
|
|
8c71113cd6 | ||
|
|
79ba99811c | ||
|
|
55a664d6fd | ||
|
|
b4affd607d | ||
|
|
c7007c98d7 | ||
|
|
fa684a97da | ||
|
|
cad03afc54 | ||
|
|
fe6d782751 | ||
|
|
dfe517cfbe | ||
|
|
46ab95f24c | ||
|
|
9a57ea4c4a | ||
|
|
5fc98ffa69 | ||
|
|
814eb397e1 | ||
|
|
77f030956c | ||
|
|
ab7ad3451d | ||
|
|
1107f82824 | ||
|
|
2bc2378033 | ||
|
|
676e214f34 | ||
|
|
7df1ccbf91 | ||
|
|
82d3ee5454 | ||
|
|
fcb6fb00e0 | ||
|
|
4e09e6ca10 | ||
|
|
af6dd44048 | ||
|
|
d30ec9fd1e | ||
|
|
16ee54ad23 | ||
|
|
627409ec38 | ||
|
|
4ead572462 | ||
|
|
42783a54db | ||
|
|
84763527c5 | ||
|
|
1744c1c2ba | ||
|
|
7ef5fbdbe6 | ||
|
|
b1482c52b7 | ||
|
|
7b0d61b96d | ||
|
|
951b974c4d | ||
|
|
975b3c3428 | ||
|
|
f0420012e6 | ||
|
|
30e5413e2b | ||
|
|
5077a1bb83 | ||
|
|
a8ed16de33 | ||
|
|
ee0a4914d5 | ||
|
|
8b70a0d0b7 | ||
|
|
8e7c6b60fb | ||
|
|
fbb0bb63e7 | ||
|
|
46dc1b6e99 | ||
|
|
82b34e06f2 | ||
|
|
bc178df8f0 | ||
|
|
d5a3de5a97 | ||
|
|
b8774d7aac | ||
|
|
891246562f | ||
|
|
e53a955115 | ||
|
|
1ec6812246 | ||
|
|
e896691b0f | ||
|
|
fbe92a13c0 | ||
|
|
94a434e9e7 | ||
|
|
e829c626da | ||
|
|
837adeea7f | ||
|
|
65d6350d36 | ||
|
|
ba99186951 | ||
|
|
b3975f5098 | ||
|
|
b90f909289 | ||
|
|
d098e4def6 | ||
|
|
835b0d9f62 | ||
|
|
9fea2798e3 | ||
|
|
394cae5d21 | ||
|
|
7996aae5e9 | ||
|
|
9788b9d7a9 | ||
|
|
6f5e1c3d73 | ||
|
|
d4421b12ba | ||
|
|
099b03f038 | ||
|
|
f84d2eeec9 | ||
|
|
f02531802c | ||
|
|
375cb5c31d | ||
|
|
8f2ba4ec3c | ||
|
|
9935d1183a | ||
|
|
aff8e77bec | ||
|
|
c9fd743c65 | ||
|
|
7a4fa925fc | ||
|
|
ff442c1e28 | ||
|
|
5cedaa972a | ||
|
|
2c8f647e0c | ||
|
|
3be5edae0e | ||
|
|
1078f24d5a | ||
|
|
c02cc5321a | ||
|
|
e60a7ff1d0 | ||
|
|
91de7311d7 | ||
|
|
e357c9fc0c | ||
|
|
ec4daa5936 | ||
|
|
2743fb9771 | ||
|
|
88c4802bdc | ||
|
|
a47e422715 | ||
|
|
3a9ab631e5 | ||
|
|
9ca5118a68 | ||
|
|
d6053080f8 | ||
|
|
b1f8076da0 | ||
|
|
abc760c8e4 | ||
|
|
0331a34d58 | ||
|
|
98af0ba143 | ||
|
|
157810ea3d | ||
|
|
448e4251f8 | ||
|
|
81ce20d616 | ||
|
|
3e9ab41e76 | ||
|
|
a3c8fbc6b6 | ||
|
|
e9dc6880af | ||
|
|
25fb2c4fb6 | ||
|
|
97d28ae4d7 | ||
|
|
b5bad15dae | ||
|
|
3098ef4a6e | ||
|
|
e354b1210e | ||
|
|
895b6ff719 | ||
|
|
0a22655ff3 | ||
|
|
8def378b5e | ||
|
|
7ab8b44b6c | ||
|
|
335fe09d70 | ||
|
|
523a7ed7d3 | ||
|
|
f69e8e3606 | ||
|
|
3516797b49 | ||
|
|
1683e94f0c | ||
|
|
1d249195a4 | ||
|
|
2f7ee08288 | ||
|
|
e0772fb301 | ||
|
|
78bdbce2fd | ||
|
|
5a5fed28fa | ||
|
|
5818b6efb8 | ||
|
|
53a66492e8 | ||
|
|
b17ddc26c0 | ||
|
|
b7e19d2fe3 | ||
|
|
d8130a99b4 | ||
|
|
8c654aeebe | ||
|
|
bad318d451 | ||
|
|
11d2997e44 | ||
|
|
2d75d2e76e | ||
|
|
6074f58641 | ||
|
|
48de09c279 | ||
|
|
032c2cb462 | ||
|
|
2008367883 | ||
|
|
165d88cfd8 | ||
|
|
0c0e1fbbeb | ||
|
|
3559e20dab | ||
|
|
e400f6eab9 | ||
|
|
cffffe0c2e | ||
|
|
70fcdb495a | ||
|
|
c1b2049df9 | ||
|
|
f6cabc78c0 | ||
|
|
b8526452b5 | ||
|
|
a1cefb3e17 | ||
|
|
def0f38f3d | ||
|
|
58a8b00086 | ||
|
|
50a27398b0 | ||
|
|
eab7cba1f3 | ||
|
|
83774ba6ae | ||
|
|
ab700b4ea3 | ||
|
|
bf7936d494 | ||
|
|
14f627329d | ||
|
|
829c996611 | ||
|
|
dff2e8ecb4 | ||
|
|
7c79b1c7c5 | ||
|
|
a390fac356 | ||
|
|
9a43e67347 | ||
|
|
b0d08c572a | ||
|
|
ee4eb0aa6f | ||
|
|
07e27cac02 | ||
|
|
cdc905cc16 | ||
|
|
88b0c82a0d | ||
|
|
01d3349587 | ||
|
|
cf7f096db7 | ||
|
|
21ed352ac5 | ||
|
|
f8a4f79277 | ||
|
|
16d385ac6a | ||
|
|
3dc1945b44 | ||
|
|
3c7db9e986 | ||
|
|
44e1f095d1 | ||
|
|
90c39b8371 | ||
|
|
17b7944ac2 | ||
|
|
bbf486f890 | ||
|
|
20faa956a8 | ||
|
|
74a4e04185 | ||
|
|
b102455b57 | ||
|
|
c2235a0baa | ||
|
|
c36d2b02a3 | ||
|
|
4eb8d86346 | ||
|
|
1b33fbf98b | ||
|
|
3f74391b87 | ||
|
|
93c954dae1 | ||
|
|
f736563a7a | ||
|
|
0350c4f0f6 | ||
|
|
0c0caf0272 | ||
|
|
9abd966a80 | ||
|
|
a1dbd7156c | ||
|
|
b74e5b870c | ||
|
|
bcb021296f | ||
|
|
dcf907f36d | ||
|
|
972b11e39e | ||
|
|
10fffe842b | ||
|
|
963cf98df1 | ||
|
|
0f64ddf2fb | ||
|
|
3fa82818b9 | ||
|
|
c48ba4464c | ||
|
|
2d1118a26f | ||
|
|
53560b8e0b | ||
|
|
3f647cdf32 | ||
|
|
9a0dc6d522 | ||
|
|
c819525e81 | ||
|
|
4024ad5eb2 | ||
|
|
2c0df9552f | ||
|
|
9359586fde | ||
|
|
68069c70e1 | ||
|
|
6a00ceeb66 | ||
|
|
8143f55488 | ||
|
|
03e03fb7a1 | ||
|
|
b13b8c1882 | ||
|
|
02a2afb64f | ||
|
|
ae8e907d72 | ||
|
|
f042834068 | ||
|
|
63130374b9 | ||
|
|
ac01d56747 | ||
|
|
6f751afae4 | ||
|
|
8fd85fb6e6 | ||
|
|
1dbfe1e856 | ||
|
|
d3fd4c0381 | ||
|
|
0e20e05795 | ||
|
|
3bb0dc03af | ||
|
|
4257485ff2 | ||
|
|
f69b7a58f2 | ||
|
|
fd4fe42013 | ||
|
|
930820b738 | ||
|
|
06cc081ca2 | ||
|
|
ee9bf16d1a | ||
|
|
f08e65fd04 | ||
|
|
877de45d6e | ||
|
|
5a4813d336 | ||
|
|
6dc818deb1 | ||
|
|
4b2bf06873 | ||
|
|
839af3e90e | ||
|
|
c059cdd0f2 | ||
|
|
0ba837e163 | ||
|
|
1ddcf370a7 | ||
|
|
e0559e4fda | ||
|
|
eeefbfd38d | ||
|
|
60ba4943ec | ||
|
|
ba4ac17425 | ||
|
|
3965d3ba83 | ||
|
|
3435f24770 | ||
|
|
31672ff60e | ||
|
|
6e619f8927 | ||
|
|
2ccdb165e3 | ||
|
|
db8eab04e3 | ||
|
|
4e2e8954dc | ||
|
|
a25fe81b9e | ||
|
|
bce3ac2c73 | ||
|
|
52b70fbbfa | ||
|
|
08b540dd78 | ||
|
|
22e91979bb | ||
|
|
e3730ecfc3 | ||
|
|
9cfc9b3ee2 | ||
|
|
c0ff3805c8 | ||
|
|
49ebd19ab1 | ||
|
|
79bcc98e9b | ||
|
|
a58980fe82 | ||
|
|
fe67a86a5f | ||
|
|
4d85bb13d1 | ||
|
|
0501c06745 | ||
|
|
abb2e6ea9b | ||
|
|
a99a30d720 | ||
|
|
0670c8f60f | ||
|
|
dfdcb92f3d | ||
|
|
bc9b5706e9 | ||
|
|
64c37a20d1 | ||
|
|
6d2d4f72ac | ||
|
|
4c151970e6 | ||
|
|
e65e815aae | ||
|
|
db3fb23de4 | ||
|
|
5c9adc4052 | ||
|
|
b8c8c29ee4 | ||
|
|
47c0c71e19 | ||
|
|
7d26a86071 | ||
|
|
556d880951 | ||
|
|
4ee50ed6de | ||
|
|
b1b5a9d8fa | ||
|
|
62d8848bee | ||
|
|
c63b16cf75 | ||
|
|
d32a6f15bf | ||
|
|
918abadb6c | ||
|
|
7f5adb135d | ||
|
|
b1ce301520 | ||
|
|
cd93201e46 | ||
|
|
c9aaf5fb24 | ||
|
|
fdf1e32962 | ||
|
|
36d336618e | ||
|
|
013f27e3e6 | ||
|
|
1b3f8a4c18 | ||
|
|
dd8ef51fa1 | ||
|
|
11e8d26606 | ||
|
|
1e954bc8ef | ||
|
|
720eb0e91c | ||
|
|
106763ef9a | ||
|
|
10019a9d96 | ||
|
|
4515bcf289 | ||
|
|
aa8728a2ab | ||
|
|
f2d3b3661b | ||
|
|
24b598b1be | ||
|
|
0d98ee8916 | ||
|
|
3eca5ad9a1 | ||
|
|
ed2465fd30 | ||
|
|
6d21e61889 | ||
|
|
983312d14d | ||
|
|
2e1271fe36 | ||
|
|
15e53c9839 | ||
|
|
115d48497e | ||
|
|
a31948f3b7 | ||
|
|
a12106eb52 | ||
|
|
dd9f42172f | ||
|
|
3d8e149668 | ||
|
|
f557647525 | ||
|
|
1efaf2cde0 | ||
|
|
202aea4dda | ||
|
|
eaefa1ac5d | ||
|
|
fd49174b1a | ||
|
|
342605bb44 | ||
|
|
a9851f5e95 | ||
|
|
848b39b5a0 | ||
|
|
de372ce095 | ||
|
|
8bbae4b10b | ||
|
|
cff2eda198 | ||
|
|
7a75b47da6 | ||
|
|
79430340e5 | ||
|
|
4494c25df7 | ||
|
|
763d659ee2 | ||
|
|
54086f86d2 | ||
|
|
9195a23c95 | ||
|
|
739ba0fbcc | ||
|
|
93ac41e917 | ||
|
|
1928af2a42 | ||
|
|
45e6585e77 | ||
|
|
8d6fbe1a89 | ||
|
|
375b420c35 | ||
|
|
887b48bd1d | ||
|
|
0794a2e526 | ||
|
|
a859e44630 | ||
|
|
1c1a248277 | ||
|
|
e0e2165c8e | ||
|
|
957f8315e3 | ||
|
|
d279ed7dd6 | ||
|
|
827480b9d6 | ||
|
|
1a0af097a6 | ||
|
|
d408fc2864 | ||
|
|
bba03eef2f | ||
|
|
352f7d7f2b | ||
|
|
0f07768d6b | ||
|
|
a6a2be6e37 | ||
|
|
e840cc8b91 | ||
|
|
ff17105386 | ||
|
|
d82f7b9205 | ||
|
|
01b09aab43 | ||
|
|
f0153d801e | ||
|
|
319b2d8f32 | ||
|
|
419675cd2b | ||
|
|
9dd273626a | ||
|
|
2997acf9dc | ||
|
|
1ee9677b8a | ||
|
|
9c14c897f5 | ||
|
|
dc3e37956b | ||
|
|
eb283dcbc6 | ||
|
|
fec2b39df3 | ||
|
|
1e1b8cc2d5 | ||
|
|
8a902d7e58 | ||
|
|
1a0d994305 | ||
|
|
597986b711 | ||
|
|
ba0a843482 | ||
|
|
0ad0f9e094 | ||
|
|
f93a548fe2 | ||
|
|
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 |
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.
|
||||
|
||||
76
Makefile.in
76
Makefile.in
@@ -14,47 +14,63 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
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/cmirrord \
|
||||
daemons/dmeventd/plugins \
|
||||
daemons/dmeventd \
|
||||
lib/format1 \
|
||||
lib/format_pool \
|
||||
lib/locking \
|
||||
lib/mirror \
|
||||
lib/snapshot \
|
||||
liblvm \
|
||||
udev \
|
||||
test/api \
|
||||
test \
|
||||
po
|
||||
DISTCLEAN_TARGETS += lib/misc/configure.h
|
||||
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 +87,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.43-cvs (2010-01-23)
|
||||
591
WHATS_NEW
591
WHATS_NEW
@@ -1,5 +1,590 @@
|
||||
Version 2.02.39 -
|
||||
Version 2.02.60 - 23rd January 2010
|
||||
===================================
|
||||
Extend cmirrord man page.
|
||||
Sleep before first progress check if pvmove/lvconvert interval has prefix '+'.
|
||||
Default to checking progress before waiting in _wait_for_single_lv.
|
||||
Fix cmirror initscript (including syntax error).
|
||||
Eliminate avoidable ioctls for checking open_count in _add_new_lv_to_dtree.
|
||||
Disable memory debugging if dmeventd is configured. (Not thread-safe.)
|
||||
Fix first log message prefix in syslog for dmeventd plugins.
|
||||
Fix exported symbols names for dmeventd lvm2 wrapper plugin.
|
||||
Make failed locking initialisation messages more descriptive.
|
||||
|
||||
Version 2.02.59 - 21st January 2010
|
||||
===================================
|
||||
Add libdevmapper-event-lvm2.so to serialise dmeventd plugin liblvm2cmd use.
|
||||
Cleanup memory initialization and freeing in pv_read() and pv_create().
|
||||
Clear pointer and counters after their release in _fin_commands().
|
||||
Stop dmeventd trying to access already-removed snapshots.
|
||||
Remove (fallback) /dev mknod from cmirrord.
|
||||
Add t-topology-support.sh and t-snapshot-merge.sh tests.
|
||||
Fix clvmd to never scan suspended devices.
|
||||
Fix dmeventd build outside source tree.
|
||||
Assorted cmirror code changes to remove various compiler warnings.
|
||||
Fix detection of completed snapshot merge.
|
||||
Add Red Hat cmirror initscript (unfinished).
|
||||
Add cmirrord man page (incomplete).
|
||||
Make cluster log communication structures architecture independant.
|
||||
Fix cluster log in-memory bitmap handling.
|
||||
Improve snapshot merge metadata import validation.
|
||||
Improve target type compatibility checking in _percent_run().
|
||||
Add 'target_status_compatible' method to 'struct segtype_handler'.
|
||||
Change underscore to hyphen in table line for clustered log type.
|
||||
|
||||
Version 2.02.58 - 14th January 2010
|
||||
===================================
|
||||
Cleanup some minor gcc warnings.
|
||||
Add --merge to lvconvert to merge a snapshot into its origin.
|
||||
Fix clvmd automatic target module loading crash (no reset_locking fn).
|
||||
Fix allocation code not to stop at the first area of a PV that fits.
|
||||
|
||||
Version 2.02.57 - 12th January 2010
|
||||
===================================
|
||||
Ensure exactly one process returns from poll_daemon(), never two.
|
||||
Reset _vgs_locked in lvmcache_init() in child after forking.
|
||||
Define {DM, LVM}_UDEV_DISABLE_CHECKING=1 environment variables during tests.
|
||||
Enable udev_sync and udev_rules in lvm.conf by default while running tests.
|
||||
If LVM_UDEV_DISABLE_CHECKING in set in environment, disable udev warnings.
|
||||
Add --splitmirrors to lvconvert to split off part of a mirror.
|
||||
Change background polldaemon's process name to "(lvm2)".
|
||||
Allow vgremove to remove a VG with PVs missing after a prompt.
|
||||
Return success in lvconvert --repair --use-policies on failed allocation.
|
||||
Keep log type consistent when changing mirror image count.
|
||||
Always set environment variables for an LVM2 device in 11-dm-lvm.rules.
|
||||
Add activation/udev_rules config option in lvm.conf.
|
||||
Add consts to text metadata flag structs.
|
||||
Add macros outfc, outsize, outhint and function out_text_with_comment.
|
||||
Reimplement report FIELD macro using offsetof instead of static structs.
|
||||
Fix fsadm man page typo (fsdam).
|
||||
Rename mirror_device_fault_policy to mirror_image_fault policy.
|
||||
Remove empty PV devices if lvconvert --repair is using defined policies.
|
||||
Use fixed buffer to prevent stack overflow in persistent filter dump.
|
||||
Use extended status of new kernel snapshot target 1.8.0 to detect when empty.
|
||||
Insert stack macros in suspend_lv, resume_lv & (de)activate_lv callers.
|
||||
Add --poll flag to vgchange and lvchange to control background daemon launch.
|
||||
Propagate metadata commit and revert notifications to other cluster nodes.
|
||||
Use proper mask for VG lock mode in clvmd.
|
||||
Allow precommitted metadata to be dropped from lvmcache.
|
||||
Move processing of VG locks to separate function in clvmd.
|
||||
Properly decode all flags in clvmd messages including VG locks.
|
||||
Properly handle precommitted cache flag when only committed metadata present.
|
||||
Resume renamed volumes in reverse order to preserve memlock pairing.
|
||||
Drop cached metadata after device was auto-repaired and removed from VG.
|
||||
Clear MISSING_PV flag if PV reappeared and is empty.
|
||||
Fix removal of multiple devices from a mirror.
|
||||
Also clean up PVs flagged as missing in vgreduce --removemissing --force.
|
||||
Introduce INTERNAL_ERROR macro for error messages and use throughout.
|
||||
Remove superfluous returns from void functions.
|
||||
Destroy allocated mempool in _vg_read_orphans() error path.
|
||||
Fix some pvresize and toollib error paths with missing VG releases/unlocks.
|
||||
Explicitly call suspend for temporary mirror layer.
|
||||
Allow use of precommitted metadata when a PV is missing.
|
||||
Add memlock information to do_lock_lv debug output.
|
||||
Always bypass calls to remote cluster nodes for non-clustered VGs.
|
||||
Permit implicit cluster lock conversion in pre/post callbacks on local node.
|
||||
Permit implicit cluster lock conversion to the lock mode already held.
|
||||
Fix lock flag masking in clvmd so intended code paths get invoked.
|
||||
Replace magic masks in cluster locking code by defined masks.
|
||||
Remove newly-created mirror log from metadata if initial deactivation fails.
|
||||
Correct activated or deactivated text in vgchange summary message.
|
||||
Improve pvmove error message when all source LVs are skipped.
|
||||
Fix memlock imbalance in lv_suspend if already suspended.
|
||||
Fix pvmove test mode not to poll (and fail).
|
||||
Fix vgcreate error message if VG already exists.
|
||||
Fix tools to use log_error when aborted due to user response to prompt.
|
||||
Fix ignored readahead setting in lvcreate --readahead.
|
||||
Fix clvmd memory leak in lv_info_by_lvid by calling release_vg.
|
||||
If aborting due to internal error, always send that message to stderr.
|
||||
Add global/abort_on_internal_errors to lvm.conf to assist testing.
|
||||
Fix test Makefiles when builddir and srcdir differ.
|
||||
Impose limit of 8 mirror images to match the in-kernel kcopyd restriction.
|
||||
Use locking_type 3 (compiled in) for lvmconf --enable-cluster.
|
||||
Remove list.c and list.h with no-longer-used dm_list macros and functions.
|
||||
Log failure type and recognise type 'F' (flush) in dmeventd mirror plugin.
|
||||
Extend internal PV/VG/LV/segment status variables from 32-bit to 64-bit.
|
||||
|
||||
Version 2.02.56 - 24th November 2009
|
||||
====================================
|
||||
Add missing vg_release to pvs and pvdisplay to fix memory leak.
|
||||
Do not try to unlock VG which is not locked in _process_one_vg.
|
||||
Move is_long_lived persistent_filter_dump to happen after every full scan.
|
||||
Refresh device filters before full device rescan in lvmcache.
|
||||
Return error status if vgchange fails to activate some volume.
|
||||
Fix suspend/resume lock type test causing unbalanced memory locking.
|
||||
Revert vg_read_internal change as clvmd was not ready for vg_read. (2.02.55)
|
||||
|
||||
Version 2.02.55 - 19th November 2009
|
||||
====================================
|
||||
Fix deadlock when changing mirrors due to unpaired memlock refcount changes.
|
||||
Use separate memlock counter for dmeventd handlers to permit device scanning.
|
||||
Directly restrict vgchange to activating visible LVs.
|
||||
Fix pvmove region_size overflow for very large PVs.
|
||||
Fix lvcreate and lvresize %PVS argument always to use sensible total size.
|
||||
Tidy some uses of arg_count and introduce arg_is_set.
|
||||
Export outnl and indent functions for modules.
|
||||
Flush stdout after yes/no prompt.
|
||||
Update vgsplit and vgcreate to use vg_set_clustered.
|
||||
Add vg_mda_count and vg_set_clustered library functions.
|
||||
Add more vgcreate and vgsplit nightly tests.
|
||||
Insert some missing stack macros into activation code.
|
||||
Recognise DRBD devices and handle them like md devices.
|
||||
|
||||
Version 2.02.54 - 26th October 2009
|
||||
===================================
|
||||
Update lvcreate/lvconvert man pages to explain PhysicalVolume parameter.
|
||||
Document --all option in man pages, cleanup {pv|vg|lv}{s|display} man pages.
|
||||
Permit snapshots of mirrors.
|
||||
Cleanup mimagetmp LV if allocation fails for new lvconvert mimage.
|
||||
Fix clvmd segfault when refresh_toolcontext fails.
|
||||
Remember to clear 'global lock held during cache refresh' state after use.
|
||||
Use udev flags support in LVM and apply various fixes to udev rules.
|
||||
Delay announcing mirror monitoring to syslog until initialisation succeeded.
|
||||
Handle metadata with unknown segment types more gracefully.
|
||||
Set default owner and group to null.
|
||||
Add dmeventd.static to the build.
|
||||
Disable realtime support code by default.
|
||||
Make clvmd return 0 on success rather than 1.
|
||||
Add --pvmetadatacopies for pvcreate, vgcreate, vgextend, vgconvert.
|
||||
Add implict pvcreate support to vgcreate and vgextend.
|
||||
Correct example.conf to indicate that lvm2 not lvm1 is the default format.
|
||||
Remove an unused stray LVM1_SUPPORT ifdef.
|
||||
Only include selinux libs in libdevmapper.pc when selinux build enabled.
|
||||
Allow for a build directory separate from the source.
|
||||
Update distclean target for rename clogd to cmirrord. (2.02.52)
|
||||
Only do lock conversions in clvmd if we are explicitly asked for one.
|
||||
Introduce percent_range_t and centralise snapshot full/mirror in-sync checks.
|
||||
Factor out poll_mirror_progress and introduce progress_t.
|
||||
Distinguish between powers of 1000 and powers of 1024 in unit suffixes.
|
||||
Restart lvconverts in vgchange by sharing lv_spawn_background_polling.
|
||||
Generalise polldaemon code by changing mirror-specific variable names.
|
||||
Don't attempt to deactivate an LV if any of its snapshots are in use.
|
||||
Return error if lv_deactivate fails to remove device from kernel.
|
||||
Provide alternative implementation of obsolete siginterrupt().
|
||||
Consolidate LV allocation into alloc_lv().
|
||||
Treat input units of both 's' and 'S' as 512-byte sectors. (2.02.49)
|
||||
Use standard output units for 'PE Size' and 'Stripe size' in pv/lvdisplay.
|
||||
Add configure --enable-units-compat to set si_unit_consistency off by default.
|
||||
Add global/si_unit_consistency to enable cleaned-up use of units in output.
|
||||
|
||||
Version 2.02.53 - 25th September 2009
|
||||
=====================================
|
||||
Create any directories in /dev with DM_DEV_DIR_UMASK (022).
|
||||
Enable dmeventd monitoring section of config file by default.
|
||||
Update lvm2 monitoring script to lvm2_monitoring_init_red_hat.in.
|
||||
Fix lvm2app test to run under test/api subdirectory only when configured.
|
||||
Add vg_is_resizeable() and cleanup reference to VG_RESIZEABLE.
|
||||
|
||||
Version 2.02.52 - 15th September 2009
|
||||
=====================================
|
||||
Update _process_one_vg to cleanup properly after vg_read_error.
|
||||
Add lots of missing stack debug messages to tools.
|
||||
Make readonly locking available as locking type 4.
|
||||
Fix readonly locking to permit writeable global locks (for vgscan). (2.02.49)
|
||||
Add DM_UDEV_RULES_VSN environment variable to udev rules.
|
||||
Update vgsplit, vgmerge, and vgrename to obey new vgname ordering rules.
|
||||
Make lvm2app pv_t, lv_t, vg_t handle definitions consistent with lvm_t.
|
||||
Enforce an alphabetical lock ordering on vgname locking.
|
||||
Prioritise write locks over read locks by default for file locking.
|
||||
Add local lock files with suffix ':aux' to serialise locking requests.
|
||||
Fix global locking in PV reporting commands (2.02.49).
|
||||
Fix pvcreate string termination in duplicate uuid warning message.
|
||||
Don't loop reading sysfs with pvcreate on a non-blkext partition (2.02.51).
|
||||
Fix vgcfgrestore error paths when locking fails (2.02.49).
|
||||
Update Makefile distclean target.
|
||||
Add libudev configuration check.
|
||||
Make clvmd check corosync to see what cluster interface it should use.
|
||||
Add clvmd autodetection check and cleanup related configure messages.
|
||||
Rewrite clvmd configuration code to cope with all combinations of libs.
|
||||
Added configure --enable-cmirrord to build the cluster mirror log daemon.
|
||||
Rename clogd to cmirrord.
|
||||
Make lvchange --refresh only take a read lock on volume group.
|
||||
Fix race where non-blocking file locks could be granted in error.
|
||||
Fix vgextend error path - if ORPHAN lock fails, unlock / release vg (2.02.49).
|
||||
Fix compile warning in clvmd.
|
||||
Clarify use of PE ranges in lv{convert|create|extend|resize} man pages.
|
||||
Remove useless _pv_write wrapper.
|
||||
Add lvm2app.sh to tests conditional upon configure --enable-applib.
|
||||
Add lvm_vg_is_clustered, lvm_vg_is_exported, and lvm_vg_is_partial.
|
||||
Update lvm_vg_remove to require lvm_vg_write to commit remove to disk.
|
||||
Update test/api/test.c to call lvm_vg_create and lvm_vg_remove.
|
||||
|
||||
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
|
||||
================================
|
||||
Add readonly locking type to replace implementation of --ignorelockingfailure.
|
||||
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.
|
||||
@@ -9,12 +594,12 @@ Version 2.02.39 -
|
||||
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.
|
||||
Fix ambiguous use of identifier error_message_produced.
|
||||
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 to not activate mirror leg and log volumes directly.
|
||||
Fix vgchange not to activate component mirror volumes directly.
|
||||
Fix test directory clean up in make distclean.
|
||||
|
||||
Version 2.02.38 - 11th June 2008
|
||||
|
||||
115
WHATS_NEW_DM
115
WHATS_NEW_DM
@@ -1,3 +1,118 @@
|
||||
Version 1.02.43 - 21st January 2010
|
||||
===================================
|
||||
Remove bitset, hash and pool headers superceded by libdevmapper.h.
|
||||
Fix off-by-one error causing bad cluster mirror table construction.
|
||||
|
||||
Version 1.02.42 - 14th January 2010
|
||||
===================================
|
||||
Add support for the "snapshot-merge" kernel target (2.6.33-rc1).
|
||||
Introduce a third activation_priority level in dm_tree_activate_children.
|
||||
|
||||
Version 1.02.41 - 12th January 2010
|
||||
===================================
|
||||
If DM_UDEV_DISABLE_CHECKING is set in environment, disable udev warnings.
|
||||
Add dm_tree_add_dev_with_udev_flags to provide wider support for udev flags.
|
||||
Add --noudevrules option for dmsetup to disable /dev node management by udev.
|
||||
Fix 'dmsetup info -c -o all' to show all fields.
|
||||
Return errors if dm_tree_*_children functions fail.
|
||||
Fix coredump and memory leak for 'dmsetup help -c'.
|
||||
Disable udev rules for change events with DISK_RO set.
|
||||
|
||||
Version 1.02.40 - 19th November 2009
|
||||
====================================
|
||||
Fix install_device-mapper Makefile target to not build dmeventd plugins.
|
||||
Support udev flags even when udev_sync is disabled or not compiled in.
|
||||
Remove 'last_rule' from udev rules: honour DM_UDEV_DISABLE_OTHER_RULES_FLAG.
|
||||
Add dmsetup --inactive support.
|
||||
Add dm_task_query_inactive_table to libdevmapper for kernel driver >= 4.16.
|
||||
Fix hash lookup segfault when keys compared are different lengths.
|
||||
|
||||
Version 1.02.39 - 26th October 2009
|
||||
===================================
|
||||
Remove strict default permissions for DM devices from 95-dm-notify.rules.
|
||||
Add dmsetup udevflags command to decode udev flags in given cookie value.
|
||||
Support udev flags in libdevmapper incl. dm_tree_add_new_dev_with_udev_flags.
|
||||
Make libdm ABI consistent when built with/without selinux support.
|
||||
|
||||
Version 1.02.38 - 25th September 2009
|
||||
=====================================
|
||||
Export DM_DEV_DIR_UMASK, the default umask for /dev directories created.
|
||||
Handle any path supplied to dm_task_set_name by looking up in /dev/mapper.
|
||||
Add several examples to 12-dm-permissions.rules.
|
||||
Add splitname and --yes to dmsetup man page.
|
||||
Fix _mirror_emit_segment_line return code.
|
||||
Fix dmeventd _temporary_log_fn parameters. (2.02.50)
|
||||
|
||||
Version 1.02.37 - 15th September 2009
|
||||
=====================================
|
||||
Add dmsetup manpage entries for udevcomplete_all and udevcookies.
|
||||
Check udev is running when processing cookies and retain state internally.
|
||||
Add y|--yes option to dmsetup for default 'yes' answer to prompts.
|
||||
Fix tools Makefile to process dmsetup sources separately.
|
||||
Restore umask when device node creation fails.
|
||||
Check kernel vsn to use 'block_on_error' or 'handle_errors' in mirror table.
|
||||
Add dm-log-userspace.h to tree for cmirrord builds.
|
||||
|
||||
Version 1.02.36 - 6th August 2009
|
||||
=================================
|
||||
Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
|
||||
Add libdevmapper functions to support synchronisation with udev.
|
||||
|
||||
Version 1.02.35 - 28th July 2009
|
||||
================================
|
||||
Add LOG_LINE_WITH_ERRNO macro.
|
||||
Use log_error macro consistently throughout in place of log_err.
|
||||
|
||||
Version 1.02.34 - 15th July 2009
|
||||
================================
|
||||
Use _exit() not exit() after forking to avoid flushing libc buffers twice.
|
||||
Rename plog macro to LOG_LINE & add LOG_MESG variant for dm_dump_memory_debug.
|
||||
Change plog to use dm_log_with_errno unless deprecated dm_log_init was used.
|
||||
Add dm_log_with_errno and dm_log_with_errno_init, deprecating the old fns.
|
||||
Fix whitespace in linear target line to fix identical table line detection.
|
||||
Add device number to more log messages during activation.
|
||||
|
||||
Version 1.02.33 - 30th June 2009
|
||||
================================
|
||||
Don't fallback to default major number: use dm_task_set_major_minor. (1.02.31)
|
||||
Do not fork daemon when dmeventd cannot be found.
|
||||
Add crypt target handling to libdevmapper tree nodes.
|
||||
Add splitname command to dmsetup.
|
||||
Add subsystem, vg_name, lv_name, lv_layer fields to dmsetup reports.
|
||||
Make mempool optional in dm_split_lvm_name().
|
||||
|
||||
Version 1.02.32 - 21st May 2009
|
||||
===============================
|
||||
Only generate libdevmapper.a when configured to link statically.
|
||||
Export dm_tree_node_size_changed() from libdevmapper.
|
||||
Propagate the table size_changed property up the dm device tree.
|
||||
Detect failure to free memory pools when releasing the library.
|
||||
Fix segfault when getopt processes dmsetup -U, -G and -M options.
|
||||
|
||||
Version 1.02.31 - 3rd March 2009
|
||||
================================
|
||||
If kernel supports only one dm major number, use in place of any supplied.
|
||||
|
||||
Version 1.02.30 - 26th January 2009
|
||||
====================================
|
||||
Add "all" field to reports expanding to all fields of report type.
|
||||
Enforce device name length and character limitations in libdm.
|
||||
Replace _dm_snprintf with EMIT_PARAMS macro for creating target lines.
|
||||
|
||||
Version 1.02.29 - 10th November 2008
|
||||
====================================
|
||||
Merge device-mapper into the LVM2 tree.
|
||||
Split out dm-logging.h from log.h.
|
||||
Use lvm-types.h.
|
||||
Add usrsbindir to configure.
|
||||
|
||||
Version 1.02.28 - 18th September 2008
|
||||
=====================================
|
||||
Only resume devices in dm_tree_preload_children if size changes.
|
||||
Extend deptree buffers so the largest possible device numbers fit.
|
||||
Generate versioned libdevmapper-event.so.
|
||||
Underline longer report help text headings.
|
||||
|
||||
Version 1.02.27 - 25th June 2008
|
||||
================================
|
||||
Align struct memblock in dbg_malloc for sparc.
|
||||
|
||||
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
|
||||
;;
|
||||
|
||||
662
configure.in
662
configure.in
@@ -1,6 +1,6 @@
|
||||
###############################################################################
|
||||
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
|
||||
## Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
## 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
|
||||
@@ -28,6 +28,7 @@ AC_CANONICAL_TARGET([])
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CFLAGS="$CFLAGS"
|
||||
COPTIMISE_FLAG="-O2"
|
||||
CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
|
||||
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
||||
@@ -39,9 +40,8 @@ case "$host_os" in
|
||||
ODIRECT=yes
|
||||
DM_IOCTLS=yes
|
||||
SELINUX=yes
|
||||
REALTIME=yes
|
||||
CLUSTER=internal
|
||||
FSADM=no
|
||||
FSADM=yes
|
||||
;;
|
||||
darwin*)
|
||||
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
||||
@@ -54,7 +54,6 @@ case "$host_os" in
|
||||
ODIRECT=no
|
||||
DM_IOCTLS=no
|
||||
SELINUX=no
|
||||
REALTIME=no
|
||||
CLUSTER=none
|
||||
FSADM=no
|
||||
;;
|
||||
@@ -62,6 +61,7 @@ esac
|
||||
|
||||
################################################################################
|
||||
dnl -- Checks for programs.
|
||||
AC_PROG_SED
|
||||
AC_PROG_AWK
|
||||
AC_PROG_CC
|
||||
|
||||
@@ -70,6 +70,7 @@ 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)
|
||||
@@ -115,6 +116,7 @@ dnl -- Check for functions
|
||||
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_CHECK_FUNCS(siginterrupt)
|
||||
AC_FUNC_ALLOCA
|
||||
AC_FUNC_CLOSEDIR_VOID
|
||||
AC_FUNC_FORK
|
||||
@@ -126,6 +128,15 @@ 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)
|
||||
@@ -133,10 +144,10 @@ AC_PREFIX_DEFAULT(/usr)
|
||||
################################################################################
|
||||
dnl -- Setup the ownership of the files
|
||||
AC_MSG_CHECKING(file owner)
|
||||
OWNER="root"
|
||||
OWNER=""
|
||||
|
||||
AC_ARG_WITH(user,
|
||||
[ --with-user=USER Set the owner of installed files [[USER=root]] ],
|
||||
[ --with-user=USER Set the owner of installed files [[USER=]] ],
|
||||
[ OWNER="$withval" ])
|
||||
AC_MSG_RESULT($OWNER)
|
||||
|
||||
@@ -147,9 +158,9 @@ fi
|
||||
################################################################################
|
||||
dnl -- Setup the group ownership of the files
|
||||
AC_MSG_CHECKING(group owner)
|
||||
GROUP="root"
|
||||
GROUP=""
|
||||
AC_ARG_WITH(group,
|
||||
[ --with-group=GROUP Set the group owner of installed files [[GROUP=root]] ],
|
||||
[ --with-group=GROUP Set the group owner of installed files [[GROUP=]] ],
|
||||
[ GROUP="$withval" ])
|
||||
AC_MSG_RESULT($GROUP)
|
||||
|
||||
@@ -157,6 +168,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)
|
||||
@@ -268,25 +306,42 @@ if test x$MIRRORS = xinternal; then
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
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])
|
||||
[ --disable-readline Disable readline support],
|
||||
[READLINE=$enableval], [READLINE=maybe])
|
||||
AC_MSG_RESULT($READLINE)
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable realtime clock support
|
||||
AC_MSG_CHECKING(whether to enable realtime support)
|
||||
AC_ARG_ENABLE(realtime, [ --disable-realtime Disable realtime clock support],
|
||||
AC_ARG_ENABLE(realtime, [ --enable-realtime Enable realtime clock support],
|
||||
REALTIME=$enableval)
|
||||
AC_MSG_RESULT($REALTIME)
|
||||
|
||||
################################################################################
|
||||
dnl -- Init pkg-config with dummy invokation:
|
||||
dnl -- this is required because PKG_CHECK_MODULES macro is expanded
|
||||
dnl -- to initialize the pkg-config environment only at the first invokation,
|
||||
dnl -- that would be conditional in this configure.in.
|
||||
pkg_config_init() {
|
||||
PKG_CHECK_MODULES(PKGCONFIGINIT, pkgconfiginit, [],
|
||||
[AC_MSG_RESULT([pkg-config initialized])])
|
||||
PKGCONFIG_INIT=1
|
||||
}
|
||||
|
||||
################################################################################
|
||||
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.
|
||||
The following cluster manager combinations are valid:
|
||||
* cman,gulm (RHEL4 or equivalent)
|
||||
* cman (RHEL5 or equivalent)
|
||||
* cman,corosync,openais (or selection of them)
|
||||
* all (autodetect)
|
||||
* none (disable build)
|
||||
[TYPE=none] ],
|
||||
[ CLVMD="$withval" ],
|
||||
[ CLVMD="none" ])
|
||||
@@ -300,6 +355,242 @@ if test x$CLVMD != xnone && test x$CLUSTER = xnone; then
|
||||
CLUSTER=internal
|
||||
fi
|
||||
|
||||
dnl -- init pkgconfig if required
|
||||
if test x$CLVMD != xnone && test x$PKGCONFIG_INIT != x1; then
|
||||
pkg_config_init
|
||||
fi
|
||||
|
||||
|
||||
dnl -- define build types
|
||||
if [[ `expr x"$CLVMD" : '.*gulm.*'` != 0 ]]; then
|
||||
BUILDGULM=yes
|
||||
fi
|
||||
if [[ `expr x"$CLVMD" : '.*corosync.*'` != 0 ]]; then
|
||||
BUILDCOROSYNC=yes
|
||||
fi
|
||||
if [[ `expr x"$CLVMD" : '.*openais.*'` != 0 ]]; then
|
||||
BUILDOPENAIS=yes
|
||||
fi
|
||||
if [[ `expr x"$CLVMD" : '.*cman.*'` != 0 ]]; then
|
||||
BUILDCMAN=yes
|
||||
fi
|
||||
|
||||
dnl -- sanity check around user selection
|
||||
if test x$BUILDGULM = xyes; then
|
||||
if test x$BUILDCOROSYNC = xyes || \
|
||||
test x$BUILDOPENAIS = xyes; then
|
||||
AC_MSG_ERROR([requested clvmd configuration is not valid])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl -- define a soft bailout if we are autodetecting
|
||||
soft_bailout() {
|
||||
NOTFOUND=1
|
||||
}
|
||||
|
||||
hard_bailout() {
|
||||
AC_MSG_ERROR([bailing out])
|
||||
}
|
||||
|
||||
dnl -- if clvmd=all then set soft_bailout (we don't want to error)
|
||||
dnl -- and set all builds to yes. We need to do this here
|
||||
dnl -- to skip the gulm + openais|corosync sanity check above.
|
||||
if test x$CLVMD = xall; then
|
||||
bailout=soft_bailout
|
||||
BUILDGULM=yes
|
||||
BUILDCMAN=yes
|
||||
BUILDCOROSYNC=yes
|
||||
BUILDOPENAIS=yes
|
||||
else
|
||||
bailout=hard_bailout
|
||||
fi
|
||||
|
||||
dnl -- helper macro to check libs without adding them to LIBS
|
||||
check_lib_no_libs() {
|
||||
lib_no_libs_arg1=$1
|
||||
shift
|
||||
lib_no_libs_arg2=$1
|
||||
shift
|
||||
lib_no_libs_args=$@
|
||||
AC_CHECK_LIB([$lib_no_libs_arg1],
|
||||
[$lib_no_libs_arg2],,
|
||||
[$bailout],
|
||||
[$lib_no_libs_args])
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
}
|
||||
|
||||
dnl -- Look for gulm libraries if required.
|
||||
if test x$BUILDGULM = xyes; then
|
||||
PKG_CHECK_MODULES(CCS, libccs, [HAVE_CCS=yes],
|
||||
[NOTFOUND=0
|
||||
AC_CHECK_HEADERS(ccs.h,,$bailout)
|
||||
check_lib_no_libs ccs ccs_connect
|
||||
if test $NOTFOUND = 0; then
|
||||
AC_MSG_RESULT([no pkg for libccs, using -lccs])
|
||||
CCS_LIBS="-lccs"
|
||||
HAVE_CCS=yes
|
||||
fi])
|
||||
PKG_CHECK_MODULES(GULM, libgulm, [HAVE_GULM=yes],
|
||||
[NOTFOUND=0
|
||||
AC_CHECK_HEADERS(libgulm.h,,$bailout)
|
||||
check_lib_no_libs gulm lg_core_login
|
||||
if test $NOTFOUND = 0; then
|
||||
AC_MSG_RESULT([no pkg for libgulm, using -lgulm])
|
||||
GULM_LIBS="-lgulm"
|
||||
HAVE_GULM=yes
|
||||
fi])
|
||||
fi
|
||||
|
||||
dnl -- Look for cman libraries if required.
|
||||
if test x$BUILDCMAN = xyes; then
|
||||
PKG_CHECK_MODULES(CMAN, libcman, [HAVE_CMAN=yes],
|
||||
[NOTFOUND=0
|
||||
AC_CHECK_HEADERS(libcman.h,,$bailout)
|
||||
check_lib_no_libs cman cman_init
|
||||
if test $NOTFOUND = 0; then
|
||||
AC_MSG_RESULT([no pkg for libcman, using -lcman])
|
||||
CMAN_LIBS="-lcman"
|
||||
HAVE_CMAN=yes
|
||||
fi])
|
||||
CHECKCONFDB=yes
|
||||
CHECKDLM=yes
|
||||
fi
|
||||
|
||||
dnl -- Look for corosync that's required also for openais build
|
||||
dnl -- only enough recent version of corosync ship pkg-config files.
|
||||
dnl -- We can safely rely on that to detect the correct bits.
|
||||
if test x$BUILDCOROSYNC = xyes || \
|
||||
test x$BUILDOPENAIS = xyes; then
|
||||
PKG_CHECK_MODULES(COROSYNC, corosync, [HAVE_COROSYNC=yes], $bailout)
|
||||
CHECKCONFDB=yes
|
||||
fi
|
||||
|
||||
dnl -- Look for corosync libraries if required.
|
||||
if test x$BUILDCOROSYNC = xyes; then
|
||||
PKG_CHECK_MODULES(QUORUM, libquorum, [HAVE_QUORUM=yes], $bailout)
|
||||
CHECKCPG=yes
|
||||
CHECKDLM=yes
|
||||
fi
|
||||
|
||||
dnl -- Look for openais libraries if required.
|
||||
if test x$BUILDOPENAIS = xyes; then
|
||||
PKG_CHECK_MODULES(SALCK, libSaLck, [HAVE_SALCK=yes], $bailout)
|
||||
CHECKCPG=yes
|
||||
fi
|
||||
|
||||
dnl -- Below are checks for libraries common to more than one build.
|
||||
|
||||
dnl -- Check confdb library.
|
||||
dnl -- mandatory for corosync build.
|
||||
dnl -- optional for openais/cman build.
|
||||
|
||||
if test x$CHECKCONFDB = xyes; then
|
||||
PKG_CHECK_MODULES(CONFDB, libconfdb,
|
||||
[HAVE_CONFDB=yes],
|
||||
[HAVE_CONFDB=no])
|
||||
|
||||
AC_CHECK_HEADERS(corosync/confdb.h,
|
||||
[HAVE_CONFDB_H=yes],
|
||||
[HAVE_CONFDB_H=no])
|
||||
|
||||
if test x$HAVE_CONFDB != xyes && \
|
||||
test x$HAVE_CONFDB_H = xyes; then
|
||||
check_lib_no_libs confdb confdb_initialize
|
||||
AC_MSG_RESULT([no pkg for confdb, using -lconfdb])
|
||||
CONFDB_LIBS="-lconfdb"
|
||||
HAVE_CONFDB=yes
|
||||
fi
|
||||
|
||||
if test x$BUILDCOROSYNC = xyes && \
|
||||
test x$HAVE_CONFDB != xyes &&
|
||||
test x$CLVMD != xall; then
|
||||
AC_MSG_ERROR([bailing out... confdb library is required])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl -- Check cpg library.
|
||||
if test x$CHECKCPG = xyes; then
|
||||
PKG_CHECK_MODULES(CPG, libcpg, [HAVE_CPG=yes], $bailout)
|
||||
fi
|
||||
|
||||
dnl -- Check dlm library.
|
||||
if test x$CHECKDLM = xyes; then
|
||||
PKG_CHECK_MODULES(DLM, libdlm, [HAVE_DLM=yes],
|
||||
[NOTFOUND=0
|
||||
AC_CHECK_HEADERS(libdlm.h,,$bailout)
|
||||
check_lib_no_libs dlm dlm_lock -lpthread
|
||||
if test $NOTFOUND = 0; then
|
||||
AC_MSG_RESULT([no pkg for libdlm, using -ldlm])
|
||||
DLM_LIBS="-ldlm -lpthread"
|
||||
HAVE_DLM=yes
|
||||
fi])
|
||||
fi
|
||||
|
||||
dnl -- If we are autodetecting, we need to re-create
|
||||
dnl -- the depedencies checks and set a proper CLVMD.
|
||||
if test x$CLVMD = xall; then
|
||||
CLVMD=none
|
||||
if test x$HAVE_CCS = xyes && \
|
||||
test x$HAVE_GULM = xyes; then
|
||||
AC_MSG_RESULT([Enabling clvmd gulm cluster manager])
|
||||
CLVMD="$CLVMD,gulm"
|
||||
fi
|
||||
if test x$HAVE_CMAN = xyes && \
|
||||
test x$HAVE_DLM = xyes; then
|
||||
AC_MSG_RESULT([Enabling clvmd cman cluster manager])
|
||||
CLVMD="$CLVMD,cman"
|
||||
fi
|
||||
if test x$HAVE_COROSYNC = xyes && \
|
||||
test x$HAVE_QUORUM = xyes && \
|
||||
test x$HAVE_CPG = xyes && \
|
||||
test x$HAVE_DLM = xyes && \
|
||||
test x$HAVE_CONFDB = xyes; then
|
||||
AC_MSG_RESULT([Enabling clvmd corosync cluster manager])
|
||||
CLVMD="$CLVMD,corosync"
|
||||
fi
|
||||
if test x$HAVE_COROSYNC = xyes && \
|
||||
test x$HAVE_CPG = xyes && \
|
||||
test x$HAVE_SALCK = xyes; then
|
||||
AC_MSG_RESULT([Enabling clvmd openais cluster manager])
|
||||
CLVMD="$CLVMD,openais"
|
||||
fi
|
||||
if test x$CLVMD = xnone; then
|
||||
AC_MSG_RESULT([Disabling clvmd build. No cluster manager detected.])
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Build cluster mirror log daemon
|
||||
AC_MSG_CHECKING(whether to build cluster mirror log daemon)
|
||||
AC_ARG_ENABLE(cmirrord, [ --enable-cmirrord Enable the cluster mirror log daemon],
|
||||
CMIRRORD=$enableval, CMIRRORD=no)
|
||||
AC_MSG_RESULT($CMIRRORD)
|
||||
|
||||
BUILD_CMIRRORD=$CMIRRORD
|
||||
|
||||
################################################################################
|
||||
dnl -- cmirrord pidfile
|
||||
AH_TEMPLATE(CMIRRORD_PIDFILE, [Path to cmirrord pidfile.])
|
||||
if test "x$BUILD_CMIRRORD" = xyes; then
|
||||
AC_ARG_WITH(cmirrord-pidfile,
|
||||
[ --with-cmirrord-pidfile=PATH cmirrord pidfile [[/var/run/cmirrord.pid]] ],
|
||||
[ AC_DEFINE_UNQUOTED(CMIRRORD_PIDFILE,"$withval") ],
|
||||
[ AC_DEFINE_UNQUOTED(CMIRRORD_PIDFILE,"/var/run/cmirrord.pid") ])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Look for corosync libraries if required.
|
||||
if [[ "x$BUILD_CMIRRORD" = xyes ]]; then
|
||||
dnl -- init pkgconfig if required
|
||||
if test x$PKGCONFIG_INIT != x1; then
|
||||
pkg_config_init
|
||||
fi
|
||||
PKG_CHECK_MODULES(SACKPT, libSaCkpt)
|
||||
if test x$HAVE_CPG != xyes; then
|
||||
PKG_CHECK_MODULES(CPG, libcpg)
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable debugging
|
||||
AC_MSG_CHECKING(whether to enable debugging)
|
||||
@@ -322,17 +613,88 @@ AC_ARG_WITH(optimisation,
|
||||
[ 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 -- Check for libudev's udev_queue_get_udev_is_active function when udev synchronisation is enabled
|
||||
|
||||
if test x$UDEV_SYNC = xyes; then
|
||||
AC_CHECK_LIB(udev, udev_queue_get_udev_is_active, HAVE_UDEV_QUEUE_GET_UDEV_IS_ACTIVE=yes,
|
||||
HAVE_UDEV_QUEUE_GET_UDEV_IS_ACTIVE=no)
|
||||
|
||||
if test x$HAVE_UDEV_QUEUE_GET_UDEV_IS_ACTIVE = xyes; then
|
||||
AC_DEFINE([HAVE_UDEV_QUEUE_GET_UDEV_IS_ACTIVE], 1,
|
||||
[Define to 1 if libudev's udev_queue_get_udev_is_active function is available.])
|
||||
LIBS="-ludev $LIBS"
|
||||
else
|
||||
AC_MSG_WARN(It won't be possible to get udev state. We will assume that udev is not running.)
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Compatibility mode
|
||||
AC_ARG_ENABLE(compat, [ --enable-compat Enable support for old device-mapper versions],
|
||||
DM_COMPAT=$enableval, DM_COMPAT=no)
|
||||
|
||||
################################################################################
|
||||
dnl -- Compatible units suffix mode
|
||||
AC_ARG_ENABLE(units-compat,
|
||||
[ --enable-units-compat Enable output compatibility with old versions that
|
||||
that don't use KiB-style unit suffixes],
|
||||
UNITS_COMPAT=$enableval, UNITS_COMPAT=no)
|
||||
|
||||
if test x$UNITS_COMPAT = xyes; then
|
||||
AC_DEFINE([DEFAULT_SI_UNIT_CONSISTENCY], 0, [Define to 0 to reinstate the pre-2.02.54 handling of unit suffixes.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
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)
|
||||
@@ -344,6 +706,18 @@ 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)
|
||||
@@ -351,10 +725,15 @@ AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library],
|
||||
CMDLIB=$enableval, CMDLIB=no)
|
||||
AC_MSG_RESULT($CMDLIB)
|
||||
AC_SUBST([LVM2CMD_LIB])
|
||||
test $CMDLIB=yes \
|
||||
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 install fsadm)
|
||||
@@ -369,16 +748,39 @@ 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 -- 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 ]];
|
||||
@@ -387,9 +789,11 @@ fi;
|
||||
|
||||
################################################################################
|
||||
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:
|
||||
@@ -399,7 +803,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
|
||||
|
||||
################################################################################
|
||||
@@ -423,15 +826,6 @@ Features cannot be 'shared' when building statically
|
||||
)
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
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 -- Disable selinux
|
||||
AC_MSG_CHECKING(whether to enable selinux support)
|
||||
@@ -447,17 +841,18 @@ if test x$SELINUX = xyes; then
|
||||
if test x$HAVE_SEPOL = xyes; then
|
||||
AC_DEFINE([HAVE_SEPOL], 1,
|
||||
[Define to 1 if sepol_check_context is available.])
|
||||
LIBS="-lsepol $LIBS"
|
||||
SELINUX_LIBS="-lsepol $SELINUX_LIBS"
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
|
||||
|
||||
if test x$HAVE_SELINUX = xyes; then
|
||||
AC_DEFINE([HAVE_SELINUX], 1, [Define to 1 to include support for selinux.])
|
||||
LIBS="-lselinux $LIBS"
|
||||
SELINUX_LIBS="-lselinux $SELINUX_LIBS"
|
||||
else
|
||||
AC_MSG_WARN(Disabling selinux)
|
||||
fi
|
||||
LIBS="$SELINUX_LIBS $LIBS"
|
||||
|
||||
# With --enable-static_link and selinux enabled, linking
|
||||
# fails on at least Debian unstable due to unsatisfied references
|
||||
@@ -491,9 +886,11 @@ AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 if getop
|
||||
|
||||
################################################################################
|
||||
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:
|
||||
@@ -501,12 +898,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.]))
|
||||
AC_DEFINE([READLINE_SUPPORT], 1,
|
||||
[Define to 1 to include the LVM readline shell.])
|
||||
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
|
||||
|
||||
################################################################################
|
||||
@@ -517,6 +913,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 ]];
|
||||
@@ -533,25 +930,35 @@ fi
|
||||
|
||||
################################################################################
|
||||
AC_ARG_WITH(confdir,
|
||||
[ --with-confdir=DIR Configuration files in DIR [/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]],
|
||||
[ --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
|
||||
@@ -580,12 +987,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)
|
||||
|
||||
@@ -594,10 +1003,67 @@ if test x$MODPROBE_CMD != x; then
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
LVM_VERSION="\"`cat VERSION 2>/dev/null || echo 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
|
||||
|
||||
################################################################################
|
||||
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 "$srcdir"/VERSION_DM 2>/dev/null || echo Unknown`\""
|
||||
AC_DEFINE_UNQUOTED(DM_LIB_VERSION, $DM_LIB_VERSION, [Library version])
|
||||
|
||||
DM_LIB_PATCHLEVEL=`cat "$srcdir"/VERSION_DM | $AWK -F '[[-. ]]' '{printf "%s.%s.%s",$1,$2,$3}'`
|
||||
|
||||
LVM_VERSION="\"`cat "$srcdir"/VERSION 2>/dev/null || echo Unknown`\""
|
||||
|
||||
VER=`cat "$srcdir"/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_CMIRRORD)
|
||||
AC_SUBST(BUILD_DMEVENTD)
|
||||
AC_SUBST(CCS_CFLAGS)
|
||||
AC_SUBST(CCS_LIBS)
|
||||
AC_SUBST(CFLAGS)
|
||||
AC_SUBST(CFLOW_CMD)
|
||||
AC_SUBST(CLDFLAGS)
|
||||
@@ -605,13 +1071,20 @@ AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||
AC_SUBST(CLDWHOLEARCHIVE)
|
||||
AC_SUBST(CLUSTER)
|
||||
AC_SUBST(CLVMD)
|
||||
AC_SUBST(CMAN_CFLAGS)
|
||||
AC_SUBST(CMAN_LIBS)
|
||||
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(DMDIR)
|
||||
# FIXME: rename to LVM_USE_DMEVENTD
|
||||
AC_SUBST(DLM_CFLAGS)
|
||||
AC_SUBST(DLM_LIBS)
|
||||
AC_SUBST(DMEVENTD)
|
||||
AC_SUBST(DM_COMPAT)
|
||||
AC_SUBST(DM_DEVICE_GID)
|
||||
@@ -619,8 +1092,11 @@ 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(GULM_CFLAGS)
|
||||
AC_SUBST(GULM_LIBS)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
AC_SUBST(HAVE_SELINUX)
|
||||
@@ -633,18 +1109,40 @@ AC_SUBST(LIB_SUFFIX)
|
||||
AC_SUBST(LOCALEDIR)
|
||||
AC_SUBST(LVM1)
|
||||
AC_SUBST(LVM1_FALLBACK)
|
||||
# FIXME: rename to LVM_CONF_DIR
|
||||
AC_SUBST(CONFDIR)
|
||||
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(SACKPT_CFLAGS)
|
||||
AC_SUBST(SACKPT_LIBS)
|
||||
AC_SUBST(SALCK_CFLAGS)
|
||||
AC_SUBST(SALCK_LIBS)
|
||||
AC_SUBST(SELINUX_LIBS)
|
||||
AC_SUBST(SNAPSHOTS)
|
||||
AC_SUBST(STATICDIR)
|
||||
AC_SUBST(STATIC_LINK)
|
||||
AC_SUBST(UDEV_RULES)
|
||||
AC_SUBST(UDEV_SYNC)
|
||||
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
|
||||
@@ -652,36 +1150,42 @@ dnl -- keep utility scripts running properly
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
make.tmpl
|
||||
include/Makefile
|
||||
lib/Makefile
|
||||
man/Makefile
|
||||
po/Makefile
|
||||
dmeventd/Makefile
|
||||
daemons/Makefile
|
||||
daemons/clvmd/Makefile
|
||||
dmeventd/mirror/Makefile
|
||||
dmeventd/snapshot/Makefile
|
||||
daemons/cmirrord/Makefile
|
||||
daemons/dmeventd/Makefile
|
||||
daemons/dmeventd/libdevmapper-event.pc
|
||||
daemons/dmeventd/plugins/Makefile
|
||||
daemons/dmeventd/plugins/lvm2/Makefile
|
||||
daemons/dmeventd/plugins/mirror/Makefile
|
||||
daemons/dmeventd/plugins/snapshot/Makefile
|
||||
doc/Makefile
|
||||
include/.symlinks
|
||||
include/Makefile
|
||||
lib/Makefile
|
||||
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/cmirrord_init_red_hat
|
||||
scripts/lvm2_monitoring_init_red_hat
|
||||
scripts/Makefile
|
||||
test/Makefile
|
||||
test/api/Makefile
|
||||
tools/Makefile
|
||||
tools/version.h
|
||||
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
|
||||
|
||||
@@ -13,11 +13,25 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
.PHONY: dmeventd clvmd cmirrord
|
||||
|
||||
ifneq ("@CLVMD@", "none")
|
||||
SUBDIRS = clvmd
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
ifeq ("@BUILD_CMIRRORD@", "yes")
|
||||
SUBDIRS += cmirrord
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
SUBDIRS += dmeventd
|
||||
endif
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
device-mapper: dmeventd.device-mapper
|
||||
endif
|
||||
|
||||
@@ -13,60 +13,69 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CCS_LIBS = @CCS_LIBS@
|
||||
CCS_CFLAGS = @CCS_CFLAGS@
|
||||
CMAN_LIBS = @CMAN_LIBS@
|
||||
CMAN_CFLAGS = @CMAN_CFLAGS@
|
||||
CONFDB_LIBS = @CONFDB_LIBS@
|
||||
CONFDB_CFLAGS = @CONFDB_CFLAGS@
|
||||
CPG_LIBS = @CPG_LIBS@
|
||||
CPG_CFLAGS = @CPG_CFLAGS@
|
||||
DLM_LIBS = @DLM_LIBS@
|
||||
DLM_CFLAGS = @DLM_CFLAGS@
|
||||
GULM_LIBS = @GULM_LIBS@
|
||||
GULM_CFLAGS = @GULM_CFLAGS@
|
||||
QUORUM_LIBS = @QUORUM_LIBS@
|
||||
QUORUM_CFLAGS = @QUORUM_CFLAGS@
|
||||
SALCK_LIBS = @SALCK_LIBS@
|
||||
SALCK_CFLAGS = @SALCK_CFLAGS@
|
||||
|
||||
SOURCES = \
|
||||
clvmd-command.c \
|
||||
clvmd.c \
|
||||
lvm-functions.c \
|
||||
refresh_clvmd.c
|
||||
|
||||
ifeq ("@CLVMD@", "gulm")
|
||||
GULM = yes
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "cman")
|
||||
CMAN = yes
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "openais")
|
||||
OPENAIS = yes
|
||||
GULM = no
|
||||
CMAN = no
|
||||
endif
|
||||
|
||||
ifeq ("@CLVMD@", "all")
|
||||
GULM = yes
|
||||
CMAN = yes
|
||||
OPENAIS = no
|
||||
endif
|
||||
|
||||
ifeq ("@DEBUG@", "yes")
|
||||
DEFS += -DDEBUG
|
||||
endif
|
||||
|
||||
ifeq ("$(GULM)", "yes")
|
||||
ifneq (,$(findstring gulm,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-gulm.c tcp-comms.c
|
||||
LMLIBS += -lccs -lgulm
|
||||
LMLIBS += $(CCS_LIBS) $(GULM_LIBS)
|
||||
CFLAGS += $(CCS_CFLAGS) $(GULM_CFLAGS)
|
||||
DEFS += -DUSE_GULM
|
||||
endif
|
||||
|
||||
ifeq ("$(CMAN)", "yes")
|
||||
ifneq (,$(findstring cman,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-cman.c
|
||||
LMLIBS += -ldlm -lcman
|
||||
LMLIBS += $(CMAN_LIBS) $(CONFDB_LIBS) $(DLM_LIBS)
|
||||
CFLAGS += $(CMAN_CFLAGS) $(CONFDB_CFLAGS) $(DLM_CFLAGS)
|
||||
DEFS += -DUSE_CMAN
|
||||
endif
|
||||
|
||||
ifeq ("$(OPENAIS)", "yes")
|
||||
ifneq (,$(findstring openais,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-openais.c
|
||||
LMLIBS += -lSaLck -lcpg
|
||||
LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(SALCK_LIBS)
|
||||
CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(SALCK_CFLAGS)
|
||||
DEFS += -DUSE_OPENAIS
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring corosync,, "@CLVMD@,"))
|
||||
SOURCES += clvmd-corosync.c
|
||||
LMLIBS += $(CONFDB_LIBS) $(CPG_LIBS) $(DLM_LIBS) $(QUORUM_LIBS)
|
||||
CFLAGS += $(CONFDB_CFLAGS) $(CPG_CFLAGS) $(DLM_CFLAGS) $(QUORUM_CFLAGS)
|
||||
DEFS += -DUSE_COROSYNC
|
||||
endif
|
||||
|
||||
|
||||
TARGETS = \
|
||||
clvmd
|
||||
|
||||
LVMLIBS = -llvm -lpthread
|
||||
LVMLIBS = -llvm-internal -lpthread
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
LVMLIBS += -ldevmapper-event
|
||||
@@ -77,20 +86,20 @@ LVMLIBS += -ldevmapper
|
||||
DEFS += -D_REENTRANT
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
include ../../make.tmpl
|
||||
|
||||
INSTALL_TARGETS = \
|
||||
install_clvmd
|
||||
|
||||
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
|
||||
$(CC) -o clvmd $(OBJECTS) $(CFLAGS) $(LDFLAGS) \
|
||||
clvmd: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o clvmd $(OBJECTS) \
|
||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
.PHONY: install_clvmd
|
||||
|
||||
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>
|
||||
@@ -41,7 +45,7 @@
|
||||
|
||||
#include "clvmd-comms.h"
|
||||
#include "clvm.h"
|
||||
#include "log.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "clvmd.h"
|
||||
#include "lvm-functions.h"
|
||||
|
||||
@@ -106,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");
|
||||
@@ -254,7 +263,7 @@ static void _add_up_node(const char *csid)
|
||||
|
||||
static void _cluster_closedown()
|
||||
{
|
||||
unlock_all();
|
||||
destroy_lvhash();
|
||||
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||
cman_finish(c_handle);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -115,20 +119,17 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
lock_cmd = args[0];
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
/* Check to see if the VG is in use by LVM1 */
|
||||
status = do_check_lvm1(lockname);
|
||||
/* P_#global causes a full cache refresh */
|
||||
if (!strcmp(lockname, "P_" VG_GLOBAL))
|
||||
do_refresh_cache();
|
||||
else
|
||||
drop_metadata(lockname + 2);
|
||||
|
||||
do_lock_vg(lock_cmd, lock_flags, lockname);
|
||||
break;
|
||||
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
/* This is the biggie */
|
||||
lock_cmd = args[0] & 0x3F;
|
||||
lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
status = do_lock_lv(lock_cmd, lock_flags, lockname);
|
||||
@@ -141,6 +142,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;
|
||||
@@ -156,7 +165,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:
|
||||
@@ -180,6 +193,7 @@ static int lock_vg(struct local_client *client)
|
||||
(struct clvm_header *) client->bits.localsock.cmd;
|
||||
unsigned char lock_cmd;
|
||||
unsigned char lock_flags;
|
||||
int lock_mode;
|
||||
char *args = header->node + strlen(header->node) + 1;
|
||||
int lkid;
|
||||
int status = 0;
|
||||
@@ -198,12 +212,13 @@ static int lock_vg(struct local_client *client)
|
||||
client->bits.localsock.private = (void *)lock_hash;
|
||||
}
|
||||
|
||||
lock_cmd = args[0] & 0x3F;
|
||||
lock_cmd = args[0] & (LCK_NONBLOCK | LCK_HOLD | LCK_SCOPE_MASK | LCK_TYPE_MASK);
|
||||
lock_mode = ((int)lock_cmd & LCK_TYPE_MASK);
|
||||
lock_flags = args[1];
|
||||
lockname = &args[2];
|
||||
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||
|
||||
if (lock_cmd == LCK_UNLOCK) {
|
||||
if (lock_mode == LCK_UNLOCK) {
|
||||
|
||||
lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
|
||||
if (lkid == 0)
|
||||
@@ -217,11 +232,9 @@ static int lock_vg(struct local_client *client)
|
||||
}
|
||||
else {
|
||||
/* Read locks need to be PR; other modes get passed through */
|
||||
if ((lock_cmd & LCK_TYPE_MASK) == LCK_READ) {
|
||||
lock_cmd &= ~LCK_TYPE_MASK;
|
||||
lock_cmd |= LCK_PREAD;
|
||||
}
|
||||
status = sync_lock(lockname, (int)lock_cmd, (lock_flags & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
|
||||
if (lock_mode == LCK_READ)
|
||||
lock_mode = LCK_PREAD;
|
||||
status = sync_lock(lockname, lock_mode, (lock_cmd & LCK_NONBLOCK) ? LKF_NOQUEUE : 0, &lkid);
|
||||
if (status)
|
||||
status = errno;
|
||||
else
|
||||
@@ -271,6 +284,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:
|
||||
@@ -301,6 +315,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;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -77,7 +77,7 @@ struct cluster_ops *init_cman_cluster(void);
|
||||
|
||||
#ifdef USE_OPENAIS
|
||||
# include <openais/saAis.h>
|
||||
# include <openais/totem/totem.h>
|
||||
# include <corosync/totem/totem.h>
|
||||
# define OPENAIS_CSID_LEN (sizeof(int))
|
||||
# define OPENAIS_MAX_CLUSTER_MESSAGE MESSAGE_SIZE_MAX
|
||||
# define OPENAIS_MAX_CLUSTER_MEMBER_NAME_LEN SA_MAX_NAME_LENGTH
|
||||
@@ -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
|
||||
|
||||
649
daemons/clvmd/clvmd-corosync.c
Normal file
649
daemons/clvmd/clvmd-corosync.c
Normal file
@@ -0,0 +1,649 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 corosync_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len);
|
||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries);
|
||||
static void _cluster_closedown(void);
|
||||
|
||||
/* Hash list of nodes in the cluster */
|
||||
static struct dm_hash_table *node_hash;
|
||||
|
||||
/* Number of active nodes */
|
||||
static int num_nodes;
|
||||
static unsigned int our_nodeid;
|
||||
|
||||
static struct local_client *cluster_client;
|
||||
|
||||
/* Corosync handles */
|
||||
static cpg_handle_t cpg_handle;
|
||||
static quorum_handle_t quorum_handle;
|
||||
|
||||
/* DLM Handle */
|
||||
static dlm_lshandle_t *lockspace;
|
||||
|
||||
static struct cpg_name cpg_group_name;
|
||||
|
||||
/* Corosync callback structs */
|
||||
cpg_callbacks_t corosync_cpg_callbacks = {
|
||||
.cpg_deliver_fn = corosync_cpg_deliver_callback,
|
||||
.cpg_confchg_fn = corosync_cpg_confchg_callback,
|
||||
};
|
||||
|
||||
quorum_callbacks_t quorum_callbacks = {
|
||||
.quorum_notify_fn = NULL,
|
||||
};
|
||||
|
||||
struct node_info
|
||||
{
|
||||
enum {NODE_UNKNOWN, NODE_DOWN, NODE_UP, NODE_CLVMD} state;
|
||||
int nodeid;
|
||||
};
|
||||
|
||||
|
||||
/* Set errno to something approximating the right value and return 0 or -1 */
|
||||
static int cs_to_errno(cs_error_t err)
|
||||
{
|
||||
switch(err)
|
||||
{
|
||||
case CS_OK:
|
||||
return 0;
|
||||
case CS_ERR_LIBRARY:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_VERSION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_INIT:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_TIMEOUT:
|
||||
errno = ETIME;
|
||||
break;
|
||||
case CS_ERR_TRY_AGAIN:
|
||||
errno = EAGAIN;
|
||||
break;
|
||||
case CS_ERR_INVALID_PARAM:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_NO_MEMORY:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case CS_ERR_BAD_HANDLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_BUSY:
|
||||
errno = EBUSY;
|
||||
break;
|
||||
case CS_ERR_ACCESS:
|
||||
errno = EPERM;
|
||||
break;
|
||||
case CS_ERR_NOT_EXIST:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case CS_ERR_NAME_TOO_LONG:
|
||||
errno = ENAMETOOLONG;
|
||||
break;
|
||||
case CS_ERR_EXIST:
|
||||
errno = EEXIST;
|
||||
break;
|
||||
case CS_ERR_NO_SPACE:
|
||||
errno = ENOSPC;
|
||||
break;
|
||||
case CS_ERR_INTERRUPT:
|
||||
errno = EINTR;
|
||||
break;
|
||||
case CS_ERR_NAME_NOT_FOUND:
|
||||
errno = ENOENT;
|
||||
break;
|
||||
case CS_ERR_NO_RESOURCES:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
case CS_ERR_NOT_SUPPORTED:
|
||||
errno = EOPNOTSUPP;
|
||||
break;
|
||||
case CS_ERR_BAD_OPERATION:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_FAILED_OPERATION:
|
||||
errno = EIO;
|
||||
break;
|
||||
case CS_ERR_MESSAGE_ERROR:
|
||||
errno = EIO;
|
||||
break;
|
||||
case CS_ERR_QUEUE_FULL:
|
||||
errno = EXFULL;
|
||||
break;
|
||||
case CS_ERR_QUEUE_NOT_AVAILABLE:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_BAD_FLAGS:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
case CS_ERR_TOO_BIG:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case CS_ERR_NO_SECTIONS:
|
||||
errno = ENOMEM;
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *print_corosync_csid(const char *csid)
|
||||
{
|
||||
static char buf[128];
|
||||
int id;
|
||||
|
||||
memcpy(&id, csid, sizeof(int));
|
||||
sprintf(buf, "%d", id);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void corosync_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
size_t msg_len)
|
||||
{
|
||||
int target_nodeid;
|
||||
|
||||
memcpy(&target_nodeid, msg, COROSYNC_CSID_LEN);
|
||||
|
||||
DEBUGLOG("%u got message from nodeid %d for %d. len %zd\n",
|
||||
our_nodeid, nodeid, target_nodeid, msg_len-4);
|
||||
|
||||
if (nodeid != our_nodeid)
|
||||
if (target_nodeid == our_nodeid || target_nodeid == 0)
|
||||
process_message(cluster_client, (char *)msg+COROSYNC_CSID_LEN,
|
||||
msg_len-COROSYNC_CSID_LEN, (char*)&nodeid);
|
||||
}
|
||||
|
||||
static void corosync_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
||||
{
|
||||
int i;
|
||||
struct node_info *ninfo;
|
||||
|
||||
DEBUGLOG("confchg callback. %zd joined, %zd left, %zd members\n",
|
||||
joined_list_entries, left_list_entries, member_list_entries);
|
||||
|
||||
for (i=0; i<joined_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&joined_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = joined_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
COROSYNC_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
for (i=0; i<left_list_entries; i++) {
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&left_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (ninfo)
|
||||
ninfo->state = NODE_DOWN;
|
||||
}
|
||||
|
||||
for (i=0; i<member_list_entries; i++) {
|
||||
if (member_list[i].nodeid == 0) continue;
|
||||
ninfo = dm_hash_lookup_binary(node_hash,
|
||||
(char *)&member_list[i].nodeid,
|
||||
COROSYNC_CSID_LEN);
|
||||
if (!ninfo) {
|
||||
ninfo = malloc(sizeof(struct node_info));
|
||||
if (!ninfo) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
ninfo->nodeid = member_list[i].nodeid;
|
||||
dm_hash_insert_binary(node_hash,
|
||||
(char *)&ninfo->nodeid,
|
||||
COROSYNC_CSID_LEN, ninfo);
|
||||
}
|
||||
}
|
||||
ninfo->state = NODE_CLVMD;
|
||||
}
|
||||
|
||||
num_nodes = member_list_entries;
|
||||
}
|
||||
|
||||
static int _init_cluster(void)
|
||||
{
|
||||
cs_error_t err;
|
||||
|
||||
node_hash = dm_hash_create(100);
|
||||
|
||||
err = cpg_initialize(&cpg_handle,
|
||||
&corosync_cpg_callbacks);
|
||||
if (err != CS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise Corosync CPG service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise Corosync CPG service: %d", err);
|
||||
return cs_to_errno(err);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,13 +1,20 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
|
||||
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (C) 2002-2003 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* This provides the interface between clvmd and gulm as the cluster
|
||||
/*
|
||||
* This provides the interface between clvmd and gulm as the cluster
|
||||
* and lock manager.
|
||||
*
|
||||
* It also provides the "liblm" functions too as it's hard (and pointless)
|
||||
@@ -17,7 +24,6 @@
|
||||
* on the cluster nodes. That is done in tcp-comms.c
|
||||
*/
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
@@ -44,9 +50,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 +254,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);
|
||||
@@ -951,7 +956,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);
|
||||
|
||||
@@ -1,16 +1,26 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) 2007 Red Hat, Inc. All rights reserved.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
/* This provides the interface between clvmd and OpenAIS as the cluster
|
||||
* and lock manager.
|
||||
/*
|
||||
* Copyright (C) 2007-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This provides the interface between clvmd and OpenAIS as the cluster
|
||||
* and lock manager.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
@@ -37,11 +47,12 @@
|
||||
|
||||
#include <openais/saAis.h>
|
||||
#include <openais/saLck.h>
|
||||
#include <openais/cpg.h>
|
||||
|
||||
#include "list.h"
|
||||
#include <corosync/corotypes.h>
|
||||
#include <corosync/cpg.h>
|
||||
|
||||
#include "locking.h"
|
||||
#include "log.h"
|
||||
#include "lvm-logging.h"
|
||||
#include "clvm.h"
|
||||
#include "clvmd-comms.h"
|
||||
#include "lvm-functions.h"
|
||||
@@ -50,17 +61,18 @@
|
||||
/* Timeout value for several openais calls */
|
||||
#define TIMEOUT 10
|
||||
|
||||
static void cpg_deliver_callback (cpg_handle_t handle,
|
||||
struct cpg_name *groupName,
|
||||
static void openais_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
int msg_len);
|
||||
static void cpg_confchg_callback(cpg_handle_t handle,
|
||||
struct cpg_name *groupName,
|
||||
struct cpg_address *member_list, int member_list_entries,
|
||||
struct cpg_address *left_list, int left_list_entries,
|
||||
struct cpg_address *joined_list, int joined_list_entries);
|
||||
size_t msg_len);
|
||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries);
|
||||
|
||||
static void _cluster_closedown(void);
|
||||
|
||||
/* Hash list of nodes in the cluster */
|
||||
@@ -82,9 +94,9 @@ static SaLckHandleT lck_handle;
|
||||
static struct cpg_name cpg_group_name;
|
||||
|
||||
/* Openais callback structs */
|
||||
cpg_callbacks_t cpg_callbacks = {
|
||||
.cpg_deliver_fn = cpg_deliver_callback,
|
||||
.cpg_confchg_fn = cpg_confchg_callback,
|
||||
cpg_callbacks_t openais_cpg_callbacks = {
|
||||
.cpg_deliver_fn = openais_cpg_deliver_callback,
|
||||
.cpg_confchg_fn = openais_cpg_confchg_callback,
|
||||
};
|
||||
|
||||
struct node_info
|
||||
@@ -192,7 +204,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;
|
||||
@@ -227,12 +239,12 @@ static int add_internal_client(int fd, fd_callback_t callback)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cpg_deliver_callback (cpg_handle_t handle,
|
||||
struct cpg_name *groupName,
|
||||
static void openais_cpg_deliver_callback (cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
uint32_t nodeid,
|
||||
uint32_t pid,
|
||||
void *msg,
|
||||
int msg_len)
|
||||
size_t msg_len)
|
||||
{
|
||||
int target_nodeid;
|
||||
|
||||
@@ -247,11 +259,11 @@ static void cpg_deliver_callback (cpg_handle_t handle,
|
||||
msg_len-OPENAIS_CSID_LEN, (char*)&nodeid);
|
||||
}
|
||||
|
||||
static void cpg_confchg_callback(cpg_handle_t handle,
|
||||
struct cpg_name *groupName,
|
||||
struct cpg_address *member_list, int member_list_entries,
|
||||
struct cpg_address *left_list, int left_list_entries,
|
||||
struct cpg_address *joined_list, int joined_list_entries)
|
||||
static void openais_cpg_confchg_callback(cpg_handle_t handle,
|
||||
const struct cpg_name *groupName,
|
||||
const struct cpg_address *member_list, size_t member_list_entries,
|
||||
const struct cpg_address *left_list, size_t left_list_entries,
|
||||
const struct cpg_address *joined_list, size_t joined_list_entries)
|
||||
{
|
||||
int i;
|
||||
struct node_info *ninfo;
|
||||
@@ -327,7 +339,7 @@ static int _init_cluster(void)
|
||||
lock_hash = dm_hash_create(10);
|
||||
|
||||
err = cpg_initialize(&cpg_handle,
|
||||
&cpg_callbacks);
|
||||
&openais_cpg_callbacks);
|
||||
if (err != SA_AIS_OK) {
|
||||
syslog(LOG_ERR, "Cannot initialise OpenAIS CPG service: %d",
|
||||
err);
|
||||
@@ -339,7 +351,7 @@ static int _init_cluster(void)
|
||||
NULL,
|
||||
&ver);
|
||||
if (err != SA_AIS_OK) {
|
||||
cpg_initialize(&cpg_handle, &cpg_callbacks);
|
||||
cpg_initialize(&cpg_handle, &openais_cpg_callbacks);
|
||||
syslog(LOG_ERR, "Cannot initialise OpenAIS lock service: %d",
|
||||
err);
|
||||
DEBUGLOG("Cannot initialise OpenAIS lock service: %d\n\n", err);
|
||||
@@ -379,7 +391,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);
|
||||
@@ -412,7 +424,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;
|
||||
}
|
||||
|
||||
@@ -434,7 +446,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -38,16 +44,17 @@
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <libdlm.h>
|
||||
#ifdef HAVE_COROSYNC_CONFDB_H
|
||||
#include <corosync/confdb.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
@@ -75,7 +82,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;
|
||||
@@ -90,7 +97,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];
|
||||
@@ -103,6 +110,10 @@ 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;
|
||||
|
||||
typedef void *(lvm_pthread_fn_t)(void*);
|
||||
|
||||
/* Prototypes for code further down */
|
||||
static void sigusr2_handler(int sig);
|
||||
static void sighup_handler(int sig);
|
||||
@@ -131,7 +142,7 @@ static int check_all_clvmds_running(struct local_client *client);
|
||||
static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
|
||||
int len, const char *csid,
|
||||
struct local_client **new_client);
|
||||
static void *lvm_thread_fn(void *);
|
||||
static void lvm_thread_fn(void *) __attribute__ ((noreturn));
|
||||
static int add_to_lvmqueue(struct local_client *client, struct clvm_header *msg,
|
||||
int msglen, const char *csid);
|
||||
static int distribute_command(struct local_client *thisfd);
|
||||
@@ -139,6 +150,8 @@ 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 if_type_t get_cluster_type(void);
|
||||
|
||||
static void usage(char *prog, FILE *file)
|
||||
{
|
||||
@@ -153,6 +166,20 @@ static void usage(char *prog, FILE *file)
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -199,44 +226,47 @@ static const char *decode_cmd(unsigned char cmdl)
|
||||
const char *command;
|
||||
|
||||
switch (cmdl) {
|
||||
case CLVMD_CMD_TEST:
|
||||
command = "TEST";
|
||||
case CLVMD_CMD_TEST:
|
||||
command = "TEST";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
command = "LOCK_VG";
|
||||
case CLVMD_CMD_LOCK_VG:
|
||||
command = "LOCK_VG";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
command = "LOCK_LV";
|
||||
case CLVMD_CMD_LOCK_LV:
|
||||
command = "LOCK_LV";
|
||||
break;
|
||||
case CLVMD_CMD_REFRESH:
|
||||
command = "REFRESH";
|
||||
case CLVMD_CMD_REFRESH:
|
||||
command = "REFRESH";
|
||||
break;
|
||||
case CLVMD_CMD_SET_DEBUG:
|
||||
command = "SET_DEBUG";
|
||||
case CLVMD_CMD_SET_DEBUG:
|
||||
command = "SET_DEBUG";
|
||||
break;
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||
command = "GET_CLUSTERNAME";
|
||||
break;
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
command = "VG_BACKUP";
|
||||
case CLVMD_CMD_VG_BACKUP:
|
||||
command = "VG_BACKUP";
|
||||
break;
|
||||
case CLVMD_CMD_REPLY:
|
||||
command = "REPLY";
|
||||
case CLVMD_CMD_REPLY:
|
||||
command = "REPLY";
|
||||
break;
|
||||
case CLVMD_CMD_VERSION:
|
||||
command = "VERSION";
|
||||
case CLVMD_CMD_VERSION:
|
||||
command = "VERSION";
|
||||
break;
|
||||
case CLVMD_CMD_GOAWAY:
|
||||
command = "GOAWAY";
|
||||
case CLVMD_CMD_GOAWAY:
|
||||
command = "GOAWAY";
|
||||
break;
|
||||
case CLVMD_CMD_LOCK:
|
||||
command = "LOCK";
|
||||
case CLVMD_CMD_LOCK:
|
||||
command = "LOCK";
|
||||
break;
|
||||
case CLVMD_CMD_UNLOCK:
|
||||
command = "UNLOCK";
|
||||
case CLVMD_CMD_UNLOCK:
|
||||
command = "UNLOCK";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
case CLVMD_CMD_LOCK_QUERY:
|
||||
command = "LOCK_QUERY";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -253,6 +283,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;
|
||||
@@ -261,7 +292,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);
|
||||
@@ -272,7 +303,7 @@ int main(int argc, char *argv[])
|
||||
exit(0);
|
||||
|
||||
case 'R':
|
||||
return refresh_clvmd();
|
||||
return refresh_clvmd()==1?0:1;
|
||||
|
||||
case 'C':
|
||||
clusterwide_opt = 1;
|
||||
@@ -294,6 +325,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) {
|
||||
@@ -320,7 +354,7 @@ int main(int argc, char *argv[])
|
||||
/* Sending to stderr makes no sense for a detached daemon */
|
||||
if (debug == DEBUG_STDERR)
|
||||
debug = DEBUG_SYSLOG;
|
||||
return debug_clvmd(debug, clusterwide_opt);
|
||||
return debug_clvmd(debug, clusterwide_opt)==1?0:1;
|
||||
}
|
||||
|
||||
/* Fork into the background (unless requested not to) */
|
||||
@@ -346,21 +380,26 @@ 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);
|
||||
init_lvhash();
|
||||
|
||||
/* Start the cluster interface */
|
||||
if (cluster_iface == IF_AUTO)
|
||||
cluster_iface = get_cluster_type();
|
||||
|
||||
#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;
|
||||
@@ -369,7 +408,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;
|
||||
@@ -377,9 +416,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;
|
||||
@@ -418,7 +466,10 @@ 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");
|
||||
pthread_create(&lvm_thread, NULL, lvm_thread_fn,
|
||||
|
||||
/* Don't let anyone else to do work until we are started */
|
||||
pthread_mutex_lock(&lvm_start_mutex);
|
||||
pthread_create(&lvm_thread, NULL, (lvm_pthread_fn_t*)lvm_thread_fn,
|
||||
(void *)(long)using_gulm);
|
||||
|
||||
/* Tell the rest of the cluster our version number */
|
||||
@@ -438,6 +489,8 @@ int main(int argc, char *argv[])
|
||||
/* Do some work */
|
||||
main_loop(local_sock, cmd_timeout);
|
||||
|
||||
destroy_lvm();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -631,6 +684,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;
|
||||
@@ -1747,15 +1805,12 @@ static int process_work_item(struct lvm_thread_cmd *cmd)
|
||||
/*
|
||||
* Routine that runs in the "LVM thread".
|
||||
*/
|
||||
static __attribute__ ((noreturn)) void *lvm_thread_fn(void *arg)
|
||||
static 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 */
|
||||
@@ -1775,15 +1830,15 @@ 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);
|
||||
@@ -1833,7 +1888,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);
|
||||
|
||||
@@ -1994,3 +2049,76 @@ 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try and find a cluster system in corosync's objdb, if it is running. This is
|
||||
* only called if the command-line option is not present, and if it fails
|
||||
* we still try the interfaces in order.
|
||||
*/
|
||||
static if_type_t get_cluster_type()
|
||||
{
|
||||
#ifdef HAVE_COROSYNC_CONFDB_H
|
||||
confdb_handle_t handle;
|
||||
if_type_t type = IF_AUTO;
|
||||
int result;
|
||||
char buf[255];
|
||||
size_t namelen = sizeof(buf);
|
||||
hdb_handle_t cluster_handle;
|
||||
hdb_handle_t clvmd_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
|
||||
};
|
||||
|
||||
result = confdb_initialize (&handle, &callbacks);
|
||||
if (result != CS_OK)
|
||||
return type;
|
||||
|
||||
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_object_find_start(handle, cluster_handle);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
result = confdb_object_find(handle, cluster_handle, (void *)"clvmd", strlen("clvmd"), &clvmd_handle);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
result = confdb_key_get(handle, clvmd_handle, (void *)"interface", strlen("interface"), buf, &namelen);
|
||||
if (result != CS_OK)
|
||||
goto out;
|
||||
|
||||
buf[namelen] = '\0';
|
||||
type = parse_cluster_interface(buf);
|
||||
DEBUGLOG("got interface type '%s' from confdb\n", buf);
|
||||
out:
|
||||
confdb_finalize(handle);
|
||||
return type;
|
||||
#else
|
||||
return IF_AUTO;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2008 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,11 +46,13 @@
|
||||
/* 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"
|
||||
#include "defaults.h"
|
||||
#include "memlock.h"
|
||||
|
||||
static struct cmd_context *cmd = NULL;
|
||||
static struct dm_hash_table *lv_hash = NULL;
|
||||
@@ -61,8 +66,6 @@ struct lv_info {
|
||||
int lock_mode;
|
||||
};
|
||||
|
||||
#define LCK_MASK (LCK_TYPE_MASK | LCK_SCOPE_MASK)
|
||||
|
||||
static const char *decode_locking_cmd(unsigned char cmdl)
|
||||
{
|
||||
static char buf[128];
|
||||
@@ -71,23 +74,23 @@ static const char *decode_locking_cmd(unsigned char cmdl)
|
||||
const char *command;
|
||||
|
||||
switch (cmdl & LCK_TYPE_MASK) {
|
||||
case LCK_NULL:
|
||||
type = "NULL";
|
||||
case LCK_NULL:
|
||||
type = "NULL";
|
||||
break;
|
||||
case LCK_READ:
|
||||
type = "READ";
|
||||
case LCK_READ:
|
||||
type = "READ";
|
||||
break;
|
||||
case LCK_PREAD:
|
||||
type = "PREAD";
|
||||
case LCK_PREAD:
|
||||
type = "PREAD";
|
||||
break;
|
||||
case LCK_WRITE:
|
||||
type = "WRITE";
|
||||
case LCK_WRITE:
|
||||
type = "WRITE";
|
||||
break;
|
||||
case LCK_EXCL:
|
||||
type = "EXCL";
|
||||
case LCK_EXCL:
|
||||
type = "EXCL";
|
||||
break;
|
||||
case LCK_UNLOCK:
|
||||
type = "UNLOCK";
|
||||
case LCK_UNLOCK:
|
||||
type = "UNLOCK";
|
||||
break;
|
||||
default:
|
||||
type = "unknown";
|
||||
@@ -95,34 +98,35 @@ static const char *decode_locking_cmd(unsigned char cmdl)
|
||||
}
|
||||
|
||||
switch (cmdl & LCK_SCOPE_MASK) {
|
||||
case LCK_VG:
|
||||
scope = "VG";
|
||||
case LCK_VG:
|
||||
scope = "VG";
|
||||
command = "LCK_VG";
|
||||
break;
|
||||
case LCK_LV:
|
||||
case LCK_LV:
|
||||
scope = "LV";
|
||||
switch (cmdl & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE & LCK_MASK:
|
||||
command = "LCK_LV_EXCLUSIVE";
|
||||
break;
|
||||
case LCK_LV_SUSPEND & LCK_MASK:
|
||||
command = "LCK_LV_SUSPEND";
|
||||
break;
|
||||
case LCK_LV_RESUME & LCK_MASK:
|
||||
command = "LCK_LV_RESUME";
|
||||
break;
|
||||
case LCK_LV_ACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_ACTIVATE";
|
||||
break;
|
||||
case LCK_LV_DEACTIVATE & LCK_MASK:
|
||||
command = "LCK_LV_DEACTIVATE";
|
||||
break;
|
||||
default:
|
||||
command = "unknown";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
scope = "unknown";
|
||||
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;
|
||||
}
|
||||
@@ -141,10 +145,11 @@ 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 " : "",
|
||||
sprintf(buf, "0x%x (%s%s%s%s)", flags,
|
||||
flags & LCK_PARTIAL_MODE ? "PARTIAL_MODE " : "",
|
||||
flags & LCK_MIRROR_NOSYNC_MODE ? "MIRROR_NOSYNC " : "",
|
||||
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR " : "");
|
||||
flags & LCK_DMEVENTD_MONITOR_MODE ? "DMEVENTD_MONITOR " : "",
|
||||
flags & LCK_CONVERT ? "CONVERT " : "");
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -154,32 +159,79 @@ 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);
|
||||
}
|
||||
|
||||
@@ -190,16 +242,25 @@ int hold_lock(char *resource, int mode, int flags)
|
||||
int saved_errno;
|
||||
struct lv_info *lvi;
|
||||
|
||||
flags &= LKF_NOQUEUE; /* Only LKF_NOQUEUE is valid here */
|
||||
/* Mask off invalid options */
|
||||
flags &= LKF_NOQUEUE | LKF_CONVERT;
|
||||
|
||||
pthread_mutex_lock(&lv_hash_lock);
|
||||
lvi = dm_hash_lookup(lv_hash, resource);
|
||||
pthread_mutex_unlock(&lv_hash_lock);
|
||||
lvi = lookup_info(resource);
|
||||
|
||||
if (lvi && lvi->lock_mode == mode) {
|
||||
DEBUGLOG("hold_lock, lock mode %d already held\n", mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only allow explicit conversions */
|
||||
if (lvi && !(flags & LKF_CONVERT)) {
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
if (lvi) {
|
||||
/* Already exists - convert it */
|
||||
status =
|
||||
sync_lock(resource, mode, LKF_CONVERT | flags,
|
||||
&lvi->lock_id);
|
||||
sync_lock(resource, mode, flags, &lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (!status)
|
||||
lvi->lock_mode = mode;
|
||||
@@ -215,17 +276,15 @@ int hold_lock(char *resource, int mode, int flags)
|
||||
return -1;
|
||||
|
||||
lvi->lock_mode = mode;
|
||||
status = sync_lock(resource, mode, flags, &lvi->lock_id);
|
||||
status = sync_lock(resource, mode, flags & ~LKF_CONVERT, &lvi->lock_id);
|
||||
saved_errno = errno;
|
||||
if (status) {
|
||||
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;
|
||||
@@ -238,10 +297,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;
|
||||
}
|
||||
@@ -249,9 +305,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,
|
||||
@@ -279,7 +333,8 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
|
||||
|
||||
/* Is it already open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == mode) {
|
||||
if (oldmode == mode && (lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_activate_lv, lock already held at %d\n", oldmode);
|
||||
return 0; /* Nothing to do */
|
||||
}
|
||||
|
||||
@@ -296,9 +351,13 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
|
||||
mode = LKM_EXMODE;
|
||||
}
|
||||
|
||||
/* Try to get the lock if it's a clustered volume group */
|
||||
/*
|
||||
* Try to get the lock if it's a clustered volume group.
|
||||
* Use lock conversion only if requested, to prevent implicit conversion
|
||||
* of exclusive lock to shared one during activation.
|
||||
*/
|
||||
if (lock_flags & LCK_CLUSTER_VG) {
|
||||
status = hold_lock(resource, mode, LKF_NOQUEUE);
|
||||
status = hold_lock(resource, mode, LKF_NOQUEUE | (lock_flags & LCK_CONVERT?LKF_CONVERT:0));
|
||||
if (status) {
|
||||
/* Return an LVM-sensible error for this.
|
||||
* Forcing EIO makes the upper level return this text
|
||||
@@ -328,13 +387,13 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
|
||||
}
|
||||
|
||||
/* Resume the LV if it was active */
|
||||
static int do_resume_lv(char *resource)
|
||||
static int do_resume_lv(char *resource, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1) {
|
||||
if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_resume_lv, lock not already held\n");
|
||||
return 0; /* We don't need to do anything */
|
||||
}
|
||||
@@ -346,15 +405,15 @@ static int do_resume_lv(char *resource)
|
||||
}
|
||||
|
||||
/* Suspend the device if active */
|
||||
static int do_suspend_lv(char *resource)
|
||||
static int do_suspend_lv(char *resource, unsigned char lock_flags)
|
||||
{
|
||||
int oldmode;
|
||||
struct lvinfo lvi;
|
||||
|
||||
/* Is it open ? */
|
||||
oldmode = get_current_lock(resource);
|
||||
if (oldmode == -1) {
|
||||
DEBUGLOG("do_suspend_lv, lock held at %d\n", oldmode);
|
||||
if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("do_suspend_lv, lock not already held\n");
|
||||
return 0; /* Not active, so it's OK */
|
||||
}
|
||||
|
||||
@@ -394,48 +453,69 @@ 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 = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
DEBUGLOG("do_lock_lv: resource '%s', cmd = %s, flags = %s, memlock = %d\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags), memlock());
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||
/* Reinitialise various settings inc. logging, filters */
|
||||
if (do_refresh_cache()) {
|
||||
log_error("Updated config file invalid. Aborting.");
|
||||
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;
|
||||
|
||||
/* clvmd should never try to read suspended device */
|
||||
init_ignore_suspended_devices(1);
|
||||
|
||||
switch (command & LCK_MASK) {
|
||||
case LCK_LV_EXCLUSIVE:
|
||||
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
|
||||
break;
|
||||
|
||||
case LCK_LV_SUSPEND:
|
||||
status = do_suspend_lv(resource);
|
||||
status = do_suspend_lv(resource, lock_flags);
|
||||
if (!status)
|
||||
suspended++;
|
||||
break;
|
||||
|
||||
case LCK_UNLOCK:
|
||||
case LCK_LV_RESUME: /* if active */
|
||||
status = do_resume_lv(resource);
|
||||
status = do_resume_lv(resource, lock_flags);
|
||||
if (!status)
|
||||
suspended--;
|
||||
break;
|
||||
@@ -454,20 +534,19 @@ 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);
|
||||
|
||||
DEBUGLOG("Command return is %d\n", status);
|
||||
DEBUGLOG("Command return is %d, memlock is %d\n", status, memlock());
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -477,12 +556,14 @@ int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
|
||||
lock out on this node (because we are the node modifying the metadata)
|
||||
before suspending cluster-wide.
|
||||
LKF_CONVERT is used always, local node is going to modify metadata
|
||||
*/
|
||||
if (command == LCK_LV_SUSPEND) {
|
||||
if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_SUSPEND &&
|
||||
(lock_flags & LCK_CLUSTER_VG)) {
|
||||
DEBUGLOG("pre_lock_lv: resource '%s', cmd = %s, flags = %s\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags));
|
||||
|
||||
if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE))
|
||||
if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE | LKF_CONVERT))
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
@@ -495,7 +576,8 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
int status;
|
||||
|
||||
/* Opposite of above, done on resume after a metadata update */
|
||||
if (command == LCK_LV_RESUME) {
|
||||
if ((command & (LCK_SCOPE_MASK | LCK_TYPE_MASK)) == LCK_LV_RESUME &&
|
||||
(lock_flags & LCK_CLUSTER_VG)) {
|
||||
int oldmode;
|
||||
|
||||
DEBUGLOG
|
||||
@@ -514,7 +596,7 @@ int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||
return EIO;
|
||||
|
||||
if (lvi.exists) {
|
||||
if (hold_lock(resource, LKM_CRMODE, 0))
|
||||
if (hold_lock(resource, LKM_CRMODE, LKF_CONVERT))
|
||||
return errno;
|
||||
} else {
|
||||
if (hold_unlock(resource))
|
||||
@@ -537,15 +619,24 @@ int do_check_lvm1(const char *vgname)
|
||||
|
||||
int do_refresh_cache()
|
||||
{
|
||||
int ret;
|
||||
DEBUGLOG("Refreshing context\n");
|
||||
log_notice("Refreshing context");
|
||||
|
||||
ret = refresh_toolcontext(cmd);
|
||||
init_full_scan_done(0);
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
|
||||
return ret==1?0:-1;
|
||||
if (!refresh_toolcontext(cmd)) {
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
init_full_scan_done(0);
|
||||
init_ignore_suspended_devices(1);
|
||||
lvmcache_label_scan(cmd, 2);
|
||||
dm_pool_empty(cmd->mem);
|
||||
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -589,13 +680,45 @@ static void drop_vg_locks()
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop lvmcache metadata
|
||||
* Handle VG lock - drop metadata or update lvmcache state
|
||||
*/
|
||||
void drop_metadata(const char *vgname)
|
||||
void do_lock_vg(unsigned char command, unsigned char lock_flags, char *resource)
|
||||
{
|
||||
DEBUGLOG("Dropping metadata for VG %s\n", vgname);
|
||||
uint32_t lock_cmd = command;
|
||||
char *vgname = resource + 2;
|
||||
|
||||
DEBUGLOG("do_lock_vg: resource '%s', cmd = %s, flags = %s, memlock = %d\n",
|
||||
resource, decode_locking_cmd(command), decode_flags(lock_flags), memlock());
|
||||
|
||||
/* P_#global causes a full cache refresh */
|
||||
if (!strcmp(resource, "P_" VG_GLOBAL)) {
|
||||
do_refresh_cache();
|
||||
return;
|
||||
}
|
||||
|
||||
lock_cmd &= (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_HOLD);
|
||||
|
||||
/*
|
||||
* Check if LCK_CACHE should be set. All P_ locks except # are cache related.
|
||||
*/
|
||||
if (strncmp(resource, "P_#", 3) && !strncmp(resource, "P_", 2))
|
||||
lock_cmd |= LCK_CACHE;
|
||||
|
||||
pthread_mutex_lock(&lvm_lock);
|
||||
lvmcache_drop_metadata(vgname);
|
||||
switch (lock_cmd) {
|
||||
case LCK_VG_COMMIT:
|
||||
DEBUGLOG("vg_commit notification for VG %s\n", vgname);
|
||||
lvmcache_commit_metadata(vgname);
|
||||
break;
|
||||
case LCK_VG_REVERT:
|
||||
DEBUGLOG("vg_revert notification for VG %s\n", vgname);
|
||||
lvmcache_drop_metadata(vgname, 1);
|
||||
break;
|
||||
case LCK_VG_DROP_CACHE:
|
||||
default:
|
||||
DEBUGLOG("Invalidating cached metadata for VG %s\n", vgname);
|
||||
lvmcache_drop_metadata(vgname, 0);
|
||||
}
|
||||
pthread_mutex_unlock(&lvm_lock);
|
||||
}
|
||||
|
||||
@@ -651,7 +774,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)
|
||||
{
|
||||
|
||||
@@ -660,7 +783,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);
|
||||
|
||||
/*
|
||||
@@ -698,14 +821,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)
|
||||
{
|
||||
@@ -714,36 +829,42 @@ 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();
|
||||
init_ignore_suspended_devices(1);
|
||||
|
||||
/* Remove any non-LV locks that may have been left around */
|
||||
if (using_gulm)
|
||||
@@ -756,3 +877,10 @@ int init_lvm(int using_gulm)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void destroy_lvm(void)
|
||||
{
|
||||
if (cmd)
|
||||
destroy_toolcontext(cmd);
|
||||
cmd = NULL;
|
||||
}
|
||||
|
||||
@@ -22,17 +22,20 @@ 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);
|
||||
extern void do_lock_vg(unsigned char command, unsigned char lock_flags,
|
||||
char *resource);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
|
||||
/*
|
||||
* Tell all clvmds in a cluster to refresh their toolcontext
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
@@ -1,19 +1,29 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
|
||||
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Copyright (C) 2002-2003 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* This provides the inter-clvmd communications for a system without CMAN.
|
||||
There is a listening TCP socket which accepts new connections in the
|
||||
normal way.
|
||||
It can also make outgoing connnections to the other clvmd nodes.
|
||||
*/
|
||||
/*
|
||||
* This provides the inter-clvmd communications for a system without CMAN.
|
||||
* There is a listening TCP socket which accepts new connections in the
|
||||
* normal way.
|
||||
* 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>
|
||||
|
||||
40
daemons/cmirrord/Makefile.in
Normal file
40
daemons/cmirrord/Makefile.in
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# 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 General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CPG_LIBS = @CPG_LIBS@
|
||||
CPG_CFLAGS = @CPG_CFLAGS@
|
||||
SACKPT_LIBS = @SACKPT_LIBS@
|
||||
SACKPT_CFLAGS = @SACKPT_CFLAGS@
|
||||
|
||||
SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
|
||||
|
||||
TARGETS = cmirrord
|
||||
|
||||
include ../../make.tmpl
|
||||
|
||||
LIBS += -ldevmapper
|
||||
LMLIBS += $(CPG_LIBS) $(SACKPT_LIBS)
|
||||
CFLAGS += $(CPG_CFLAGS) $(SACKPT_CFLAGS)
|
||||
|
||||
cmirrord: $(OBJECTS) $(top_builddir)/lib/liblvm-internal.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o cmirrord $(OBJECTS) \
|
||||
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||
|
||||
install: $(TARGETS)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) cmirrord \
|
||||
$(usrsbindir)/cmirrord
|
||||
267
daemons/cmirrord/clogd.c
Normal file
267
daemons/cmirrord/clogd.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v.2.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "common.h"
|
||||
#include "functions.h"
|
||||
#include "link_mon.h"
|
||||
#include "local.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static volatile sig_atomic_t exit_now = 0;
|
||||
/* FIXME Review signal handling. Should be volatile sig_atomic_t */
|
||||
static sigset_t signal_mask;
|
||||
static volatile sig_atomic_t signal_received;
|
||||
|
||||
static void process_signals(void);
|
||||
static void daemonize(void);
|
||||
static void init_all(void);
|
||||
static void cleanup_all(void);
|
||||
|
||||
int main(int argc __attribute((unused)), char *argv[] __attribute((unused)))
|
||||
{
|
||||
daemonize();
|
||||
|
||||
init_all();
|
||||
|
||||
/* Parent can now exit, we're ready to handle requests */
|
||||
kill(getppid(), SIGTERM);
|
||||
|
||||
LOG_PRINT("Starting cmirrord:");
|
||||
LOG_PRINT(" Built: "__DATE__" "__TIME__"\n");
|
||||
LOG_DBG(" Compiled with debugging.");
|
||||
|
||||
while (!exit_now) {
|
||||
links_monitor();
|
||||
|
||||
links_issue_callbacks();
|
||||
|
||||
process_signals();
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* parent_exit_handler: exit the parent
|
||||
* @sig: the signal
|
||||
*
|
||||
*/
|
||||
static void parent_exit_handler(int sig __attribute((unused)))
|
||||
{
|
||||
exit_now = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* create_lockfile - create and lock a lock file
|
||||
* @lockfile: location of lock file
|
||||
*
|
||||
* Returns: 0 on success, -1 otherwise
|
||||
*/
|
||||
static int create_lockfile(const 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());
|
||||
|
||||
/* FIXME Handle other non-error returns without aborting */
|
||||
if (write(fd, buffer, strlen(buffer)) < strlen(buffer)){
|
||||
close(fd);
|
||||
unlink(lockfile);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sig_handler(int sig)
|
||||
{
|
||||
/* FIXME Races - don't touch signal_mask here. */
|
||||
sigaddset(&signal_mask, sig);
|
||||
signal_received = 1;
|
||||
}
|
||||
|
||||
static void process_signal(int sig){
|
||||
int r = 0;
|
||||
|
||||
switch(sig) {
|
||||
case SIGINT:
|
||||
case SIGQUIT:
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
r += log_status();
|
||||
break;
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
log_debug();
|
||||
/*local_debug();*/
|
||||
cluster_debug();
|
||||
return;
|
||||
default:
|
||||
LOG_PRINT("Unknown signal received... ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
LOG_DBG("No current cluster logs... safe to exit.");
|
||||
cleanup_all();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
LOG_ERROR("Cluster logs exist. Refusing to exit.");
|
||||
}
|
||||
|
||||
static void process_signals(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
if (!signal_received)
|
||||
return;
|
||||
|
||||
signal_received = 0;
|
||||
|
||||
for (x = 1; x < _NSIG; x++) {
|
||||
if (sigismember(&signal_mask, x)) {
|
||||
sigdelset(&signal_mask, x);
|
||||
process_signal(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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("cmirrord", LOG_PID, LOG_DAEMON);
|
||||
|
||||
if (create_lockfile(CMIRRORD_PIDFILE))
|
||||
exit(EXIT_LOCKFILE);
|
||||
|
||||
/* FIXME Replace with sigaction. (deprecated) */
|
||||
signal(SIGINT, &sig_handler);
|
||||
signal(SIGQUIT, &sig_handler);
|
||||
signal(SIGTERM, &sig_handler);
|
||||
signal(SIGHUP, &sig_handler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGUSR1, &sig_handler);
|
||||
signal(SIGUSR2, &sig_handler);
|
||||
sigemptyset(&signal_mask);
|
||||
signal_received = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_all
|
||||
*
|
||||
* Initialize modules. Exit on failure.
|
||||
*/
|
||||
static void init_all(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = init_local()) ||
|
||||
(r = init_cluster())) {
|
||||
exit(r);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup_all
|
||||
*
|
||||
* Clean up before exiting
|
||||
*/
|
||||
static void cleanup_all(void)
|
||||
{
|
||||
cleanup_local();
|
||||
cleanup_cluster();
|
||||
}
|
||||
1661
daemons/cmirrord/cluster.c
Normal file
1661
daemons/cmirrord/cluster.c
Normal file
File diff suppressed because it is too large
Load Diff
76
daemons/cmirrord/cluster.h
Normal file
76
daemons/cmirrord/cluster.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_CLUSTER_H
|
||||
#define _LVM_CLOG_CLUSTER_H
|
||||
|
||||
#include "dm-log-userspace.h"
|
||||
#include "libdevmapper.h"
|
||||
|
||||
#define DM_ULOG_RESPONSE 0x1000U /* in last byte of 32-bit value */
|
||||
#define DM_ULOG_CHECKPOINT_READY 21
|
||||
#define DM_ULOG_MEMBER_JOIN 22
|
||||
|
||||
/*
|
||||
* There is other information in addition to what can
|
||||
* be found in the dm_ulog_request structure that we
|
||||
* need for processing. 'clog_request' is the wrapping
|
||||
* structure we use to make the additional fields
|
||||
* available.
|
||||
*/
|
||||
struct clog_request {
|
||||
/*
|
||||
* If we don't use a union, the structure size will
|
||||
* vary between 32-bit and 64-bit machines. So, we
|
||||
* pack two 64-bit version numbers in there to force
|
||||
* the size of the structure to be the same.
|
||||
*
|
||||
* The two version numbers also help us with endian
|
||||
* issues. The first is always little endian, while
|
||||
* the second is in native format of the sending
|
||||
* machine. If the two are equal, there is no need
|
||||
* to do endian conversions.
|
||||
*/
|
||||
union {
|
||||
uint64_t version[2]; /* LE version and native version */
|
||||
struct dm_list list;
|
||||
} u;
|
||||
|
||||
/*
|
||||
* 'originator' is the machine from which the requests
|
||||
* was made.
|
||||
*/
|
||||
uint32_t originator;
|
||||
|
||||
/*
|
||||
* 'pit_server' is the "point-in-time" server for the
|
||||
* request. (I.e. The machine that was the server at
|
||||
* the time the request was issued - only important during
|
||||
* startup.
|
||||
*/
|
||||
uint32_t pit_server;
|
||||
|
||||
/*
|
||||
* The request from the kernel that is being processed
|
||||
*/
|
||||
struct dm_ulog_request u_rq;
|
||||
};
|
||||
|
||||
int init_cluster(void);
|
||||
void cleanup_cluster(void);
|
||||
void cluster_debug(void);
|
||||
|
||||
int create_cluster_cpg(char *uuid, uint64_t luid);
|
||||
int destroy_cluster_cpg(char *uuid);
|
||||
|
||||
int cluster_send(struct clog_request *rq);
|
||||
|
||||
#endif /* _LVM_CLOG_CLUSTER_H */
|
||||
33
daemons/cmirrord/common.h
Normal file
33
daemons/cmirrord/common.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_COMMON_H
|
||||
#define _LVM_CLOG_COMMON_H
|
||||
|
||||
/*
|
||||
* If there are problems when forking off to become a daemon,
|
||||
* the child will exist with one of these codes. This allows
|
||||
* the parent to know the reason for the failure and print it
|
||||
* to the launching terminal.
|
||||
*
|
||||
* #define EXIT_SUCCESS 0 (from stdlib.h)
|
||||
* #define EXIT_FAILURE 1 (from stdlib.h)
|
||||
*/
|
||||
#define EXIT_LOCKFILE 2
|
||||
#define EXIT_KERNEL_SOCKET 3 /* Failed netlink socket create */
|
||||
#define EXIT_KERNEL_BIND 4
|
||||
#define EXIT_KERNEL_SETSOCKOPT 5
|
||||
#define EXIT_CLUSTER_CKPT_INIT 6 /* Failed to init checkpoint */
|
||||
#define EXIT_QUEUE_NOMEM 7
|
||||
|
||||
#define DM_ULOG_REQUEST_SIZE 1024
|
||||
|
||||
#endif /* _LVM_CLOG_COMMON_H */
|
||||
210
daemons/cmirrord/compat.c
Normal file
210
daemons/cmirrord/compat.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "cluster.h"
|
||||
#include "compat.h"
|
||||
#include "xlate.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Older versions of the log daemon communicate with different
|
||||
* versions of the inter-machine communication structure, which
|
||||
* varies in size and fields. The older versions append the
|
||||
* standard upstream version of the structure to every request.
|
||||
* COMPAT_OFFSET is where the upstream structure starts.
|
||||
*/
|
||||
#define COMPAT_OFFSET 256
|
||||
|
||||
static void v5_data_endian_switch(struct clog_request *rq, int to_network __attribute((unused)))
|
||||
{
|
||||
int i, end;
|
||||
int64_t *pi64;
|
||||
uint64_t *pu64;
|
||||
uint32_t rq_type = rq->u_rq.request_type & ~DM_ULOG_RESPONSE;
|
||||
|
||||
if (rq->u_rq.request_type & DM_ULOG_RESPONSE) {
|
||||
switch (rq_type) {
|
||||
case DM_ULOG_CTR:
|
||||
case DM_ULOG_DTR:
|
||||
LOG_ERROR("Invalid response type in endian switch");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
case DM_ULOG_PRESUSPEND:
|
||||
case DM_ULOG_POSTSUSPEND:
|
||||
case DM_ULOG_RESUME:
|
||||
case DM_ULOG_FLUSH:
|
||||
case DM_ULOG_MARK_REGION:
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
case DM_ULOG_SET_REGION_SYNC:
|
||||
case DM_ULOG_CHECKPOINT_READY:
|
||||
case DM_ULOG_MEMBER_JOIN:
|
||||
case DM_ULOG_STATUS_INFO:
|
||||
case DM_ULOG_STATUS_TABLE:
|
||||
/* No outbound data */
|
||||
break;
|
||||
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
pi64 = (int64_t *)rq->u_rq.data;
|
||||
*pi64 = xlate64(*pi64);
|
||||
break;
|
||||
case DM_ULOG_GET_RESYNC_WORK:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
pi64 = (int64_t *)rq->u_rq.data;
|
||||
pu64 = ((uint64_t *)rq->u_rq.data) + 1;
|
||||
*pi64 = xlate64(*pi64);
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown request type, %u", rq_type);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
switch (rq_type) {
|
||||
case DM_ULOG_CTR:
|
||||
case DM_ULOG_DTR:
|
||||
LOG_ERROR("Invalid request type in endian switch");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
case DM_ULOG_PRESUSPEND:
|
||||
case DM_ULOG_POSTSUSPEND:
|
||||
case DM_ULOG_RESUME:
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_FLUSH:
|
||||
case DM_ULOG_GET_RESYNC_WORK:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
case DM_ULOG_STATUS_INFO:
|
||||
case DM_ULOG_STATUS_TABLE:
|
||||
case DM_ULOG_CHECKPOINT_READY:
|
||||
case DM_ULOG_MEMBER_JOIN:
|
||||
/* No incoming data */
|
||||
break;
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
case DM_ULOG_MARK_REGION:
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
end = rq->u_rq.data_size/sizeof(uint64_t);
|
||||
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
for (i = 0; i < end; i++)
|
||||
pu64[i] = xlate64(pu64[i]);
|
||||
break;
|
||||
case DM_ULOG_SET_REGION_SYNC:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
pi64 = ((int64_t *)rq->u_rq.data) + 1;
|
||||
*pu64 = xlate64(*pu64);
|
||||
*pi64 = xlate64(*pi64);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown request type, %u", rq_type);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int v5_endian_to_network(struct clog_request *rq)
|
||||
{
|
||||
int size;
|
||||
struct dm_ulog_request *u_rq = &rq->u_rq;
|
||||
|
||||
size = sizeof(*rq) + u_rq->data_size;
|
||||
|
||||
u_rq->error = xlate32(u_rq->error);
|
||||
u_rq->seq = xlate32(u_rq->seq);
|
||||
u_rq->request_type = xlate32(u_rq->request_type);
|
||||
u_rq->data_size = xlate64(u_rq->data_size);
|
||||
|
||||
rq->originator = xlate32(rq->originator);
|
||||
|
||||
v5_data_endian_switch(rq, 1);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int clog_request_to_network(struct clog_request *rq)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* FIXME: Remove this safety check */
|
||||
if (rq->u.version[0] != xlate64(rq->u.version[1])) {
|
||||
LOG_ERROR("Programmer error: version[0] must be LE");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Are we already running in the endian mode we send
|
||||
* over the wire?
|
||||
*/
|
||||
if (rq->u.version[0] == rq->u.version[1])
|
||||
return 0;
|
||||
|
||||
r = v5_endian_to_network(rq);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int v5_endian_from_network(struct clog_request *rq)
|
||||
{
|
||||
int size;
|
||||
struct dm_ulog_request *u_rq = &rq->u_rq;
|
||||
|
||||
u_rq->error = xlate32(u_rq->error);
|
||||
u_rq->seq = xlate32(u_rq->seq);
|
||||
u_rq->request_type = xlate32(u_rq->request_type);
|
||||
u_rq->data_size = xlate64(u_rq->data_size);
|
||||
|
||||
rq->originator = xlate32(rq->originator);
|
||||
|
||||
size = sizeof(*rq) + u_rq->data_size;
|
||||
|
||||
v5_data_endian_switch(rq, 0);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int clog_request_from_network(void *data, size_t data_len)
|
||||
{
|
||||
uint64_t *vp = data;
|
||||
uint64_t version = xlate64(vp[0]);
|
||||
uint64_t unconverted_version = vp[1];
|
||||
struct clog_request *rq = data;
|
||||
|
||||
switch (version) {
|
||||
case 5: /* Upstream */
|
||||
if (version == unconverted_version)
|
||||
return 0;
|
||||
break;
|
||||
case 4: /* RHEL 5.[45] */
|
||||
case 3: /* RHEL 5.3 */
|
||||
case 2: /* RHEL 5.2 */
|
||||
/* FIXME: still need to account for payload */
|
||||
if (data_len < (COMPAT_OFFSET + sizeof(*rq)))
|
||||
return -ENOSPC;
|
||||
|
||||
rq = (struct clog_request *)((char *)data + COMPAT_OFFSET);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unable to process cluster message: "
|
||||
"Incompatible version");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
v5_endian_from_network(rq);
|
||||
return 0;
|
||||
}
|
||||
25
daemons/cmirrord/compat.h
Normal file
25
daemons/cmirrord/compat.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*/
|
||||
#ifndef _LVM_CLOG_COMPAT_H
|
||||
#define _LVM_CLOG_COMPAT_H
|
||||
|
||||
/*
|
||||
* The intermachine communication structure version are:
|
||||
* 0: Unused
|
||||
* 1: Never in the wild
|
||||
* 2: RHEL 5.2
|
||||
* 3: RHEL 5.3
|
||||
* 4: RHEL 5.4, RHEL 5.5
|
||||
* 5: RHEL 6, Current Upstream Format
|
||||
*/
|
||||
#define CLOG_TFR_VERSION 5
|
||||
|
||||
int clog_request_to_network(struct clog_request *rq);
|
||||
int clog_request_from_network(void *data, size_t data_len);
|
||||
|
||||
#endif /* _LVM_CLOG_COMPAT_H */
|
||||
1873
daemons/cmirrord/functions.c
Normal file
1873
daemons/cmirrord/functions.c
Normal file
File diff suppressed because it is too large
Load Diff
34
daemons/cmirrord/functions.h
Normal file
34
daemons/cmirrord/functions.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_FUNCTIONS_H
|
||||
#define _LVM_CLOG_FUNCTIONS_H
|
||||
|
||||
#include "dm-log-userspace.h"
|
||||
#include "cluster.h"
|
||||
|
||||
#define LOG_RESUMED 1
|
||||
#define LOG_SUSPENDED 2
|
||||
|
||||
int local_resume(struct dm_ulog_request *rq);
|
||||
int cluster_postsuspend(char *, uint64_t);
|
||||
|
||||
int do_request(struct clog_request *rq, int server);
|
||||
int push_state(const char *uuid, uint64_t luid,
|
||||
const char *which, char **buf, uint32_t debug_who);
|
||||
int pull_state(const char *uuid, uint64_t luid,
|
||||
const char *which, char *buf, int size);
|
||||
|
||||
int log_get_state(struct dm_ulog_request *rq);
|
||||
int log_status(void);
|
||||
void log_debug(void);
|
||||
|
||||
#endif /* _LVM_CLOG_FUNCTIONS_H */
|
||||
151
daemons/cmirrord/link_mon.c
Normal file
151
daemons/cmirrord/link_mon.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "link_mon.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct link_callback {
|
||||
int fd;
|
||||
const char *name;
|
||||
void *data;
|
||||
int (*callback)(void *data);
|
||||
|
||||
struct link_callback *next;
|
||||
};
|
||||
|
||||
static unsigned used_pfds = 0;
|
||||
static unsigned free_pfds = 0;
|
||||
static struct pollfd *pfds = NULL;
|
||||
static struct link_callback *callbacks = NULL;
|
||||
|
||||
int links_register(int fd, const char *name, int (*callback)(void *data), void *data)
|
||||
{
|
||||
unsigned i;
|
||||
struct link_callback *lc;
|
||||
|
||||
for (i = 0; i < used_pfds; i++) {
|
||||
if (fd == pfds[i].fd) {
|
||||
LOG_ERROR("links_register: Duplicate file descriptor");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
lc = malloc(sizeof(*lc));
|
||||
if (!lc)
|
||||
return -ENOMEM;
|
||||
|
||||
lc->fd = fd;
|
||||
lc->name = name;
|
||||
lc->data = data;
|
||||
lc->callback = callback;
|
||||
|
||||
if (!free_pfds) {
|
||||
struct pollfd *tmp;
|
||||
tmp = realloc(pfds, sizeof(struct pollfd) * ((used_pfds*2) + 1));
|
||||
if (!tmp) {
|
||||
free(lc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pfds = tmp;
|
||||
free_pfds = used_pfds + 1;
|
||||
}
|
||||
|
||||
free_pfds--;
|
||||
pfds[used_pfds].fd = fd;
|
||||
pfds[used_pfds].events = POLLIN;
|
||||
pfds[used_pfds].revents = 0;
|
||||
used_pfds++;
|
||||
|
||||
lc->next = callbacks;
|
||||
callbacks = lc;
|
||||
LOG_DBG("Adding %s/%d", lc->name, lc->fd);
|
||||
LOG_DBG(" used_pfds = %u, free_pfds = %u",
|
||||
used_pfds, free_pfds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int links_unregister(int fd)
|
||||
{
|
||||
unsigned i;
|
||||
struct link_callback *p, *c;
|
||||
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (fd == pfds[i].fd) {
|
||||
/* entire struct is copied (overwritten) */
|
||||
pfds[i] = pfds[used_pfds - 1];
|
||||
used_pfds--;
|
||||
free_pfds++;
|
||||
}
|
||||
|
||||
for (p = NULL, c = callbacks; c; p = c, c = c->next)
|
||||
if (fd == c->fd) {
|
||||
LOG_DBG("Freeing up %s/%d", c->name, c->fd);
|
||||
LOG_DBG(" used_pfds = %u, free_pfds = %u",
|
||||
used_pfds, free_pfds);
|
||||
if (p)
|
||||
p->next = c->next;
|
||||
else
|
||||
callbacks = c->next;
|
||||
free(c);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int links_monitor(void)
|
||||
{
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
for (i = 0; i < used_pfds; i++) {
|
||||
pfds[i].revents = 0;
|
||||
}
|
||||
|
||||
r = poll(pfds, used_pfds, -1);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = 0;
|
||||
/* FIXME: handle POLLHUP */
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (pfds[i].revents & POLLIN) {
|
||||
LOG_DBG("Data ready on %d", pfds[i].fd);
|
||||
|
||||
/* FIXME: Add this back return 1;*/
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int links_issue_callbacks(void)
|
||||
{
|
||||
unsigned i;
|
||||
struct link_callback *lc;
|
||||
|
||||
for (i = 0; i < used_pfds; i++)
|
||||
if (pfds[i].revents & POLLIN)
|
||||
for (lc = callbacks; lc; lc = lc->next)
|
||||
if (pfds[i].fd == lc->fd) {
|
||||
LOG_DBG("Issuing callback on %s/%d",
|
||||
lc->name, lc->fd);
|
||||
lc->callback(lc->data);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
20
daemons/cmirrord/link_mon.h
Normal file
20
daemons/cmirrord/link_mon.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_LINK_MON_H
|
||||
#define _LVM_CLOG_LINK_MON_H
|
||||
|
||||
int links_register(int fd, const char *name, int (*callback)(void *data), void *data);
|
||||
int links_unregister(int fd);
|
||||
int links_monitor(void);
|
||||
int links_issue_callbacks(void);
|
||||
|
||||
#endif /* _LVM_CLOG_LINK_MON_H */
|
||||
416
daemons/cmirrord/local.c
Normal file
416
daemons/cmirrord/local.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
#include "common.h"
|
||||
#include "functions.h"
|
||||
#include "link_mon.h"
|
||||
#include "local.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/connector.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef CN_IDX_DM
|
||||
/* Kernel 2.6.31 is required to run this code */
|
||||
#define CN_IDX_DM 0x7 /* Device Mapper */
|
||||
#define CN_VAL_DM_USERSPACE_LOG 0x1
|
||||
#endif
|
||||
|
||||
static int cn_fd; /* Connector (netlink) socket fd */
|
||||
static char recv_buf[2048];
|
||||
static char send_buf[2048];
|
||||
|
||||
|
||||
/* FIXME: merge this function with kernel_send_helper */
|
||||
static int kernel_ack(uint32_t seq, int error)
|
||||
{
|
||||
int r;
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)send_buf;
|
||||
struct cn_msg *msg = NLMSG_DATA(nlh);
|
||||
|
||||
if (error < 0) {
|
||||
LOG_ERROR("Programmer error: error codes must be positive");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
nlh->nlmsg_seq = 0;
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
msg->len = 0;
|
||||
msg->id.idx = CN_IDX_DM;
|
||||
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
|
||||
msg->seq = seq;
|
||||
msg->ack = error;
|
||||
|
||||
r = send(cn_fd, nlh, NLMSG_LENGTH(sizeof(struct cn_msg)), 0);
|
||||
/* FIXME: do better error processing */
|
||||
if (r <= 0)
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* kernel_recv
|
||||
* @rq: the newly allocated request from kernel
|
||||
*
|
||||
* Read requests from the kernel and allocate space for the new request.
|
||||
* If there is no request from the kernel, *rq is NULL.
|
||||
*
|
||||
* This function is not thread safe due to returned stack pointer. In fact,
|
||||
* the returned pointer must not be in-use when this function is called again.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on error
|
||||
*/
|
||||
static int kernel_recv(struct clog_request **rq)
|
||||
{
|
||||
int r = 0;
|
||||
ssize_t len;
|
||||
char *foo;
|
||||
struct cn_msg *msg;
|
||||
struct dm_ulog_request *u_rq;
|
||||
struct nlmsghdr *nlmsg_h;
|
||||
|
||||
*rq = NULL;
|
||||
memset(recv_buf, 0, sizeof(recv_buf));
|
||||
|
||||
len = recv(cn_fd, recv_buf, sizeof(recv_buf), 0);
|
||||
if (len < 0) {
|
||||
LOG_ERROR("Failed to recv message from kernel");
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nlmsg_h = (struct nlmsghdr *)recv_buf;
|
||||
switch (nlmsg_h->nlmsg_type) {
|
||||
case NLMSG_ERROR:
|
||||
LOG_ERROR("Unable to recv message from kernel: NLMSG_ERROR");
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
case NLMSG_DONE:
|
||||
msg = (struct cn_msg *)NLMSG_DATA((struct nlmsghdr *)recv_buf);
|
||||
len -= (ssize_t)sizeof(struct nlmsghdr);
|
||||
|
||||
if (len < (ssize_t)sizeof(struct cn_msg)) {
|
||||
LOG_ERROR("Incomplete request from kernel received");
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (msg->len > DM_ULOG_REQUEST_SIZE) {
|
||||
LOG_ERROR("Not enough space to receive kernel request (%d/%d)",
|
||||
msg->len, DM_ULOG_REQUEST_SIZE);
|
||||
r = -EBADE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!msg->len)
|
||||
LOG_ERROR("Zero length message received");
|
||||
|
||||
len -= (ssize_t)sizeof(struct cn_msg);
|
||||
|
||||
if (len < msg->len)
|
||||
LOG_ERROR("len = %zd, msg->len = %" PRIu16, len, msg->len);
|
||||
|
||||
msg->data[msg->len] = '\0'; /* Cleaner way to ensure this? */
|
||||
u_rq = (struct dm_ulog_request *)msg->data;
|
||||
|
||||
if (!u_rq->request_type) {
|
||||
LOG_DBG("Bad transmission, requesting resend [%u]",
|
||||
msg->seq);
|
||||
r = -EAGAIN;
|
||||
|
||||
if (kernel_ack(msg->seq, EAGAIN)) {
|
||||
LOG_ERROR("Failed to NACK kernel transmission [%u]",
|
||||
msg->seq);
|
||||
r = -EBADE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we've got sizeof(struct cn_msg) + sizeof(struct nlmsghdr)
|
||||
* worth of space that precede the request structure from the
|
||||
* kernel. Since that space isn't going to be used again, we
|
||||
* can take it for our purposes; rather than allocating a whole
|
||||
* new structure and doing a memcpy.
|
||||
*
|
||||
* We should really make sure 'clog_request' doesn't grow
|
||||
* beyond what is available to us, but we need only check it
|
||||
* once... perhaps at compile time?
|
||||
*/
|
||||
foo = (char *)u_rq;
|
||||
foo -= (sizeof(struct clog_request) - sizeof(struct dm_ulog_request));
|
||||
*rq = (struct clog_request *) foo;
|
||||
|
||||
/* Clear the wrapper container fields */
|
||||
memset(*rq, 0, (size_t)((char *)u_rq - (char *)(*rq)));
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown nlmsg_type");
|
||||
r = -EBADE;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (r)
|
||||
*rq = NULL;
|
||||
|
||||
return (r == -EAGAIN) ? 0 : r;
|
||||
}
|
||||
|
||||
static int kernel_send_helper(void *data, uint16_t out_size)
|
||||
{
|
||||
int r;
|
||||
struct nlmsghdr *nlh;
|
||||
struct cn_msg *msg;
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
nlh = (struct nlmsghdr *)send_buf;
|
||||
nlh->nlmsg_seq = 0; /* FIXME: Is this used? */
|
||||
nlh->nlmsg_pid = getpid();
|
||||
nlh->nlmsg_type = NLMSG_DONE;
|
||||
nlh->nlmsg_len = NLMSG_LENGTH(out_size + sizeof(struct cn_msg));
|
||||
nlh->nlmsg_flags = 0;
|
||||
|
||||
msg = NLMSG_DATA(nlh);
|
||||
memcpy(msg->data, data, out_size);
|
||||
msg->len = out_size;
|
||||
msg->id.idx = CN_IDX_DM;
|
||||
msg->id.val = CN_VAL_DM_USERSPACE_LOG;
|
||||
msg->seq = 0;
|
||||
|
||||
r = send(cn_fd, nlh, NLMSG_LENGTH(out_size + sizeof(struct cn_msg)), 0);
|
||||
/* FIXME: do better error processing */
|
||||
if (r <= 0)
|
||||
return -EBADE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* do_local_work
|
||||
*
|
||||
* Any processing errors are placed in the 'rq'
|
||||
* structure to be reported back to the kernel.
|
||||
* It may be pointless for this function to
|
||||
* return an int.
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
static int do_local_work(void *data __attribute((unused)))
|
||||
{
|
||||
int r;
|
||||
struct clog_request *rq;
|
||||
struct dm_ulog_request *u_rq = NULL;
|
||||
|
||||
r = kernel_recv(&rq);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!rq)
|
||||
return 0;
|
||||
|
||||
u_rq = &rq->u_rq;
|
||||
LOG_DBG("[%s] Request from kernel received: [%s/%u]",
|
||||
SHORT_UUID(u_rq->uuid), RQ_TYPE(u_rq->request_type),
|
||||
u_rq->seq);
|
||||
switch (u_rq->request_type) {
|
||||
case DM_ULOG_CTR:
|
||||
case DM_ULOG_DTR:
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
case DM_ULOG_STATUS_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;
|
||||
uint16_t size;
|
||||
|
||||
if (!u_rq)
|
||||
return -EINVAL;
|
||||
|
||||
size = (uint16_t)(sizeof(struct dm_ulog_request) + u_rq->data_size);
|
||||
|
||||
if (!u_rq->data_size && !u_rq->error) {
|
||||
/* An ACK is all that is needed */
|
||||
|
||||
/* FIXME: add ACK code */
|
||||
} else if (size > DM_ULOG_REQUEST_SIZE) {
|
||||
/*
|
||||
* If we gotten here, we've already overrun
|
||||
* our allotted space somewhere.
|
||||
*
|
||||
* We must do something, because the kernel
|
||||
* is waiting for a response.
|
||||
*/
|
||||
LOG_ERROR("Not enough space to respond to server");
|
||||
u_rq->error = -ENOSPC;
|
||||
size = sizeof(struct dm_ulog_request);
|
||||
}
|
||||
|
||||
r = kernel_send_helper(u_rq, size);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to send msg to kernel.");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_local
|
||||
*
|
||||
* Initialize kernel communication socket (netlink)
|
||||
*
|
||||
* Returns: 0 on success, values from common.h on failure
|
||||
*/
|
||||
int init_local(void)
|
||||
{
|
||||
int r = 0;
|
||||
unsigned opt;
|
||||
struct sockaddr_nl addr;
|
||||
|
||||
cn_fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||
if (cn_fd < 0)
|
||||
return EXIT_KERNEL_SOCKET;
|
||||
|
||||
/* memset to fix valgrind complaint */
|
||||
memset(&addr, 0, sizeof(struct sockaddr_nl));
|
||||
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = CN_IDX_DM;
|
||||
addr.nl_pid = 0;
|
||||
|
||||
r = bind(cn_fd, (struct sockaddr *) &addr, sizeof(addr));
|
||||
if (r < 0) {
|
||||
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);
|
||||
}
|
||||
20
daemons/cmirrord/local.h
Normal file
20
daemons/cmirrord/local.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef _LVM_CLOG_LOCAL_H
|
||||
#define _LVM_CLOG_LOCAL_H
|
||||
|
||||
int init_local(void);
|
||||
void cleanup_local(void);
|
||||
|
||||
int kernel_send(struct dm_ulog_request *rq);
|
||||
|
||||
#endif /* _LVM_CLOG_LOCAL_H */
|
||||
57
daemons/cmirrord/logging.c
Normal file
57
daemons/cmirrord/logging.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "logging.h"
|
||||
|
||||
const char *__rq_types_off_by_one[] = {
|
||||
"DM_ULOG_CTR",
|
||||
"DM_ULOG_DTR",
|
||||
"DM_ULOG_PRESUSPEND",
|
||||
"DM_ULOG_POSTSUSPEND",
|
||||
"DM_ULOG_RESUME",
|
||||
"DM_ULOG_GET_REGION_SIZE",
|
||||
"DM_ULOG_IS_CLEAN",
|
||||
"DM_ULOG_IN_SYNC",
|
||||
"DM_ULOG_FLUSH",
|
||||
"DM_ULOG_MARK_REGION",
|
||||
"DM_ULOG_CLEAR_REGION",
|
||||
"DM_ULOG_GET_RESYNC_WORK",
|
||||
"DM_ULOG_SET_REGION_SYNC",
|
||||
"DM_ULOG_GET_SYNC_COUNT",
|
||||
"DM_ULOG_STATUS_INFO",
|
||||
"DM_ULOG_STATUS_TABLE",
|
||||
"DM_ULOG_IS_REMOTE_RECOVERING",
|
||||
NULL
|
||||
};
|
||||
|
||||
int log_tabbing = 0;
|
||||
int log_is_open = 0;
|
||||
|
||||
/*
|
||||
* Variables for various conditional logging
|
||||
*/
|
||||
#ifdef MEMB
|
||||
int log_membership_change = 1;
|
||||
#else
|
||||
int log_membership_change = 0;
|
||||
#endif
|
||||
|
||||
#ifdef CKPT
|
||||
int log_checkpoint = 1;
|
||||
#else
|
||||
int log_checkpoint = 0;
|
||||
#endif
|
||||
|
||||
#ifdef RESEND
|
||||
int log_resend_requests = 1;
|
||||
#else
|
||||
int log_resend_requests = 0;
|
||||
#endif
|
||||
77
daemons/cmirrord/logging.h
Normal file
77
daemons/cmirrord/logging.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_CLOG_LOGGING_H
|
||||
#define _LVM_CLOG_LOGGING_H
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include <configure.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/* SHORT_UUID - print last 8 chars of a string */
|
||||
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
|
||||
|
||||
extern const char *__rq_types_off_by_one[];
|
||||
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
|
||||
|
||||
extern int log_tabbing;
|
||||
extern int log_is_open;
|
||||
extern int log_membership_change;
|
||||
extern int log_checkpoint;
|
||||
extern int log_resend_requests;
|
||||
|
||||
#define LOG_OPEN(ident, option, facility) do { \
|
||||
openlog(ident, option, facility); \
|
||||
log_is_open = 1; \
|
||||
} while (0)
|
||||
|
||||
#define LOG_CLOSE(void) do { \
|
||||
log_is_open = 0; \
|
||||
closelog(); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_OUTPUT(level, f, arg...) do { \
|
||||
int __i; \
|
||||
char __buffer[16]; \
|
||||
FILE *fp = (level > LOG_NOTICE) ? stderr : stdout; \
|
||||
if (log_is_open) { \
|
||||
for (__i = 0; (__i < log_tabbing) && (__i < 15); __i++) \
|
||||
__buffer[__i] = '\t'; \
|
||||
__buffer[__i] = '\0'; \
|
||||
syslog(level, "%s" f "\n", __buffer, ## arg); \
|
||||
} else { \
|
||||
for (__i = 0; __i < log_tabbing; __i++) \
|
||||
fprintf(fp, "\t"); \
|
||||
fprintf(fp, f "\n", ## arg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG_DBG(f, arg...) LOG_OUTPUT(LOG_DEBUG, f, ## arg)
|
||||
#else /* DEBUG */
|
||||
#define LOG_DBG(f, arg...)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define LOG_COND(__X, f, arg...) do {\
|
||||
if (__X) { \
|
||||
LOG_OUTPUT(LOG_NOTICE, f, ## arg); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_PRINT(f, arg...) LOG_OUTPUT(LOG_NOTICE, f, ## arg)
|
||||
#define LOG_ERROR(f, arg...) LOG_OUTPUT(LOG_ERR, f, ## arg)
|
||||
|
||||
#endif /* _LVM_CLOG_LOGGING_H */
|
||||
@@ -13,67 +13,98 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SOURCES = libdevmapper-event.c
|
||||
TARGETS = dmeventd
|
||||
|
||||
LIB_STATIC = libdevmapper-event.a
|
||||
.PHONY: install_lib_dynamic install_lib_static install_include \
|
||||
install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
|
||||
install_lib install_dmeventd
|
||||
|
||||
INSTALL_DMEVENTD_TARGETS = install_dmeventd_dynamic
|
||||
INSTALL_LIB_TARGETS = install_lib_dynamic
|
||||
|
||||
ifeq ("@STATIC_LINK@", "yes")
|
||||
LIB_STATIC = libdevmapper-event.a
|
||||
TARGETS += dmeventd.static
|
||||
INSTALL_DMEVENTD_TARGETS += install_dmeventd_static
|
||||
INSTALL_LIB_TARGETS += install_lib_static
|
||||
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
|
||||
CLEAN_TARGETS = dmeventd.o dmeventd.static
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
LDFLAGS += -ldl -ldevmapper -lpthread
|
||||
CLDFLAGS += -ldl -ldevmapper -lpthread
|
||||
|
||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||
$(CC) -o $@ dmeventd.o $(CFLAGS) $(LDFLAGS) \
|
||||
-L. -ldevmapper-event $(LIBS) -rdynamic
|
||||
|
||||
.PHONY: install_dynamic install_static install_include \
|
||||
install_pkgconfig install_dmeventd
|
||||
|
||||
INSTALL_TYPE = install_dynamic
|
||||
|
||||
ifeq ("@STATIC_LINK@", "yes")
|
||||
INSTALL_TYPE += install_static
|
||||
ifneq ($(MAKECMDGOALS),device-mapper)
|
||||
SUBDIRS+=plugins
|
||||
endif
|
||||
|
||||
include ../../make.tmpl
|
||||
|
||||
all: device-mapper
|
||||
device-mapper: $(TARGETS)
|
||||
|
||||
LIBS += -ldl
|
||||
LVMLIBS += -ldevmapper-event -lpthread -ldevmapper
|
||||
|
||||
$(VERSIONED_SHLIB): $(LIB_SHARED)
|
||||
$(RM) -f $@
|
||||
$(LN_S) $(LIB_SHARED) $@
|
||||
|
||||
dmeventd: $(LIB_SHARED) $(VERSIONED_SHLIB) dmeventd.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -L. -o $@ dmeventd.o \
|
||||
$(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
|
||||
dmeventd.o $(LVMLIBS) $(LIBS) -rdynamic
|
||||
|
||||
ifeq ("@PKGCONFIG@", "yes")
|
||||
INSTALL_TYPE += install_pkgconfig
|
||||
INSTALL_LIB_TARGETS += install_pkgconfig
|
||||
endif
|
||||
|
||||
install: $(INSTALL_TYPE) install_include install_dmeventd
|
||||
|
||||
install_include:
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.h \
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 $(srcdir)/libdevmapper-event.h \
|
||||
$(includedir)/libdevmapper-event.h
|
||||
|
||||
install_dynamic: libdevmapper-event.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION)
|
||||
$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \
|
||||
$(libdir)/libdevmapper-event.$(LIB_SUFFIX)
|
||||
|
||||
install_dmeventd: dmeventd
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$<
|
||||
|
||||
install_pkgconfig:
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 libdevmapper-event.pc \
|
||||
$(usrlibdir)/pkgconfig/devmapper-event.pc
|
||||
|
||||
install_static: libdevmapper-event.a
|
||||
install_lib_dynamic: libdevmapper-event.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION)
|
||||
$(LN_S) -f libdevmapper-event.$(LIB_SUFFIX).$(LIB_VERSION) \
|
||||
$(libdir)/libdevmapper-event.$(LIB_SUFFIX)
|
||||
|
||||
install_lib_static: libdevmapper-event.a
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
|
||||
$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
|
||||
|
||||
install_lib: $(INSTALL_LIB_TARGETS)
|
||||
|
||||
install_dmeventd_dynamic: dmeventd
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$<
|
||||
|
||||
install_dmeventd_static: dmeventd.static
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< $(sbindir)/$<
|
||||
|
||||
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)
|
||||
|
||||
install: install_include install_lib install_dmeventd
|
||||
|
||||
install_device-mapper: install_include install_lib install_dmeventd
|
||||
|
||||
.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"
|
||||
@@ -398,6 +398,8 @@ static int _start_daemon(struct dm_event_fifos *fifos)
|
||||
int pid, ret = 0;
|
||||
int status;
|
||||
struct stat statbuf;
|
||||
char dmeventdpath[] = DMEVENTD_PATH; /* const type for execvp */
|
||||
char * const args[] = { dmeventdpath, NULL };
|
||||
|
||||
if (stat(fifos->client_path, &statbuf))
|
||||
goto start_server;
|
||||
@@ -425,14 +427,20 @@ 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)
|
||||
log_error("Unable to fork.");
|
||||
|
||||
else if (!pid) {
|
||||
execvp(DMEVENTD_PATH, NULL);
|
||||
exit(EXIT_FAILURE);
|
||||
execvp(args[0], args);
|
||||
_exit(EXIT_FAILURE);
|
||||
} else {
|
||||
if (waitpid(pid, &status, 0) < 0)
|
||||
log_error("Unable to start dmeventd: %s",
|
||||
|
||||
@@ -14,9 +14,13 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SUBDIRS += mirror snapshot
|
||||
SUBDIRS += lvm2 mirror snapshot
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
mirror: lvm2
|
||||
snapshot: lvm2
|
||||
|
||||
include ../../../make.tmpl
|
||||
|
||||
|
||||
6
daemons/dmeventd/plugins/lvm2/.exported_symbols
Normal file
6
daemons/dmeventd/plugins/lvm2/.exported_symbols
Normal file
@@ -0,0 +1,6 @@
|
||||
dmeventd_lvm2_init
|
||||
dmeventd_lvm2_exit
|
||||
dmeventd_lvm2_lock
|
||||
dmeventd_lvm2_unlock
|
||||
dmeventd_lvm2_pool
|
||||
dmeventd_lvm2_run
|
||||
@@ -1,6 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2008 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@@ -14,22 +13,27 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper $(LVM2CMD_LIB)
|
||||
CLDFLAGS += -L${top_builddir}/tools
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
SOURCES = dmeventd_lvm.c
|
||||
|
||||
ifeq ("@LIB_SUFFIX@","dylib")
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
|
||||
LIB_SHARED = libdevmapper-event-lvm2.dylib
|
||||
else
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||
LIB_SHARED = libdevmapper-event-lvm2.so
|
||||
endif
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
LIBS += -ldevmapper @LIB_PTHREAD@ @LVM2CMD_LIB@
|
||||
|
||||
install_lvm2: libdevmapper-event-lvm2.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
|
||||
install: install_lvm2
|
||||
127
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
Normal file
127
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/*
|
||||
* register_device() is called first and performs initialisation.
|
||||
* Only one device may be registered or unregistered at a time.
|
||||
*/
|
||||
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/*
|
||||
* Number of active registrations.
|
||||
*/
|
||||
static int _register_count = 0;
|
||||
static struct dm_pool *_mem_pool = NULL;
|
||||
static void *_lvm_handle = NULL;
|
||||
|
||||
/*
|
||||
* Currently only one event can be processed at a time.
|
||||
*/
|
||||
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* FIXME Remove this: Pass messages back to dmeventd core for processing. */
|
||||
static void _temporary_log_fn(int level,
|
||||
const char *file __attribute((unused)),
|
||||
int line __attribute((unused)),
|
||||
int dm_errno __attribute((unused)),
|
||||
const char *format)
|
||||
{
|
||||
level &= ~_LOG_STDERR;
|
||||
|
||||
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||
syslog(LOG_CRIT, "%s", format);
|
||||
else
|
||||
syslog(LOG_DEBUG, "%s", format);
|
||||
}
|
||||
|
||||
void dmeventd_lvm2_lock(void)
|
||||
{
|
||||
if (pthread_mutex_trylock(&_event_mutex)) {
|
||||
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
|
||||
pthread_mutex_lock(&_event_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void dmeventd_lvm2_unlock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
}
|
||||
|
||||
int dmeventd_lvm2_init(void)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
/*
|
||||
* Need some space for allocations. 1024 should be more
|
||||
* than enough for what we need (device mapper name splitting)
|
||||
*/
|
||||
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
|
||||
goto out;
|
||||
|
||||
if (!_lvm_handle) {
|
||||
lvm2_log_fn(_temporary_log_fn);
|
||||
if (!(_lvm_handle = lvm2_init())) {
|
||||
dm_pool_destroy(_mem_pool);
|
||||
_mem_pool = NULL;
|
||||
goto out;
|
||||
}
|
||||
/* FIXME Temporary: move to dmeventd core */
|
||||
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||
}
|
||||
|
||||
_register_count++;
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
pthread_mutex_unlock(&_register_mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
void dmeventd_lvm2_exit(void)
|
||||
{
|
||||
pthread_mutex_lock(&_register_mutex);
|
||||
|
||||
if (!--_register_count) {
|
||||
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);
|
||||
}
|
||||
|
||||
struct dm_pool *dmeventd_lvm2_pool(void)
|
||||
{
|
||||
return _mem_pool;
|
||||
}
|
||||
|
||||
int dmeventd_lvm2_run(const char *cmdline)
|
||||
{
|
||||
return lvm2_run(_lvm_handle, cmdline);
|
||||
}
|
||||
|
||||
39
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h
Normal file
39
daemons/dmeventd/plugins/lvm2/dmeventd_lvm.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Wrappers around liblvm2cmd functions for dmeventd plug-ins.
|
||||
*
|
||||
* liblvm2cmd is not thread-safe so the locking in this library helps dmeventd
|
||||
* threads to co-operate in sharing a single instance.
|
||||
*
|
||||
* FIXME Either support this properly as a generic liblvm2cmd wrapper or make
|
||||
* liblvm2cmd thread-safe so this can go away.
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
|
||||
#ifndef _DMEVENTD_LVMWRAP_H
|
||||
#define _DMEVENTD_LVMWRAP_H
|
||||
|
||||
int dmeventd_lvm2_init(void);
|
||||
void dmeventd_lvm2_exit(void);
|
||||
int dmeventd_lvm2_run(const char *cmdline);
|
||||
|
||||
void dmeventd_lvm2_lock(void);
|
||||
void dmeventd_lvm2_unlock(void);
|
||||
|
||||
struct dm_pool *dmeventd_lvm2_pool(void);
|
||||
|
||||
#endif /* _DMEVENTD_LVMWRAP_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2008 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2005, 2008-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of LVM2.
|
||||
#
|
||||
@@ -14,10 +14,11 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper $(LVM2CMD_LIB)
|
||||
INCLUDES += -I${top_srcdir}/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||
CLDFLAGS += -L${top_builddir}/tools -L${top_builddir}/daemons/dmeventd/plugins/lvm2
|
||||
|
||||
SOURCES = dmeventd_mirror.c
|
||||
|
||||
@@ -27,9 +28,15 @@ else
|
||||
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper @LIB_PTHREAD@ @LVM2CMD_LIB@ -ldevmapper-event-lvm2
|
||||
|
||||
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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2005-2010 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -12,43 +12,53 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "lib.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.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? */
|
||||
/* FIXME Replace most syslogs with log_error() style messages and add complete context. */
|
||||
/* FIXME Reformat to 80 char lines. */
|
||||
|
||||
#define ME_IGNORE 0
|
||||
#define ME_INSYNC 1
|
||||
#define ME_FAILURE 2
|
||||
|
||||
/*
|
||||
* 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;
|
||||
static int _process_status_code(const char status_code, const char *dev_name,
|
||||
const char *dev_type, int r)
|
||||
{
|
||||
/*
|
||||
* A => Alive - No failures
|
||||
* D => Dead - A write failure occurred leaving mirror out-of-sync
|
||||
* F => Flush failed.
|
||||
* S => Sync - A sychronization failure occurred, mirror out-of-sync
|
||||
* R => Read - A read failure occurred, mirror data unaffected
|
||||
* U => Unclassified failure (bug)
|
||||
*/
|
||||
if (status_code == 'F') {
|
||||
syslog(LOG_ERR, "%s device %s flush failed.\n",
|
||||
dev_type, dev_name);
|
||||
r = ME_FAILURE;
|
||||
} else if (status_code == 'S')
|
||||
syslog(LOG_ERR, "%s device %s sync failed.\n",
|
||||
dev_type, dev_name);
|
||||
else if (status_code == 'R')
|
||||
syslog(LOG_ERR, "%s device %s read failed.\n",
|
||||
dev_type, dev_name);
|
||||
else if (status_code != 'A') {
|
||||
syslog(LOG_ERR, "%s device %s has failed (%c).\n",
|
||||
dev_type, dev_name, status_code);
|
||||
r = ME_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _get_mirror_event(char *params)
|
||||
{
|
||||
@@ -89,17 +99,14 @@ static int _get_mirror_event(char *params)
|
||||
|
||||
/* 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;
|
||||
}
|
||||
r = _process_status_code(dev_status_str[i], args[i],
|
||||
i ? "Secondary mirror" : "Primary mirror", r);
|
||||
|
||||
/* Check for bad disk log device */
|
||||
if (log_argc > 1 && log_status_str[0] == 'D') {
|
||||
syslog(LOG_ERR, "Log device, %s, has failed.\n",
|
||||
args[2 + num_devs + log_argc]);
|
||||
r = ME_FAILURE;
|
||||
}
|
||||
if (log_argc > 1)
|
||||
r = _process_status_code(log_status_str[0],
|
||||
args[2 + num_devs + log_argc],
|
||||
"Log", r);
|
||||
|
||||
if (r == ME_FAILURE)
|
||||
goto out;
|
||||
@@ -125,16 +132,6 @@ out_parse:
|
||||
return ME_IGNORE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int _remove_failed_devices(const char *device)
|
||||
{
|
||||
int r;
|
||||
@@ -145,24 +142,24 @@ static int _remove_failed_devices(const char *device)
|
||||
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)) {
|
||||
if (!dm_split_lvm_name(dmeventd_lvm2_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)) {
|
||||
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 */
|
||||
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||
}
|
||||
|
||||
r = lvm2_run(_lvm_handle, cmd_str);
|
||||
r = dmeventd_lvm2_run(cmd_str);
|
||||
|
||||
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||
return (r == 1) ? 0 : -1;
|
||||
syslog(LOG_INFO, "Repair of mirrored LV %s/%s %s.", vg, lv, (r == ECMD_PROCESSED) ? "finished successfully" : "failed");
|
||||
|
||||
return (r == ECMD_PROCESSED) ? 0 : -1;
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
@@ -175,10 +172,8 @@ void process_event(struct dm_task *dmt,
|
||||
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);
|
||||
}
|
||||
dmeventd_lvm2_lock();
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
@@ -221,7 +216,7 @@ void process_event(struct dm_task *dmt,
|
||||
}
|
||||
} while (next);
|
||||
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
dmeventd_lvm2_unlock();
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
@@ -230,37 +225,8 @@ int register_device(const char *device,
|
||||
int minor __attribute((unused)),
|
||||
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);
|
||||
|
||||
int r = dmeventd_lvm2_init();
|
||||
syslog(LOG_INFO, "Monitoring mirror device %s for events", device);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -270,20 +236,8 @@ int unregister_device(const char *device,
|
||||
int minor __attribute((unused)),
|
||||
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);
|
||||
|
||||
dmeventd_lvm2_exit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
@@ -14,10 +14,11 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper $(LVM2CMD_LIB)
|
||||
INCLUDES += -I${top_srcdir}/tools -I$(top_srcdir)/daemons/dmeventd/plugins/lvm2
|
||||
CLDFLAGS += -L${top_builddir}/tools -L${top_builddir}/daemons/dmeventd/plugins/lvm2
|
||||
|
||||
SOURCES = dmeventd_snapshot.c
|
||||
|
||||
@@ -27,9 +28,15 @@ else
|
||||
LIB_SHARED = libdevmapper-event-lvm2snapshot.so
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LIBS += -ldevmapper @LIB_PTHREAD@ @LVM2CMD_LIB@ -ldevmapper-event-lvm2
|
||||
|
||||
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
|
||||
|
||||
@@ -12,19 +12,16 @@
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "libdevmapper.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "lib.h"
|
||||
|
||||
#include "lvm2cmd.h"
|
||||
#include "errors.h"
|
||||
#include "libdevmapper-event.h"
|
||||
#include "dmeventd_lvm.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? */
|
||||
|
||||
@@ -33,38 +30,12 @@
|
||||
/* 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)
|
||||
@@ -99,24 +70,6 @@ static void _parse_snapshot_params(char *params, struct snap_status *stat)
|
||||
stat->max = atoi(p);
|
||||
}
|
||||
|
||||
/* send unregister command to itself */
|
||||
static void _unregister_self(struct dm_task *dmt)
|
||||
{
|
||||
const char *name = dm_task_get_name(dmt);
|
||||
struct dm_event_handler *dmevh;
|
||||
|
||||
if (!(dmevh = dm_event_handler_create()))
|
||||
return;
|
||||
|
||||
if (dm_event_handler_set_dev_name(dmevh, name))
|
||||
goto fail;
|
||||
|
||||
dm_event_handler_set_event_mask(dmevh, DM_EVENT_ALL_ERRORS|DM_EVENT_TIMEOUT);
|
||||
dm_event_unregister_handler(dmevh);
|
||||
fail:
|
||||
dm_event_handler_destroy(dmevh);
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute((unused)),
|
||||
void **private)
|
||||
@@ -133,10 +86,7 @@ void process_event(struct dm_task *dmt,
|
||||
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);
|
||||
}
|
||||
dmeventd_lvm2_lock();
|
||||
|
||||
dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms);
|
||||
if (!target_type)
|
||||
@@ -149,7 +99,6 @@ void process_event(struct dm_task *dmt,
|
||||
*/
|
||||
if (stat.invalid || !stat.max) {
|
||||
syslog(LOG_ERR, "Snapshot %s changed state to: %s\n", device, params);
|
||||
_unregister_self(dmt);
|
||||
*percent_warning = 0;
|
||||
goto out;
|
||||
}
|
||||
@@ -161,7 +110,7 @@ void process_event(struct dm_task *dmt,
|
||||
*percent_warning = (percent / WARNING_STEP) * WARNING_STEP + WARNING_STEP;
|
||||
}
|
||||
out:
|
||||
pthread_mutex_unlock(&_event_mutex);
|
||||
dmeventd_lvm2_unlock();
|
||||
}
|
||||
|
||||
int register_device(const char *device,
|
||||
@@ -170,40 +119,12 @@ int register_device(const char *device,
|
||||
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;
|
||||
int r = dmeventd_lvm2_init();
|
||||
|
||||
*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;
|
||||
}
|
||||
|
||||
@@ -213,20 +134,8 @@ int unregister_device(const char *device,
|
||||
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);
|
||||
|
||||
dmeventd_lvm2_exit();
|
||||
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,3 +0,0 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
@@ -1,289 +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 __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);
|
||||
}
|
||||
|
||||
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 __attribute((unused)),
|
||||
void **unused __attribute((unused)))
|
||||
{
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
|
||||
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 __attribute((unused)),
|
||||
int major __attribute((unused)),
|
||||
int minor __attribute((unused)),
|
||||
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 __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 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;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
process_event
|
||||
register_device
|
||||
unregister_device
|
||||
@@ -1,35 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
# Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This file is part of the LVM2.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
# of the GNU General Public License v.2.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
INCLUDES += -I${top_srcdir}/tools
|
||||
CLDFLAGS += -L${top_srcdir}/tools -ldevmapper $(LVM2CMD_LIB)
|
||||
|
||||
SOURCES = dmeventd_snapshot.c
|
||||
|
||||
ifeq ("@LIB_SUFFIX@","dylib")
|
||||
LIB_SHARED = libdevmapper-event-lvm2snapshot.dylib
|
||||
else
|
||||
LIB_SHARED = libdevmapper-event-lvm2snapshot.so
|
||||
endif
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
install: libdevmapper-event-lvm2snapshot.$(LIB_SUFFIX)
|
||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/$<.$(LIB_VERSION)
|
||||
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* send unregister command to itself */
|
||||
static void _unregister_self(struct dm_task *dmt)
|
||||
{
|
||||
const char *name = dm_task_get_name(dmt);
|
||||
struct dm_event_handler *dmevh;
|
||||
|
||||
if (!(dmevh = dm_event_handler_create()))
|
||||
return;
|
||||
|
||||
if (dm_event_handler_set_dev_name(dmevh, name))
|
||||
goto fail;
|
||||
|
||||
dm_event_handler_set_event_mask(dmevh, DM_EVENT_ALL_ERRORS|DM_EVENT_TIMEOUT);
|
||||
dm_event_unregister_handler(dmevh);
|
||||
fail:
|
||||
dm_event_handler_destroy(dmevh);
|
||||
}
|
||||
|
||||
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);
|
||||
_unregister_self(dmt);
|
||||
*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;
|
||||
}
|
||||
@@ -13,17 +13,19 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CONFSRC=example.conf
|
||||
CONFDEST=lvm.conf
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
include ../make.tmpl
|
||||
|
||||
install:
|
||||
install_lvm2: $(CONFSRC)
|
||||
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||
echo "Installing $(CONFSRC) as $(confdir)/$(CONFDEST)"; \
|
||||
@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $(CONFSRC) \
|
||||
@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $< \
|
||||
$(confdir)/$(CONFDEST); \
|
||||
fi
|
||||
|
||||
install: install_lvm2
|
||||
|
||||
134
doc/example.conf
134
doc/example.conf
@@ -86,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
|
||||
@@ -124,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
|
||||
@@ -170,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
|
||||
|
||||
@@ -188,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
|
||||
@@ -204,6 +236,13 @@ global {
|
||||
# Default value for --units argument
|
||||
units = "h"
|
||||
|
||||
# Since version 2.02.54, the tools distinguish between powers of
|
||||
# 1024 bytes (e.g. KiB, MiB, GiB) and powers of 1000 bytes (e.g.
|
||||
# KB, MB, GB).
|
||||
# If you have scripts that depend on the old behaviour, set this to 0
|
||||
# temporarily until you update them.
|
||||
si_unit_consistency = 1
|
||||
|
||||
# Whether or not to communicate with the kernel device-mapper.
|
||||
# Set to 0 if you want to use the tools to manipulate LVM metadata
|
||||
# without activating any logical volumes.
|
||||
@@ -223,8 +262,8 @@ global {
|
||||
|
||||
# The default metadata format that commands should use - "lvm1" or "lvm2".
|
||||
# The command line override is -M1 or -M2.
|
||||
# Defaults to "lvm1" if compiled in, else "lvm2".
|
||||
# format = "lvm1"
|
||||
# Defaults to "lvm2".
|
||||
# format = "lvm2"
|
||||
|
||||
# Location of proc filesystem
|
||||
proc = "/proc"
|
||||
@@ -234,8 +273,13 @@ global {
|
||||
# if LVM2 commands get run concurrently).
|
||||
# Type 2 uses the external shared library locking_library.
|
||||
# Type 3 uses built-in clustered locking.
|
||||
# Type 4 uses read-only locking which forbids any operations that might
|
||||
# change metadata.
|
||||
locking_type = 1
|
||||
|
||||
# Set to 0 to fail when a lock request cannot be satisfied immediately.
|
||||
wait_for_locks = 1
|
||||
|
||||
# If using external locking (type 2) and initialisation fails,
|
||||
# with this set to 1 an attempt will be made to use the built-in
|
||||
# clustered locking.
|
||||
@@ -253,6 +297,15 @@ global {
|
||||
# in progress. A directory like /tmp that may get wiped on reboot is OK.
|
||||
locking_dir = "/var/lock/lvm"
|
||||
|
||||
# Whenever there are competing read-only and read-write access requests for
|
||||
# a volume group's metadata, instead of always granting the read-only
|
||||
# requests immediately, delay them to allow the read-write requests to be
|
||||
# serviced. Without this setting, write access may be stalled by a high
|
||||
# volume of read-only requests.
|
||||
# NB. This option only affects locking_type = 1 viz. local file-based
|
||||
# locking.
|
||||
prioritise_write_locks = 1
|
||||
|
||||
# Other entries can go here to allow you to load shared libraries
|
||||
# e.g. if support for LVM1 metadata was compiled as a shared library use
|
||||
# format_libraries = "liblvm2format1.so"
|
||||
@@ -263,14 +316,37 @@ global {
|
||||
|
||||
# The external locking library to load if locking_type is set to 2.
|
||||
# locking_library = "liblvm2clusterlock.so"
|
||||
|
||||
# Treat any internal errors as fatal errors, aborting the process that
|
||||
# encountered the internal error. Please only enable for debugging.
|
||||
abort_on_internal_errors = 0
|
||||
}
|
||||
|
||||
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 synchronisation (if compiled into the binaries).
|
||||
# Processes will not wait for notification from udev.
|
||||
# They will continue irrespective of any possible udev processing
|
||||
# in the background. You should only use this if udev is not running
|
||||
# or has rules that ignore the devices LVM2 creates.
|
||||
# The command line argument --nodevsync takes precedence over this setting.
|
||||
# If set to 1 when udev is not running, and there are LVM2 processes
|
||||
# waiting for udev, run 'dmsetup udevcomplete_all' manually to wake them up.
|
||||
udev_sync = 1
|
||||
|
||||
# Set to 0 to disable the udev rules installed by LVM2 (if built with
|
||||
# --enable-udev_rules). LVM2 will then manage the /dev nodes and symlinks
|
||||
# for active logical volumes directly itself.
|
||||
# N.B. Manual intervention may be required if this setting is changed
|
||||
# while any logical volumes are active.
|
||||
udev_rules = 1
|
||||
|
||||
# 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
|
||||
@@ -304,8 +380,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
|
||||
@@ -325,23 +403,16 @@ 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"
|
||||
mirror_image_fault_policy = "remove"
|
||||
}
|
||||
|
||||
|
||||
@@ -382,7 +453,7 @@ activation {
|
||||
|
||||
# Event daemon
|
||||
#
|
||||
# dmeventd {
|
||||
dmeventd {
|
||||
# mirror_library is the library used when monitoring a mirror device.
|
||||
#
|
||||
# "libdevmapper-event-lvm2mirror.so" attempts to recover from
|
||||
@@ -390,7 +461,7 @@ activation {
|
||||
# reconfigures a mirror as necessary. If no mirror library is
|
||||
# provided, mirrors are not monitored through dmeventd.
|
||||
|
||||
# mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||
mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||
|
||||
# snapshot_library is the library used when monitoring a snapshot device.
|
||||
#
|
||||
@@ -399,6 +470,5 @@ activation {
|
||||
# snapshot exceedes 80%. The warning is repeated when 85%, 90% and
|
||||
# 95% of the snapshot are filled.
|
||||
|
||||
# snapshot_library = "libdevmapper-event-lvm2snapshot.so"
|
||||
#}
|
||||
|
||||
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,52 +0,0 @@
|
||||
../daemons/clvmd/clvm.h
|
||||
../lib/activate/activate.h
|
||||
../lib/activate/targets.h
|
||||
../lib/cache/lvmcache.h
|
||||
../lib/commands/errors.h
|
||||
../lib/commands/toolcontext.h
|
||||
../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
|
||||
../lib/device/device.h
|
||||
../lib/display/display.h
|
||||
../lib/filters/filter-composite.h
|
||||
../lib/filters/filter-md.h
|
||||
../lib/filters/filter-persistent.h
|
||||
../lib/filters/filter-regex.h
|
||||
../lib/filters/filter-sysfs.h
|
||||
../lib/filters/filter.h
|
||||
../lib/format1/format1.h
|
||||
../lib/format_pool/format_pool.h
|
||||
../lib/format_text/archiver.h
|
||||
../lib/format_text/format-text.h
|
||||
../lib/format_text/text_export.h
|
||||
../lib/format_text/text_import.h
|
||||
../lib/label/label.h
|
||||
../lib/locking/locking.h
|
||||
../lib/log/log.h
|
||||
../lib/metadata/lv_alloc.h
|
||||
../lib/metadata/metadata.h
|
||||
../lib/metadata/metadata-exported.h
|
||||
../lib/metadata/pv_alloc.h
|
||||
../lib/metadata/segtype.h
|
||||
../lib/mm/memlock.h
|
||||
../lib/mm/xlate.h
|
||||
../lib/misc/configure.h
|
||||
../lib/misc/crc.h
|
||||
../lib/misc/intl.h
|
||||
../lib/misc/util.h
|
||||
../lib/misc/last-path-component.h
|
||||
../lib/misc/lib.h
|
||||
../lib/misc/lvm-exec.h
|
||||
../lib/misc/lvm-file.h
|
||||
../lib/misc/lvm-string.h
|
||||
../lib/misc/lvm-wrappers.h
|
||||
../lib/misc/sharedlib.h
|
||||
../lib/report/report.h
|
||||
../lib/uuid/uuid.h
|
||||
../po/pogen.h
|
||||
../tools/version.h
|
||||
62
include/.symlinks.in
Normal file
62
include/.symlinks.in
Normal file
@@ -0,0 +1,62 @@
|
||||
@top_srcdir@/daemons/clvmd/clvm.h
|
||||
@top_srcdir@/daemons/dmeventd/libdevmapper-event.h
|
||||
@top_srcdir@/liblvm/lvm2app.h
|
||||
@top_srcdir@/lib/activate/activate.h
|
||||
@top_srcdir@/lib/activate/targets.h
|
||||
@top_srcdir@/lib/cache/lvmcache.h
|
||||
@top_srcdir@/lib/commands/errors.h
|
||||
@top_srcdir@/lib/commands/toolcontext.h
|
||||
@top_srcdir@/lib/config/config.h
|
||||
@top_srcdir@/lib/config/defaults.h
|
||||
@top_srcdir@/lib/datastruct/btree.h
|
||||
@top_srcdir@/lib/datastruct/lvm-types.h
|
||||
@top_srcdir@/lib/datastruct/str_list.h
|
||||
@top_srcdir@/lib/device/dev-cache.h
|
||||
@top_srcdir@/lib/device/device.h
|
||||
@top_srcdir@/lib/display/display.h
|
||||
@top_srcdir@/lib/filters/filter-composite.h
|
||||
@top_srcdir@/lib/filters/filter-md.h
|
||||
@top_srcdir@/lib/filters/filter-persistent.h
|
||||
@top_srcdir@/lib/filters/filter-regex.h
|
||||
@top_srcdir@/lib/filters/filter-sysfs.h
|
||||
@top_srcdir@/lib/filters/filter.h
|
||||
@top_srcdir@/lib/format1/format1.h
|
||||
@top_srcdir@/lib/format_pool/format_pool.h
|
||||
@top_srcdir@/lib/format_text/archiver.h
|
||||
@top_srcdir@/lib/format_text/format-text.h
|
||||
@top_srcdir@/lib/format_text/text_export.h
|
||||
@top_srcdir@/lib/format_text/text_import.h
|
||||
@top_srcdir@/lib/label/label.h
|
||||
@top_srcdir@/lib/locking/locking.h
|
||||
@top_srcdir@/lib/log/log.h
|
||||
@top_srcdir@/lib/log/lvm-logging.h
|
||||
@top_srcdir@/lib/metadata/lv_alloc.h
|
||||
@top_srcdir@/lib/metadata/metadata.h
|
||||
@top_srcdir@/lib/metadata/metadata-exported.h
|
||||
@top_srcdir@/lib/metadata/pv_alloc.h
|
||||
@top_srcdir@/lib/metadata/segtype.h
|
||||
@top_srcdir@/lib/mm/memlock.h
|
||||
@top_srcdir@/lib/mm/xlate.h
|
||||
@top_builddir@/lib/misc/configure.h
|
||||
@top_srcdir@/lib/misc/crc.h
|
||||
@top_srcdir@/lib/misc/intl.h
|
||||
@top_srcdir@/lib/misc/util.h
|
||||
@top_srcdir@/lib/misc/last-path-component.h
|
||||
@top_srcdir@/lib/misc/lib.h
|
||||
@top_srcdir@/lib/misc/lvm-exec.h
|
||||
@top_srcdir@/lib/misc/lvm-file.h
|
||||
@top_srcdir@/lib/misc/lvm-globals.h
|
||||
@top_srcdir@/lib/misc/lvm-string.h
|
||||
@top_builddir@/lib/misc/lvm-version.h
|
||||
@top_srcdir@/lib/misc/lvm-wrappers.h
|
||||
@top_srcdir@/lib/misc/sharedlib.h
|
||||
@top_srcdir@/lib/report/report.h
|
||||
@top_srcdir@/lib/uuid/uuid.h
|
||||
@top_srcdir@/libdm/libdevmapper.h
|
||||
@top_srcdir@/libdm/misc/dm-ioctl.h
|
||||
@top_srcdir@/libdm/misc/dm-logging.h
|
||||
@top_srcdir@/libdm/misc/dm-log-userspace.h
|
||||
@top_srcdir@/libdm/misc/dmlib.h
|
||||
@top_srcdir@/libdm/misc/kdev_t.h
|
||||
@top_srcdir@/po/pogen.h
|
||||
@top_srcdir@/tools/lvm2cmd.h
|
||||
@@ -16,30 +16,37 @@ SHELL = /bin/sh
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
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
|
||||
|
||||
.symlinks_created: .symlinks
|
||||
.symlinks_created: .symlinks
|
||||
find . -maxdepth 1 -type l -exec $(RM) \{\} \;
|
||||
for i in `cat .symlinks`; do $(LN_S) $$i ; done
|
||||
for i in `cat $<`; do $(LN_S) $$i ; done
|
||||
touch $@
|
||||
|
||||
distclean:
|
||||
find . -maxdepth 1 -type l -exec $(RM) \{\} \;
|
||||
$(RM) Makefile .include_symlinks .symlinks_created
|
||||
$(RM) Makefile .include_symlinks .symlinks_created .symlinks
|
||||
|
||||
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.
|
||||
#
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
ifeq ("@LVM1@", "shared")
|
||||
@@ -38,14 +39,15 @@ 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 \
|
||||
unknown/unknown.c \
|
||||
filters/filter-composite.c \
|
||||
filters/filter-persistent.c \
|
||||
filters/filter-regex.c \
|
||||
@@ -61,6 +63,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,9 +80,9 @@ 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 \
|
||||
misc/util.c \
|
||||
mm/memlock.c \
|
||||
report/report.c \
|
||||
@@ -87,6 +90,11 @@ SOURCES =\
|
||||
uuid/uuid.c \
|
||||
zero/zero.c
|
||||
|
||||
ifeq ("@HAVE_REALTIME@", "yes")
|
||||
SOURCES +=\
|
||||
misc/timestamp.c
|
||||
endif
|
||||
|
||||
ifeq ("@LVM1@", "internal")
|
||||
SOURCES +=\
|
||||
format1/disk-rep.c \
|
||||
@@ -135,21 +143,23 @@ ifeq ("@HAVE_LIBDL@", "yes")
|
||||
endif
|
||||
|
||||
ifeq ("@DMEVENTD@", "yes")
|
||||
CLDFLAGS += -ldevmapper-event
|
||||
CLDFLAGS += -L../daemons/dmeventd
|
||||
LIBS += -ldevmapper-event
|
||||
endif
|
||||
|
||||
LIB_STATIC = liblvm.a
|
||||
LIB_NAME = liblvm-internal
|
||||
LIB_STATIC = $(LIB_NAME).a
|
||||
|
||||
CLEAN_TARGETS += $(LIB_NAME).cflow
|
||||
|
||||
include ../make.tmpl
|
||||
|
||||
$(SUBDIRS): $(LIB_STATIC)
|
||||
|
||||
CLEAN_TARGETS += liblvm.cflow
|
||||
|
||||
include $(top_srcdir)/make.tmpl
|
||||
|
||||
liblvm.cflow: $(SOURCES)
|
||||
$(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) 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;
|
||||
}
|
||||
@@ -155,12 +156,14 @@ int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent,
|
||||
percent_range_t *percent_range)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr)
|
||||
int wait, float *percent, percent_range_t *percent_range,
|
||||
uint32_t *event_nr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -264,7 +267,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,11 +394,12 @@ int target_version(const char *target_name, uint32_t *maj,
|
||||
return r;
|
||||
}
|
||||
|
||||
int module_present(const char *target_name)
|
||||
int module_present(struct cmd_context *cmd, const char *target_name)
|
||||
{
|
||||
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",
|
||||
@@ -403,12 +407,17 @@ int module_present(const char *target_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = exec_cmd(MODPROBE_CMD, module, "", "");
|
||||
argv[0] = MODPROBE_CMD;
|
||||
argv[1] = module;
|
||||
argv[2] = NULL;
|
||||
|
||||
ret = exec_cmd(cmd, argv);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int target_present(const char *target_name, int use_modprobe)
|
||||
int target_present(struct cmd_context *cmd, const char *target_name,
|
||||
int use_modprobe)
|
||||
{
|
||||
uint32_t maj, min, patchlevel;
|
||||
|
||||
@@ -420,7 +429,7 @@ int target_present(const char *target_name, int use_modprobe)
|
||||
if (target_version(target_name, &maj, &min, &patchlevel))
|
||||
return 1;
|
||||
|
||||
if (!module_present(target_name))
|
||||
if (!module_present(cmd, target_name))
|
||||
return_0;
|
||||
}
|
||||
#endif
|
||||
@@ -477,18 +486,23 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvi
|
||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||
struct lvinfo *info, int with_open_count, int with_read_ahead)
|
||||
{
|
||||
int r;
|
||||
struct logical_volume *lv;
|
||||
|
||||
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||
return 0;
|
||||
|
||||
return _lv_info(cmd, lv, 0, info, with_open_count, with_read_ahead, 0);
|
||||
r = _lv_info(cmd, lv, 0, info, with_open_count, with_read_ahead, 0);
|
||||
vg_release(lv->vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if percent set, else 0 on failure.
|
||||
*/
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent,
|
||||
percent_range_t *percent_range)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -499,7 +513,7 @@ int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
|
||||
if (!(r = dev_manager_snapshot_percent(dm, lv, percent, percent_range)))
|
||||
stack;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
@@ -509,7 +523,8 @@ int lv_snapshot_percent(const struct logical_volume *lv, float *percent)
|
||||
|
||||
/* FIXME Merge with snapshot_percent */
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr)
|
||||
int wait, float *percent, percent_range_t *percent_range,
|
||||
uint32_t *event_nr)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
@@ -517,7 +532,7 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
/* If mirrored LV is temporarily shrinked to 1 area (= linear),
|
||||
* it should be considered in-sync. */
|
||||
if (list_size(&lv->segments) == 1 && first_seg(lv)->area_count == 1) {
|
||||
if (dm_list_size(&lv->segments) == 1 && first_seg(lv)->area_count == 1) {
|
||||
*percent = 100.0;
|
||||
return 1;
|
||||
}
|
||||
@@ -534,7 +549,8 @@ int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
|
||||
if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent,
|
||||
percent_range, event_nr)))
|
||||
stack;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
@@ -582,7 +598,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;
|
||||
@@ -590,7 +606,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);
|
||||
@@ -612,7 +628,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;
|
||||
@@ -620,7 +636,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);
|
||||
@@ -639,8 +655,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);
|
||||
}
|
||||
|
||||
@@ -665,8 +681,8 @@ 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);
|
||||
}
|
||||
|
||||
@@ -682,20 +698,24 @@ int lvs_in_vg_opened(const struct volume_group *vg)
|
||||
*/
|
||||
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;
|
||||
|
||||
/*
|
||||
* FIXME: Cluster does not report per-node LV activation status.
|
||||
* Currently the best we can do is try exclusive local activation.
|
||||
* If that succeeds, we know the LV is not active elsewhere in the
|
||||
* cluster.
|
||||
* 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);
|
||||
if (!deactivate_lv(lv->vg->cmd, lv))
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -715,7 +735,7 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
#ifdef DMEVENTD
|
||||
int i, pending = 0, monitored;
|
||||
int r = 1;
|
||||
struct list *tmp, *snh, *snht;
|
||||
struct dm_list *tmp, *snh, *snht;
|
||||
struct lv_segment *seg;
|
||||
int (*monitor_fn) (struct lv_segment *s, int e);
|
||||
uint32_t s;
|
||||
@@ -734,7 +754,7 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
* In case of a snapshot device, we monitor lv->snapshot->lv,
|
||||
* not the actual LV itself.
|
||||
*/
|
||||
if (lv_is_cow(lv))
|
||||
if (lv_is_cow(lv) && !lv_is_merging_cow(lv))
|
||||
return monitor_dev_for_events(cmd, lv->snapshot->lv, monitor);
|
||||
|
||||
/*
|
||||
@@ -745,15 +765,15 @@ int monitor_dev_for_events(struct cmd_context *cmd,
|
||||
* TODO: This may change when snapshots of mirrors are allowed.
|
||||
*/
|
||||
if (lv_is_origin(lv)) {
|
||||
list_iterate_safe(snh, snht, &lv->snapshot_segs)
|
||||
if (!monitor_dev_for_events(cmd, list_struct_base(snh,
|
||||
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;
|
||||
}
|
||||
|
||||
list_iterate(tmp, &lv->segments) {
|
||||
seg = list_item(tmp, struct lv_segment);
|
||||
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++) {
|
||||
@@ -836,36 +856,45 @@ 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) {
|
||||
if (!error_if_not_suspended) {
|
||||
r = 1;
|
||||
if (info.suspended)
|
||||
memlock_inc();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -878,13 +907,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 */
|
||||
@@ -903,26 +939,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();
|
||||
@@ -930,7 +970,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 */
|
||||
@@ -944,35 +989,67 @@ int lv_resume(struct cmd_context *cmd, const char *lvid_s)
|
||||
return _lv_resume(cmd, lvid_s, 1);
|
||||
}
|
||||
|
||||
static int _lv_has_open_snapshots(struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *snap_seg;
|
||||
struct lvinfo info;
|
||||
int r = 0;
|
||||
|
||||
dm_list_iterate_items_gen(snap_seg, &lv->snapshot_segs, origin_list) {
|
||||
if (!lv_info(lv->vg->cmd, snap_seg->cow, &info, 1, 0)) {
|
||||
r = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info.exists && info.open_count) {
|
||||
log_error("LV %s/%s has open snapshot %s: "
|
||||
"not deactivating", lv->vg->name, lv->name,
|
||||
snap_seg->cow->name);
|
||||
r = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
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.open_count && (lv->status & VISIBLE_LV)) {
|
||||
log_error("LV %s/%s in use: not deactivating", lv->vg->name,
|
||||
lv->name);
|
||||
return 0;
|
||||
if (!info.exists) {
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lv_is_visible(lv)) {
|
||||
if (info.open_count) {
|
||||
log_error("LV %s/%s in use: not deactivating",
|
||||
lv->vg->name, lv->name);
|
||||
goto out;
|
||||
}
|
||||
if (lv_is_origin(lv) && _lv_has_open_snapshots(lv))
|
||||
goto_out;
|
||||
}
|
||||
|
||||
lv_calculate_readahead(lv, NULL);
|
||||
|
||||
if (!monitor_dev_for_events(cmd, lv, 0))
|
||||
stack;
|
||||
|
||||
@@ -981,6 +1058,12 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
if (!lv_info(cmd, lv, &info, 1, 0) || info.exists)
|
||||
r = 0;
|
||||
out:
|
||||
if (lv)
|
||||
vg_release(lv->vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -989,23 +1072,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,
|
||||
@@ -1013,55 +1101,83 @@ 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 (lv_has_unknown_segments(lv)) {
|
||||
log_error("Refusing activation of LV %s containing "
|
||||
"an unrecognised segment.", 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;
|
||||
|
||||
memlock_inc();
|
||||
r = _lv_activate_lv(lv);
|
||||
if (!(r = _lv_activate_lv(lv)))
|
||||
stack;
|
||||
memlock_dec();
|
||||
fs_unlock();
|
||||
|
||||
if (r && !monitor_dev_for_events(cmd, lv, 1))
|
||||
stack;
|
||||
|
||||
out:
|
||||
if (lv)
|
||||
vg_release(lv->vg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Activate LV */
|
||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||
{
|
||||
return _lv_activate(cmd, lvid_s, exclusive, 0);
|
||||
if (!_lv_activate(cmd, lvid_s, exclusive, 0))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Activate LV only if it passes filter */
|
||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||
{
|
||||
return _lv_activate(cmd, lvid_s, exclusive, 1);
|
||||
if (!_lv_activate(cmd, lvid_s, exclusive, 1))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||
@@ -1078,9 +1194,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();
|
||||
|
||||
@@ -40,14 +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 module_present(const char *target_name);
|
||||
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);
|
||||
@@ -80,9 +81,11 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||
/*
|
||||
* Returns 1 if percent has been set, else 0.
|
||||
*/
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
|
||||
int lv_snapshot_percent(const struct logical_volume *lv, float *percent,
|
||||
percent_range_t *percent_range);
|
||||
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
int wait, float *percent, uint32_t *event_nr);
|
||||
int wait, float *percent, percent_range_t *percent_range,
|
||||
uint32_t *event_nr);
|
||||
|
||||
/*
|
||||
* Return number of LVs in the VG that are active.
|
||||
|
||||
@@ -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,7 +94,8 @@ 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;
|
||||
|
||||
@@ -112,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;
|
||||
@@ -125,7 +127,7 @@ 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)))
|
||||
if (!(dmt = _setup_task(name, dlid, 0, dmtask, major, minor)))
|
||||
return_0;
|
||||
|
||||
if (!with_open_count)
|
||||
@@ -138,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)
|
||||
@@ -167,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)) {
|
||||
@@ -209,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,
|
||||
@@ -242,6 +249,35 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
|
||||
info, read_ahead);
|
||||
}
|
||||
|
||||
static const struct dm_info *_cached_info(struct dm_pool *mem,
|
||||
const struct logical_volume *lv,
|
||||
struct dm_tree *dtree)
|
||||
{
|
||||
const char *dlid;
|
||||
struct dm_tree_node *dnode;
|
||||
const struct dm_info *dinfo;
|
||||
|
||||
if (!(dlid = _build_dlid(mem, lv->lvid.s, NULL))) {
|
||||
log_error("dlid build failed for %s", lv->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(dnode = dm_tree_find_node_by_uuid(dtree, dlid))) {
|
||||
log_error("failed to find tree node for %s", lv->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(dinfo = dm_tree_node_get_info(dnode))) {
|
||||
log_error("failed to get info from tree node for %s", lv->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dinfo->exists)
|
||||
return NULL;
|
||||
|
||||
return dinfo;
|
||||
}
|
||||
|
||||
/* FIXME Interface must cope with multiple targets */
|
||||
static int _status_run(const char *name, const char *uuid,
|
||||
unsigned long long *s, unsigned long long *l,
|
||||
@@ -255,7 +291,7 @@ 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)))
|
||||
if (!(dmt = _setup_task(name, uuid, 0, DM_DEVICE_STATUS, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
@@ -320,10 +356,72 @@ static int _status(const char *name, const char *uuid,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _lv_has_target_type(struct dev_manager *dm,
|
||||
struct logical_volume *lv,
|
||||
const char *layer,
|
||||
const char *target_type)
|
||||
{
|
||||
int r = 0;
|
||||
char *dlid;
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *type = NULL;
|
||||
char *params = NULL;
|
||||
|
||||
if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task(NULL, dlid, 0,
|
||||
DM_DEVICE_STATUS, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
log_error("Failed to disable open_count");
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto_out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info) || !info.exists)
|
||||
goto_out;
|
||||
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&type, ¶ms);
|
||||
if (type && strncmp(type, target_type,
|
||||
strlen(target_type)) == 0) {
|
||||
if (info.live_table)
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
} while (next);
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static percent_range_t _combine_percent_ranges(percent_range_t a,
|
||||
percent_range_t b)
|
||||
{
|
||||
if (a == PERCENT_INVALID || b == PERCENT_INVALID)
|
||||
return PERCENT_INVALID;
|
||||
|
||||
if (a == PERCENT_100 && b == PERCENT_100)
|
||||
return PERCENT_100;
|
||||
|
||||
if (a == PERCENT_0 && b == PERCENT_0)
|
||||
return PERCENT_0;
|
||||
|
||||
return PERCENT_0_TO_100;
|
||||
}
|
||||
|
||||
static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
const char *dlid,
|
||||
const char *target_type, int wait,
|
||||
struct logical_volume *lv, float *percent,
|
||||
const struct logical_volume *lv, float *percent,
|
||||
percent_range_t *overall_percent_range,
|
||||
uint32_t *event_nr)
|
||||
{
|
||||
int r = 0;
|
||||
@@ -333,16 +431,19 @@ 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;
|
||||
const struct dm_list *segh = &lv->segments;
|
||||
struct lv_segment *seg = NULL;
|
||||
struct segment_type *segtype;
|
||||
percent_range_t percent_range = 0, combined_percent_range = 0;
|
||||
int first_time = 1;
|
||||
|
||||
uint64_t total_numerator = 0, total_denominator = 0;
|
||||
|
||||
*percent = -1;
|
||||
*overall_percent_range = PERCENT_INVALID;
|
||||
|
||||
if (!(dmt = _setup_task(name, dlid, event_nr,
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS)))
|
||||
wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!dm_task_no_open_count(dmt))
|
||||
@@ -361,40 +462,66 @@ 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))
|
||||
if (!type || !params)
|
||||
continue;
|
||||
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, type)))
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, target_type)))
|
||||
continue;
|
||||
|
||||
if (strcmp(type, target_type)) {
|
||||
/* If kernel's type isn't an exact match is it compatible? */
|
||||
if (!segtype->ops->target_status_compatible ||
|
||||
!segtype->ops->target_status_compatible(type))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (segtype->ops->target_percent &&
|
||||
!segtype->ops->target_percent(&dm->target_state, dm->mem,
|
||||
!segtype->ops->target_percent(&dm->target_state,
|
||||
&percent_range, dm->mem,
|
||||
dm->cmd, seg, params,
|
||||
&total_numerator,
|
||||
&total_denominator,
|
||||
percent))
|
||||
&total_denominator))
|
||||
goto_out;
|
||||
|
||||
if (first_time) {
|
||||
combined_percent_range = percent_range;
|
||||
first_time = 0;
|
||||
} else
|
||||
combined_percent_range =
|
||||
_combine_percent_ranges(combined_percent_range,
|
||||
percent_range);
|
||||
} 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;
|
||||
}
|
||||
|
||||
if (total_denominator)
|
||||
if (total_denominator) {
|
||||
*percent = (float) total_numerator *100 / total_denominator;
|
||||
else if (*percent < 0)
|
||||
*overall_percent_range = combined_percent_range;
|
||||
} else {
|
||||
*percent = 100;
|
||||
if (first_time) {
|
||||
/* above ->target_percent() was not executed! */
|
||||
/* FIXME why return PERCENT_100 et. al. in this case? */
|
||||
*overall_percent_range = PERCENT_100;
|
||||
if (lv && lv_is_merging_origin(lv)) {
|
||||
/* must fail in snapshot-merge case */
|
||||
goto_out;
|
||||
}
|
||||
} else
|
||||
*overall_percent_range = combined_percent_range;
|
||||
}
|
||||
|
||||
log_debug("LV percent: %f", *percent);
|
||||
r = 1;
|
||||
@@ -406,21 +533,21 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
|
||||
static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
|
||||
const char *target_type, int wait,
|
||||
struct logical_volume *lv, float *percent,
|
||||
uint32_t *event_nr)
|
||||
const struct logical_volume *lv, float *percent,
|
||||
percent_range_t *overall_percent_range, uint32_t *event_nr)
|
||||
{
|
||||
if (dlid && *dlid) {
|
||||
if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
|
||||
event_nr))
|
||||
overall_percent_range, event_nr))
|
||||
return 1;
|
||||
else if (_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
target_type, wait, lv, percent,
|
||||
event_nr))
|
||||
overall_percent_range, event_nr))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
|
||||
event_nr))
|
||||
overall_percent_range, event_nr))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -438,24 +565,19 @@ struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||
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:
|
||||
@@ -480,7 +602,7 @@ void dev_manager_exit(void)
|
||||
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
float *percent)
|
||||
float *percent, percent_range_t *percent_range)
|
||||
{
|
||||
char *name;
|
||||
const char *dlid;
|
||||
@@ -498,8 +620,8 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
* Try and get some info on this device.
|
||||
*/
|
||||
log_debug("Getting device status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, "snapshot", 0, NULL, percent,
|
||||
NULL)))
|
||||
if (!(_percent(dm, name, dlid, "snapshot", 0, lv, percent,
|
||||
percent_range, NULL)))
|
||||
return_0;
|
||||
|
||||
/* FIXME dm_pool_free ? */
|
||||
@@ -511,28 +633,30 @@ int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
/* FIXME Merge with snapshot_percent, auto-detecting target type */
|
||||
/* FIXME Cope with more than one target */
|
||||
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, int wait,
|
||||
float *percent, uint32_t *event_nr)
|
||||
const struct logical_volume *lv, int wait,
|
||||
float *percent, percent_range_t *percent_range,
|
||||
uint32_t *event_nr)
|
||||
{
|
||||
char *name;
|
||||
const char *dlid;
|
||||
const char *suffix = (lv_is_origin(lv)) ? "real" : NULL;
|
||||
|
||||
/*
|
||||
* Build a name for the top layer.
|
||||
*/
|
||||
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, NULL)))
|
||||
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, suffix)))
|
||||
return_0;
|
||||
|
||||
/* FIXME dm_pool_free ? */
|
||||
|
||||
if (!(dlid = build_dlid(dm, lv->lvid.s, NULL))) {
|
||||
if (!(dlid = build_dlid(dm, lv->lvid.s, suffix))) {
|
||||
log_error("dlid build failed for %s", lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("Getting device mirror status percentage for %s", name);
|
||||
if (!(_percent(dm, name, dlid, "mirror", wait, lv, percent,
|
||||
event_nr)))
|
||||
percent_range, event_nr)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
@@ -587,7 +711,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) {
|
||||
@@ -621,7 +745,8 @@ 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;
|
||||
uint16_t udev_flags = 0;
|
||||
|
||||
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
|
||||
return_0;
|
||||
@@ -635,7 +760,44 @@ static int _add_dev_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info.exists && !dm_tree_add_dev(dtree, info.major, info.minor)) {
|
||||
/*
|
||||
* 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 (layer || !lv_is_visible(lv))
|
||||
udev_flags |= DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG |
|
||||
DM_UDEV_DISABLE_DISK_RULES_FLAG |
|
||||
DM_UDEV_DISABLE_OTHER_RULES_FLAG;
|
||||
|
||||
if (lv_is_cow(lv))
|
||||
udev_flags |= DM_UDEV_LOW_PRIORITY_FLAG;
|
||||
|
||||
if (!dm->cmd->current_settings.udev_rules)
|
||||
udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
|
||||
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
|
||||
|
||||
if (info.exists && !dm_tree_add_dev_with_udev_flags(dtree, info.major,
|
||||
info.minor, udev_flags)) {
|
||||
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
|
||||
info.major, info.minor);
|
||||
return 0;
|
||||
@@ -668,7 +830,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;
|
||||
|
||||
@@ -681,12 +843,12 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, struct logi
|
||||
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))
|
||||
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)))
|
||||
@@ -700,6 +862,68 @@ bad:
|
||||
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)
|
||||
@@ -713,11 +937,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,
|
||||
@@ -731,7 +954,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
dm_tree_node_add_target_area(node, NULL, dlid,
|
||||
extent_size * seg_le(seg, s));
|
||||
} else {
|
||||
log_error("Internal error: Unassigned area found in LV %s.",
|
||||
log_error(INTERNAL_ERROR "Unassigned area found in LV %s.",
|
||||
seg->lv->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -755,6 +978,30 @@ static int _add_origin_target_to_dtree(struct dev_manager *dm,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_snapshot_merge_target_to_dtree(struct dev_manager *dm,
|
||||
struct dm_tree_node *dnode,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
const char *origin_dlid, *cow_dlid, *merge_dlid;
|
||||
struct lv_segment *merging_cow_seg = find_merging_cow(lv);
|
||||
|
||||
if (!(origin_dlid = build_dlid(dm, lv->lvid.s, "real")))
|
||||
return_0;
|
||||
|
||||
if (!(cow_dlid = build_dlid(dm, merging_cow_seg->cow->lvid.s, "cow")))
|
||||
return_0;
|
||||
|
||||
if (!(merge_dlid = build_dlid(dm, merging_cow_seg->cow->lvid.s, NULL)))
|
||||
return_0;
|
||||
|
||||
if (!dm_tree_node_add_snapshot_merge_target(dnode, lv->size, origin_dlid,
|
||||
cow_dlid, merge_dlid,
|
||||
merging_cow_seg->chunk_size))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
|
||||
struct dm_tree_node *dnode,
|
||||
struct logical_volume *lv)
|
||||
@@ -769,6 +1016,10 @@ static int _add_snapshot_target_to_dtree(struct dev_manager *dm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cow is to be merged so skip adding it */
|
||||
if (lv_is_merging_cow(lv))
|
||||
return 1;
|
||||
|
||||
if (!(origin_dlid = build_dlid(dm, snap_seg->origin->lvid.s, "real")))
|
||||
return_0;
|
||||
|
||||
@@ -790,7 +1041,7 @@ static int _add_target_to_dtree(struct dev_manager *dm,
|
||||
uint64_t extent_size = seg->lv->vg->extent_size;
|
||||
|
||||
if (!seg->segtype->ops->add_target_line) {
|
||||
log_error("_emit_target: Internal error: Can't handle "
|
||||
log_error(INTERNAL_ERROR "_emit_target cannot handle "
|
||||
"segment type %s", seg->segtype->name);
|
||||
return 0;
|
||||
}
|
||||
@@ -812,7 +1063,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 */
|
||||
@@ -823,7 +1074,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, NULL)) {
|
||||
!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;
|
||||
@@ -835,11 +1087,21 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
return_0;
|
||||
|
||||
/* If this is a snapshot origin, add real LV */
|
||||
/* If this is a snapshot origin + merging snapshot, add cow + real LV */
|
||||
if (lv_is_origin(seg->lv) && !layer) {
|
||||
if (vg_is_clustered(seg->lv->vg)) {
|
||||
log_error("Clustered snapshots are not yet supported");
|
||||
return 0;
|
||||
}
|
||||
if (lv_is_merging_origin(seg->lv)) {
|
||||
if (!_add_new_lv_to_dtree(dm, dtree,
|
||||
find_merging_cow(seg->lv)->cow, "cow"))
|
||||
return_0;
|
||||
/*
|
||||
* Must also add "real" LV for use when
|
||||
* snapshot-merge target is added
|
||||
*/
|
||||
}
|
||||
if (!_add_new_lv_to_dtree(dm, dtree, seg->lv, "real"))
|
||||
return_0;
|
||||
} else if (lv_is_cow(seg->lv) && !layer) {
|
||||
@@ -849,14 +1111,20 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
/* Add any LVs used by this segment */
|
||||
for (s = 0; s < seg->area_count; s++)
|
||||
if ((seg_type(seg, s) == AREA_LV) &&
|
||||
(!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s), NULL)))
|
||||
(!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
|
||||
NULL)))
|
||||
return_0;
|
||||
}
|
||||
|
||||
/* Now we've added its dependencies, we can add the target itself */
|
||||
if (lv_is_origin(seg->lv) && !layer) {
|
||||
if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
|
||||
return_0;
|
||||
if (!lv_is_merging_origin(seg->lv)) {
|
||||
if (!_add_origin_target_to_dtree(dm, dnode, seg->lv))
|
||||
return_0;
|
||||
} else {
|
||||
if (!_add_snapshot_merge_target_to_dtree(dm, dnode, seg->lv))
|
||||
return_0;
|
||||
}
|
||||
} else if (lv_is_cow(seg->lv) && !layer) {
|
||||
if (!_add_snapshot_target_to_dtree(dm, dnode, seg->lv))
|
||||
return_0;
|
||||
@@ -865,8 +1133,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;
|
||||
@@ -878,12 +1146,49 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
struct lv_segment *seg;
|
||||
struct lv_layer *lvlayer;
|
||||
struct dm_tree_node *dnode;
|
||||
char *name, *dlid;
|
||||
const struct dm_info *dinfo;
|
||||
char *name, *dlid, *lv_name;
|
||||
uint32_t max_stripe_size = UINT32_C(0);
|
||||
uint32_t read_ahead = lv->read_ahead;
|
||||
uint32_t read_ahead_flags = UINT32_C(0);
|
||||
uint16_t udev_flags = 0;
|
||||
|
||||
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
|
||||
/* FIXME Seek a simpler way to lay out the snapshot-merge tree. */
|
||||
|
||||
if (lv_is_origin(lv) && lv_is_merging_origin(lv) && !layer) {
|
||||
/*
|
||||
* Clear merge attributes if merge isn't currently possible:
|
||||
* either origin or merging snapshot are open
|
||||
* - but use "snapshot-merge" if it is already in use
|
||||
* - open_count is always retrieved (as of dm-ioctl 4.7.0)
|
||||
* so just use the tree's existing nodes' info
|
||||
*/
|
||||
if (((dinfo = _cached_info(dm->mem, lv,
|
||||
dtree)) && dinfo->open_count) ||
|
||||
((dinfo = _cached_info(dm->mem, find_merging_cow(lv)->cow,
|
||||
dtree)) && dinfo->open_count)) {
|
||||
/* FIXME Is there anything simpler to check for instead? */
|
||||
if (!_lv_has_target_type(dm, lv, NULL, "snapshot-merge"))
|
||||
clear_snapshot_merge(lv);
|
||||
}
|
||||
}
|
||||
|
||||
lv_name = lv->name;
|
||||
if (lv_is_cow(lv) && lv_is_merging_cow(lv)) {
|
||||
if (layer) {
|
||||
/*
|
||||
* use origin's name as basis for snapshot-merge device names;
|
||||
* this allows _clean_tree to automatically cleanup "-cow"
|
||||
* when the origin is resumed (after merge completes)
|
||||
*/
|
||||
lv_name = origin_from_cow(lv)->name;
|
||||
} else {
|
||||
/* top-level snapshot device is not needed during merge */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(name = build_dm_name(dm->mem, lv->vg->name, lv_name, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(dlid = build_dlid(dm, lv->lvid.s, layer)))
|
||||
@@ -895,24 +1200,38 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return 1;
|
||||
|
||||
if (!(lvlayer = dm_pool_alloc(dm->mem, sizeof(*lvlayer)))) {
|
||||
log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.", lv->name, layer);
|
||||
log_error("_add_new_lv_to_dtree: pool alloc failed for %s %s.",
|
||||
lv_name, layer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lvlayer->lv = lv;
|
||||
|
||||
if (layer || !lv_is_visible(lv))
|
||||
udev_flags |= DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG |
|
||||
DM_UDEV_DISABLE_DISK_RULES_FLAG |
|
||||
DM_UDEV_DISABLE_OTHER_RULES_FLAG;
|
||||
|
||||
if (lv_is_cow(lv))
|
||||
udev_flags |= DM_UDEV_LOW_PRIORITY_FLAG;
|
||||
|
||||
if (!dm->cmd->current_settings.udev_rules)
|
||||
udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
|
||||
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
|
||||
|
||||
/*
|
||||
* Add LV to dtree.
|
||||
* If we're working with precommitted metadata, clear any
|
||||
* existing inactive table left behind.
|
||||
* Major/minor settings only apply to the visible layer.
|
||||
*/
|
||||
if (!(dnode = dm_tree_add_new_dev(dtree, name, dlid,
|
||||
if (!(dnode = dm_tree_add_new_dev_with_udev_flags(dtree, name, dlid,
|
||||
layer ? UINT32_C(0) : (uint32_t) lv->major,
|
||||
layer ? UINT32_C(0) : (uint32_t) lv->minor,
|
||||
_read_only_lv(lv),
|
||||
(lv->vg->status & PRECOMMITTED) ? 1 : 0,
|
||||
lvlayer)))
|
||||
lvlayer,
|
||||
udev_flags)))
|
||||
return_0;
|
||||
|
||||
/* Store existing name so we can do rename later */
|
||||
@@ -920,7 +1239,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 */
|
||||
@@ -935,6 +1254,8 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -955,24 +1276,37 @@ 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;
|
||||
|
||||
while ((child = dm_tree_next_child(&handle, root, 0))) {
|
||||
if (!(lvlayer = (struct lv_layer *) dm_tree_node_get_context(child)))
|
||||
if (!(lvlayer = dm_tree_node_get_context(child)))
|
||||
continue;
|
||||
|
||||
/* Detect rename */
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
fs_rename_lv(lvlayer->lv, name, lvname);
|
||||
} else if (!dev_manager_lv_mknodes(lvlayer->lv))
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1002,7 +1336,8 @@ static int _remove_lv_symlinks(struct dev_manager *dm, struct dm_tree_node *root
|
||||
if (*layer)
|
||||
continue;
|
||||
|
||||
fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname);
|
||||
fs_del_lv_byname(dm->cmd->dev_dir, vgname, lvname,
|
||||
dm->cmd->current_settings.udev_rules);
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -1014,6 +1349,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)))
|
||||
@@ -1031,7 +1367,12 @@ static int _clean_tree(struct dev_manager *dm, struct dm_tree_node *root)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1065,14 +1406,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))
|
||||
@@ -1085,22 +1430,34 @@ 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);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
@@ -1118,13 +1475,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)
|
||||
@@ -1139,8 +1502,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#ifndef _LVM_DEV_MANAGER_H
|
||||
#define _LVM_DEV_MANAGER_H
|
||||
|
||||
#include "metadata-exported.h"
|
||||
|
||||
struct logical_volume;
|
||||
struct volume_group;
|
||||
struct cmd_context;
|
||||
@@ -44,14 +46,17 @@ int dev_manager_info(struct dm_pool *mem, const char *name,
|
||||
struct dm_info *info, uint32_t *read_ahead);
|
||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
float *percent);
|
||||
float *percent,
|
||||
percent_range_t *percent_range);
|
||||
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
struct logical_volume *lv, int wait,
|
||||
float *percent, uint32_t *event_nr);
|
||||
const struct logical_volume *lv, int wait,
|
||||
float *percent, percent_range_t *percent_range,
|
||||
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);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
static int _mk_dir(const char *dev_dir, const char *vg_name)
|
||||
{
|
||||
char vg_path[PATH_MAX];
|
||||
mode_t old_umask;
|
||||
|
||||
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||
dev_dir, vg_name) == -1) {
|
||||
@@ -41,10 +42,14 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
|
||||
return 1;
|
||||
|
||||
log_very_verbose("Creating directory %s", vg_path);
|
||||
|
||||
old_umask = umask(DM_DEV_DIR_UMASK);
|
||||
if (mkdir(vg_path, 0777)) {
|
||||
log_sys_error("mkdir", vg_path);
|
||||
umask(old_umask);
|
||||
return 0;
|
||||
}
|
||||
umask(old_umask);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -103,11 +108,11 @@ static void _rm_blks(const char *dir)
|
||||
}
|
||||
|
||||
static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, const char *dev)
|
||||
const char *lv_name, const char *dev, int check_udev)
|
||||
{
|
||||
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) {
|
||||
@@ -161,12 +166,34 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_udev_get_sync_support() && udev_checking() && check_udev) {
|
||||
/* 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() && udev_checking() && check_udev)
|
||||
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) {
|
||||
@@ -174,16 +201,14 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!dm_set_selinux_context(lv_path, S_IFLNK))
|
||||
return_0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _rm_link(const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name)
|
||||
const char *lv_name, int check_udev)
|
||||
{
|
||||
struct stat buf;
|
||||
char lv_path[PATH_MAX];
|
||||
@@ -194,9 +219,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() && udev_checking() && check_udev)
|
||||
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;
|
||||
}
|
||||
@@ -218,36 +248,38 @@ typedef enum {
|
||||
|
||||
static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, const char *dev,
|
||||
const char *old_lv_name)
|
||||
const char *old_lv_name, int check_udev)
|
||||
{
|
||||
switch (type) {
|
||||
case FS_ADD:
|
||||
if (!_mk_dir(dev_dir, vg_name) ||
|
||||
!_mk_link(dev_dir, vg_name, lv_name, dev))
|
||||
!_mk_link(dev_dir, vg_name, lv_name, dev, check_udev))
|
||||
return_0;
|
||||
break;
|
||||
case FS_DEL:
|
||||
if (!_rm_link(dev_dir, vg_name, lv_name) ||
|
||||
if (!_rm_link(dev_dir, vg_name, lv_name, check_udev) ||
|
||||
!_rm_dir(dev_dir, vg_name))
|
||||
return_0;
|
||||
break;
|
||||
/* FIXME Use rename() */
|
||||
case FS_RENAME:
|
||||
if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name))
|
||||
if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name,
|
||||
check_udev))
|
||||
stack;
|
||||
|
||||
if (!_mk_link(dev_dir, vg_name, lv_name, dev))
|
||||
if (!_mk_link(dev_dir, vg_name, lv_name, dev, check_udev))
|
||||
stack;
|
||||
}
|
||||
|
||||
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;
|
||||
int check_udev;
|
||||
char *dev_dir;
|
||||
char *vg_name;
|
||||
char *lv_name;
|
||||
@@ -265,7 +297,7 @@ static void _store_str(char **pos, char **ptr, const char *str)
|
||||
|
||||
static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, const char *dev,
|
||||
const char *old_lv_name)
|
||||
const char *old_lv_name, int check_udev)
|
||||
{
|
||||
struct fs_op_parms *fsp;
|
||||
size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) +
|
||||
@@ -279,6 +311,7 @@ static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
|
||||
pos = fsp->names;
|
||||
fsp->type = type;
|
||||
fsp->check_udev = check_udev;
|
||||
|
||||
_store_str(&pos, &fsp->dev_dir, dev_dir);
|
||||
_store_str(&pos, &fsp->vg_name, vg_name);
|
||||
@@ -286,60 +319,71 @@ 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);
|
||||
fsp->dev, fsp->old_lv_name, fsp->check_udev);
|
||||
dm_list_del(&fsp->list);
|
||||
dm_free(fsp);
|
||||
}
|
||||
}
|
||||
|
||||
static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, const char *dev, const char *old_lv_name)
|
||||
const char *lv_name, const char *dev, const char *old_lv_name,
|
||||
int check_udev)
|
||||
{
|
||||
if (memlock()) {
|
||||
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
|
||||
old_lv_name))
|
||||
old_lv_name, check_udev))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name);
|
||||
return _do_fs_op(type, dev_dir, vg_name, lv_name, dev,
|
||||
old_lv_name, check_udev);
|
||||
}
|
||||
|
||||
int fs_add_lv(const struct logical_volume *lv, const char *dev)
|
||||
{
|
||||
return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, "");
|
||||
dev, "", lv->vg->cmd->current_settings.udev_rules);
|
||||
}
|
||||
|
||||
int fs_del_lv(const struct logical_volume *lv)
|
||||
{
|
||||
return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
"", "");
|
||||
"", "", lv->vg->cmd->current_settings.udev_rules);
|
||||
}
|
||||
|
||||
int fs_del_lv_byname(const char *dev_dir, const char *vg_name, const char *lv_name)
|
||||
int fs_del_lv_byname(const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, int check_udev)
|
||||
{
|
||||
return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "");
|
||||
return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "", check_udev);
|
||||
}
|
||||
|
||||
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, "", "", lv->vg->cmd->current_settings.udev_rules) &&
|
||||
_fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
lv->name, dev, "", lv->vg->cmd->current_settings.udev_rules));
|
||||
}
|
||||
else
|
||||
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||
dev, old_lvname, lv->vg->cmd->current_settings.udev_rules);
|
||||
}
|
||||
|
||||
void fs_unlock(void)
|
||||
|
||||
@@ -25,9 +25,10 @@
|
||||
*/
|
||||
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_del_lv_byname(const char *dev_dir, const char *vg_name,
|
||||
const char *lv_name, int check_udev);
|
||||
int fs_rename_lv(struct logical_volume *lv, const char *dev,
|
||||
const char *old_vgname, const char *old_lvname);
|
||||
void fs_unlock(void);
|
||||
|
||||
#endif
|
||||
|
||||
291
lib/cache/lvmcache.c
vendored
291
lib/cache/lvmcache.c
vendored
@@ -20,6 +20,7 @@
|
||||
#include "locking.h"
|
||||
#include "metadata.h"
|
||||
#include "filter.h"
|
||||
#include "filter-persistent.h"
|
||||
#include "memlock.h"
|
||||
#include "str_list.h"
|
||||
#include "format-text.h"
|
||||
@@ -30,7 +31,7 @@ static struct dm_hash_table *_pvid_hash = NULL;
|
||||
static struct dm_hash_table *_vgid_hash = NULL;
|
||||
static struct dm_hash_table *_vgname_hash = NULL;
|
||||
static struct dm_hash_table *_lock_hash = NULL;
|
||||
static struct list _vginfos;
|
||||
static struct dm_list _vginfos;
|
||||
static int _scanning_in_progress = 0;
|
||||
static int _has_scanned = 0;
|
||||
static int _vgs_locked = 0;
|
||||
@@ -38,7 +39,13 @@ static int _vg_global_lock_held = 0; /* Global lock held when cache wiped? */
|
||||
|
||||
int lvmcache_init(void)
|
||||
{
|
||||
list_init(&_vginfos);
|
||||
/*
|
||||
* FIXME add a proper lvmcache_locking_reset() that
|
||||
* resets the cache so no previous locks are locked
|
||||
*/
|
||||
_vgs_locked = 0;
|
||||
|
||||
dm_list_init(&_vginfos);
|
||||
|
||||
if (!(_vgname_hash = dm_hash_create(128)))
|
||||
return 0;
|
||||
@@ -52,8 +59,15 @@ int lvmcache_init(void)
|
||||
if (!(_lock_hash = dm_hash_create(128)))
|
||||
return 0;
|
||||
|
||||
if (_vg_global_lock_held)
|
||||
/*
|
||||
* Reinitialising the cache clears the internal record of
|
||||
* which locks are held. The global lock can be held during
|
||||
* this operation so its state must be restored afterwards.
|
||||
*/
|
||||
if (_vg_global_lock_held) {
|
||||
lvmcache_lock_vgname(VG_GLOBAL, 0);
|
||||
_vg_global_lock_held = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -71,11 +85,20 @@ static void _free_cached_vgmetadata(struct lvmcache_vginfo *vginfo)
|
||||
log_debug("Metadata cache: VG %s wiped.", vginfo->vgname);
|
||||
}
|
||||
|
||||
static void _store_metadata(struct lvmcache_vginfo *vginfo,
|
||||
struct volume_group *vg, unsigned precommitted)
|
||||
/*
|
||||
* Cache VG metadata against the vginfo with matching vgid.
|
||||
*/
|
||||
static void _store_metadata(struct volume_group *vg, unsigned precommitted)
|
||||
{
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
int size;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgid((const char *)&vg->id))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vginfo->vgmetadata)
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
|
||||
@@ -86,8 +109,14 @@ static void _store_metadata(struct lvmcache_vginfo *vginfo,
|
||||
|
||||
vginfo->precommitted = precommitted;
|
||||
|
||||
log_debug("Metadata cache: VG %s stored (%d bytes%s).", vginfo->vgname,
|
||||
size, precommitted ? ", precommitted" : "");
|
||||
if (!id_write_format((const struct id *)vginfo->vgid, uuid, sizeof(uuid))) {
|
||||
stack;
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug("Metadata cache: VG %s (%s) stored (%d bytes%s).",
|
||||
vginfo->vgname, uuid, size,
|
||||
precommitted ? ", precommitted" : "");
|
||||
}
|
||||
|
||||
static void _update_cache_info_lock_state(struct lvmcache_info *info,
|
||||
@@ -97,9 +126,10 @@ static void _update_cache_info_lock_state(struct lvmcache_info *info,
|
||||
int was_locked = (info->status & CACHE_LOCKED) ? 1 : 0;
|
||||
|
||||
/*
|
||||
* Cache becomes invalid whenever lock state changes
|
||||
* Cache becomes invalid whenever lock state changes unless
|
||||
* exclusive VG_GLOBAL is held (i.e. while scanning).
|
||||
*/
|
||||
if (was_locked != locked) {
|
||||
if (!vgname_is_locked(VG_GLOBAL) && (was_locked != locked)) {
|
||||
info->status |= CACHE_INVALID;
|
||||
*cached_vgmetadata_valid = 0;
|
||||
}
|
||||
@@ -116,7 +146,7 @@ static void _update_cache_vginfo_lock_state(struct lvmcache_vginfo *vginfo,
|
||||
struct lvmcache_info *info;
|
||||
int cached_vgmetadata_valid = 1;
|
||||
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
dm_list_iterate_items(info, &vginfo->infos)
|
||||
_update_cache_info_lock_state(info, locked,
|
||||
&cached_vgmetadata_valid);
|
||||
|
||||
@@ -134,7 +164,7 @@ static void _update_cache_lock_state(const char *vgname, int locked)
|
||||
_update_cache_vginfo_lock_state(vginfo, locked);
|
||||
}
|
||||
|
||||
static void _drop_metadata(const char *vgname)
|
||||
static void _drop_metadata(const char *vgname, int drop_precommitted)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
@@ -148,26 +178,91 @@ static void _drop_metadata(const char *vgname)
|
||||
* already invalidated the PV labels (before caching it)
|
||||
* and we must not do it again.
|
||||
*/
|
||||
if (!drop_precommitted && vginfo->precommitted && !vginfo->vgmetadata)
|
||||
log_error(INTERNAL_ERROR "metadata commit (or revert) missing before "
|
||||
"dropping metadata from cache.");
|
||||
|
||||
if (!vginfo->precommitted)
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
if (drop_precommitted || !vginfo->precommitted)
|
||||
dm_list_iterate_items(info, &vginfo->infos)
|
||||
info->status |= CACHE_INVALID;
|
||||
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
}
|
||||
|
||||
void lvmcache_drop_metadata(const char *vgname)
|
||||
/*
|
||||
* Remote node uses this to upgrade precommited metadata to commited state
|
||||
* when receives vg_commit notification.
|
||||
* (Note that devices can be suspended here, if so, precommited metadata are already read.)
|
||||
*/
|
||||
void lvmcache_commit_metadata(const char *vgname)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, NULL)))
|
||||
return;
|
||||
|
||||
if (vginfo->precommitted) {
|
||||
log_debug("Precommitted metadata cache: VG %s upgraded to committed.",
|
||||
vginfo->vgname);
|
||||
vginfo->precommitted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted)
|
||||
{
|
||||
/* For VG_ORPHANS, we need to invalidate all labels on orphan PVs. */
|
||||
if (!strcmp(vgname, VG_ORPHANS)) {
|
||||
_drop_metadata(FMT_TEXT_ORPHAN_VG_NAME);
|
||||
_drop_metadata(FMT_LVM1_ORPHAN_VG_NAME);
|
||||
_drop_metadata(FMT_POOL_ORPHAN_VG_NAME);
|
||||
_drop_metadata(FMT_TEXT_ORPHAN_VG_NAME, 0);
|
||||
_drop_metadata(FMT_LVM1_ORPHAN_VG_NAME, 0);
|
||||
_drop_metadata(FMT_POOL_ORPHAN_VG_NAME, 0);
|
||||
|
||||
/* Indicate that PVs could now be missing from the cache */
|
||||
init_full_scan_done(0);
|
||||
} else
|
||||
_drop_metadata(vgname);
|
||||
} else if (!vgname_is_locked(VG_GLOBAL))
|
||||
_drop_metadata(vgname, drop_precommitted);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure vgname2 comes after vgname1 alphabetically.
|
||||
* Special VG names beginning with '#' don't count.
|
||||
*/
|
||||
static int _vgname_order_correct(const char *vgname1, const char *vgname2)
|
||||
{
|
||||
if ((*vgname1 == '#') || (*vgname2 == '#'))
|
||||
return 1;
|
||||
|
||||
if (strcmp(vgname1, vgname2) < 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure VG locks are acquired in alphabetical order.
|
||||
*/
|
||||
int lvmcache_verify_lock_order(const char *vgname)
|
||||
{
|
||||
struct dm_hash_node *n;
|
||||
const char *vgname2;
|
||||
|
||||
if (!_lock_hash)
|
||||
return_0;
|
||||
|
||||
dm_hash_iterate(n, _lock_hash) {
|
||||
if (!dm_hash_get_data(_lock_hash, n))
|
||||
return_0;
|
||||
|
||||
vgname2 = dm_hash_get_key(_lock_hash, n);
|
||||
|
||||
if (!_vgname_order_correct(vgname2, vgname)) {
|
||||
log_errno(EDEADLK, INTERNAL_ERROR "VG lock %s must "
|
||||
"be requested before %s, not after.",
|
||||
vgname, vgname2);
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
|
||||
@@ -178,9 +273,9 @@ void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)
|
||||
}
|
||||
|
||||
if (dm_hash_lookup(_lock_hash, vgname))
|
||||
log_error("Internal error: Nested locking attempted on VG %s.",
|
||||
log_error(INTERNAL_ERROR "Nested locking attempted on VG %s.",
|
||||
vgname);
|
||||
|
||||
|
||||
if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
|
||||
log_error("Cache locking failure for %s", vgname);
|
||||
|
||||
@@ -201,7 +296,7 @@ int vgname_is_locked(const char *vgname)
|
||||
void lvmcache_unlock_vgname(const char *vgname)
|
||||
{
|
||||
if (!dm_hash_lookup(_lock_hash, vgname))
|
||||
log_error("Internal error: Attempt to unlock unlocked VG %s.",
|
||||
log_error(INTERNAL_ERROR "Attempt to unlock unlocked VG %s.",
|
||||
vgname);
|
||||
|
||||
_update_cache_lock_state(vgname, 0);
|
||||
@@ -225,14 +320,14 @@ static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
|
||||
return;
|
||||
|
||||
info->vginfo = vginfo;
|
||||
list_add(&vginfo->infos, &info->list);
|
||||
dm_list_add(&vginfo->infos, &info->list);
|
||||
}
|
||||
|
||||
static void _vginfo_detach_info(struct lvmcache_info *info)
|
||||
{
|
||||
if (!list_empty(&info->list)) {
|
||||
list_del(&info->list);
|
||||
list_init(&info->list);
|
||||
if (!dm_list_empty(&info->list)) {
|
||||
dm_list_del(&info->list);
|
||||
dm_list_init(&info->list);
|
||||
}
|
||||
|
||||
info->vginfo = NULL;
|
||||
@@ -266,8 +361,8 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
struct label *label;
|
||||
struct list *devh, *tmp;
|
||||
struct list devs;
|
||||
struct dm_list *devh, *tmp;
|
||||
struct dm_list devs;
|
||||
struct device_list *devl;
|
||||
char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
|
||||
|
||||
@@ -276,22 +371,22 @@ const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid)
|
||||
|
||||
/* This function is normally called before reading metadata so
|
||||
* we check cached labels here. Unfortunately vginfo is volatile. */
|
||||
list_init(&devs);
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
dm_list_init(&devs);
|
||||
dm_list_iterate_items(info, &vginfo->infos) {
|
||||
if (!(devl = dm_malloc(sizeof(*devl)))) {
|
||||
log_error("device_list element allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
devl->dev = info->dev;
|
||||
list_add(&devs, &devl->list);
|
||||
dm_list_add(&devs, &devl->list);
|
||||
}
|
||||
|
||||
memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
|
||||
|
||||
list_iterate_safe(devh, tmp, &devs) {
|
||||
devl = list_item(devh, struct device_list);
|
||||
dm_list_iterate_safe(devh, tmp, &devs) {
|
||||
devl = dm_list_item(devh, struct device_list);
|
||||
label_read(devl->dev, &label, UINT64_C(0));
|
||||
list_del(&devl->list);
|
||||
dm_list_del(&devl->list);
|
||||
dm_free(devl);
|
||||
}
|
||||
|
||||
@@ -361,7 +456,7 @@ static int _vginfo_is_valid(struct lvmcache_vginfo *vginfo)
|
||||
struct lvmcache_info *info;
|
||||
|
||||
/* Invalid if any info is invalid */
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
dm_list_iterate_items(info, &vginfo->infos)
|
||||
if (!_info_is_valid(info))
|
||||
return 0;
|
||||
|
||||
@@ -373,7 +468,7 @@ static int _vginfo_is_invalid(struct lvmcache_vginfo *vginfo)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
|
||||
list_iterate_items(info, &vginfo->infos)
|
||||
dm_list_iterate_items(info, &vginfo->infos)
|
||||
if (_info_is_valid(info))
|
||||
return 0;
|
||||
|
||||
@@ -444,6 +539,11 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (full_scan == 2 && !refresh_filters(cmd)) {
|
||||
log_error("refresh filters failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
|
||||
log_error("dev_iter creation failed");
|
||||
goto out;
|
||||
@@ -457,11 +557,18 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||
_has_scanned = 1;
|
||||
|
||||
/* Perform any format-specific scanning e.g. text files */
|
||||
list_iterate_items(fmt, &cmd->formats) {
|
||||
dm_list_iterate_items(fmt, &cmd->formats) {
|
||||
if (fmt->ops->scan && !fmt->ops->scan(fmt))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are a long-lived process, write out the updated persistent
|
||||
* device cache for the benefit of short-lived processes.
|
||||
*/
|
||||
if (full_scan == 2 && cmd->is_long_lived && cmd->dump_filter)
|
||||
persistent_filter_dump(cmd->filter);
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
@@ -506,6 +613,7 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
|
||||
if (!(vg = import_vg_from_buffer(vginfo->vgmetadata, fid)) ||
|
||||
!vg_validate(vg)) {
|
||||
_free_cached_vgmetadata(vginfo);
|
||||
vg_release(vg);
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
@@ -515,9 +623,9 @@ struct volume_group *lvmcache_get_vg(const char *vgid, unsigned precommitted)
|
||||
return vg;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct list *vgids;
|
||||
struct dm_list *vgids;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
lvmcache_label_scan(cmd, full_scan);
|
||||
@@ -527,7 +635,7 @@ struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(vginfo, &_vginfos) {
|
||||
dm_list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgids,
|
||||
dm_pool_strdup(cmd->mem, vginfo->vgid))) {
|
||||
log_error("strlist allocation failed");
|
||||
@@ -538,22 +646,22 @@ struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
|
||||
return vgids;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct list *vgnames;
|
||||
struct dm_list *vgnames;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
|
||||
lvmcache_label_scan(cmd, full_scan);
|
||||
|
||||
if (!(vgnames = str_list_create(cmd->mem))) {
|
||||
log_error("vgnames list allocation failed");
|
||||
log_errno(ENOMEM, "vgnames list allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_iterate_items(vginfo, &_vginfos) {
|
||||
dm_list_iterate_items(vginfo, &_vginfos) {
|
||||
if (!str_list_add(cmd->mem, vgnames,
|
||||
dm_pool_strdup(cmd->mem, vginfo->vgname))) {
|
||||
log_error("strlist allocation failed");
|
||||
log_errno(ENOMEM, "strlist allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -561,10 +669,10 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
||||
return vgnames;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct list *pvids;
|
||||
struct dm_list *pvids;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
@@ -576,7 +684,7 @@ struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
|
||||
return pvids;
|
||||
|
||||
list_iterate_items(info, &vginfo->infos) {
|
||||
dm_list_iterate_items(info, &vginfo->infos) {
|
||||
if (!str_list_add(cmd->mem, pvids,
|
||||
dm_pool_strdup(cmd->mem, info->dev->pvid))) {
|
||||
log_error("strlist allocation failed");
|
||||
@@ -663,7 +771,7 @@ static int _free_vginfo(struct lvmcache_vginfo *vginfo)
|
||||
vginfo_from_vgid(vginfo->vgid) == vginfo)
|
||||
dm_hash_remove(_vgid_hash, vginfo->vgid);
|
||||
|
||||
list_del(&vginfo->list);
|
||||
dm_list_del(&vginfo->list);
|
||||
|
||||
dm_free(vginfo);
|
||||
|
||||
@@ -680,7 +788,7 @@ static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vgin
|
||||
|
||||
/* vginfo still referenced? */
|
||||
if (!vginfo || is_orphan_vg(vginfo->vgname) ||
|
||||
!list_empty(&vginfo->infos))
|
||||
!dm_list_empty(&vginfo->infos))
|
||||
return 1;
|
||||
|
||||
if (!_free_vginfo(vginfo))
|
||||
@@ -706,11 +814,14 @@ void lvmcache_del(struct lvmcache_info *info)
|
||||
|
||||
static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
|
||||
{
|
||||
if (!strcmp(info->dev->pvid, pvid))
|
||||
/*
|
||||
* Nothing to do if already stored with same pvid.
|
||||
*/
|
||||
if (((dm_hash_lookup(_pvid_hash, pvid)) == info) &&
|
||||
!strcmp(info->dev->pvid, pvid))
|
||||
return 1;
|
||||
if (*info->dev->pvid) {
|
||||
if (*info->dev->pvid)
|
||||
dm_hash_remove(_pvid_hash, info->dev->pvid);
|
||||
}
|
||||
strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
|
||||
if (!dm_hash_insert(_pvid_hash, pvid, info)) {
|
||||
log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
|
||||
@@ -762,7 +873,7 @@ static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
|
||||
char uuid_primary[64] __attribute((aligned(8)));
|
||||
char uuid_new[64] __attribute((aligned(8)));
|
||||
int use_new = 0;
|
||||
|
||||
|
||||
/* Pre-existing VG takes precedence. Unexported VG takes precedence. */
|
||||
if (primary_vginfo) {
|
||||
if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
|
||||
@@ -845,6 +956,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo, *primary_vginfo, *orphan_vginfo;
|
||||
struct lvmcache_info *info2, *info3;
|
||||
char mdabuf[32];
|
||||
// struct lvmcache_vginfo *old_vginfo, *next;
|
||||
|
||||
if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
|
||||
@@ -902,7 +1014,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
log_error("cache vgname alloc failed for %s", vgname);
|
||||
return 0;
|
||||
}
|
||||
list_init(&vginfo->infos);
|
||||
dm_list_init(&vginfo->infos);
|
||||
|
||||
/*
|
||||
* If we're scanning and there's an invalidated entry, remove it.
|
||||
@@ -910,15 +1022,20 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
*/
|
||||
while ((primary_vginfo = vginfo_from_vgname(vgname, NULL)) &&
|
||||
_scanning_in_progress && _vginfo_is_invalid(primary_vginfo))
|
||||
list_iterate_items_safe(info2, info3, &primary_vginfo->infos) {
|
||||
dm_list_iterate_items_safe(info2, info3, &primary_vginfo->infos) {
|
||||
orphan_vginfo = vginfo_from_vgname(primary_vginfo->fmt->orphan_vg_name, NULL);
|
||||
_drop_vginfo(info2, primary_vginfo);
|
||||
_vginfo_attach_info(orphan_vginfo, info2);
|
||||
log_debug("lvmcache: %s: now in VG %s%s%s%s",
|
||||
if (info2->mdas.n)
|
||||
sprintf(mdabuf, " with %u mdas",
|
||||
dm_list_size(&info2->mdas));
|
||||
else
|
||||
mdabuf[0] = '\0';
|
||||
log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
|
||||
dev_name(info2->dev),
|
||||
vgname, orphan_vginfo->vgid[0] ? " (" : "",
|
||||
orphan_vginfo->vgid[0] ? orphan_vginfo->vgid : "",
|
||||
orphan_vginfo->vgid[0] ? ")" : "");
|
||||
orphan_vginfo->vgid[0] ? ")" : "", mdabuf);
|
||||
}
|
||||
|
||||
if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
|
||||
@@ -929,9 +1046,9 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
}
|
||||
/* Ensure orphans appear last on list_iterate */
|
||||
if (is_orphan_vg(vgname))
|
||||
list_add(&_vginfos, &vginfo->list);
|
||||
dm_list_add(&_vginfos, &vginfo->list);
|
||||
else
|
||||
list_add_h(&_vginfos, &vginfo->list);
|
||||
dm_list_add_h(&_vginfos, &vginfo->list);
|
||||
/***
|
||||
}
|
||||
***/
|
||||
@@ -947,13 +1064,17 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||
/* FIXME Check consistency of list! */
|
||||
vginfo->fmt = fmt;
|
||||
|
||||
if (info)
|
||||
log_debug("lvmcache: %s: now in VG %s%s%s%s",
|
||||
if (info) {
|
||||
if (info->mdas.n)
|
||||
sprintf(mdabuf, " with %u mdas", dm_list_size(&info->mdas));
|
||||
else
|
||||
mdabuf[0] = '\0';
|
||||
log_debug("lvmcache: %s: now in VG %s%s%s%s%s",
|
||||
dev_name(info->dev),
|
||||
vgname, vginfo->vgid[0] ? " (" : "",
|
||||
vginfo->vgid[0] ? vginfo->vgid : "",
|
||||
vginfo->vgid[0] ? ")" : "");
|
||||
else
|
||||
vginfo->vgid[0] ? ")" : "", mdabuf);
|
||||
} else
|
||||
log_debug("lvmcache: initialised VG %s", vgname);
|
||||
|
||||
return 1;
|
||||
@@ -1009,14 +1130,14 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||
uint32_t vgstatus, const char *creation_host)
|
||||
{
|
||||
if (!vgname && !info->vginfo) {
|
||||
log_error("Internal error: NULL vgname handed to cache");
|
||||
log_error(INTERNAL_ERROR "NULL vgname handed to cache");
|
||||
/* FIXME Remove this */
|
||||
vgname = info->fmt->orphan_vg_name;
|
||||
vgid = vgname;
|
||||
}
|
||||
|
||||
/* If PV without mdas is already in a real VG, don't make it orphan */
|
||||
if (is_orphan_vg(vgname) && info->vginfo && !list_size(&info->mdas) &&
|
||||
if (is_orphan_vg(vgname) && info->vginfo && !dm_list_size(&info->mdas) &&
|
||||
!is_orphan_vg(info->vginfo->vgname) && memlock())
|
||||
return 1;
|
||||
|
||||
@@ -1037,12 +1158,11 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
struct lvmcache_info *info;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
|
||||
|
||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||
|
||||
list_iterate_items(pvl, &vg->pvs) {
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
|
||||
/* FIXME Could pvl->pv->dev->pvid ever be different? */
|
||||
if ((info = info_from_pvid(pvid_s, 0)) &&
|
||||
@@ -1053,9 +1173,8 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
|
||||
}
|
||||
|
||||
/* store text representation of vg to cache */
|
||||
if (vg->cmd->current_settings.cache_vgmetadata &&
|
||||
(vginfo = vginfo_from_vgname(vg->name, NULL)))
|
||||
_store_metadata(vginfo, vg, precommitted);
|
||||
if (vg->cmd->current_settings.cache_vgmetadata)
|
||||
_store_metadata(vg, precommitted);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1090,16 +1209,17 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
|
||||
label->info = info;
|
||||
info->label = label;
|
||||
list_init(&info->list);
|
||||
dm_list_init(&info->list);
|
||||
info->dev = dev;
|
||||
} else {
|
||||
if (existing->dev != dev) {
|
||||
/* Is the existing entry a duplicate pvid e.g. md ? */
|
||||
if (MAJOR(existing->dev->dev) == md_major() &&
|
||||
MAJOR(dev->dev) != md_major()) {
|
||||
if (dev_subsystem_part_major(existing->dev) &&
|
||||
!dev_subsystem_part_major(dev)) {
|
||||
log_very_verbose("Ignoring duplicate PV %s on "
|
||||
"%s - using md %s",
|
||||
"%s - using %s %s",
|
||||
pvid, dev_name(dev),
|
||||
dev_subsystem_name(existing->dev),
|
||||
dev_name(existing->dev));
|
||||
return NULL;
|
||||
} else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
@@ -1109,11 +1229,12 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
pvid, dev_name(dev),
|
||||
dev_name(existing->dev));
|
||||
return NULL;
|
||||
} else if (MAJOR(existing->dev->dev) != md_major() &&
|
||||
MAJOR(dev->dev) == md_major())
|
||||
} else if (!dev_subsystem_part_major(existing->dev) &&
|
||||
dev_subsystem_part_major(dev))
|
||||
log_very_verbose("Duplicate PV %s on %s - "
|
||||
"using md %s", pvid,
|
||||
"using %s %s", pvid,
|
||||
dev_name(existing->dev),
|
||||
dev_subsystem_name(existing->dev),
|
||||
dev_name(dev));
|
||||
else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
dm_is_dm_major(MAJOR(dev->dev)))
|
||||
@@ -1125,11 +1246,15 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||
//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||
//dm_is_dm_major(MAJOR(dev->dev)))
|
||||
//
|
||||
else
|
||||
else if (!strcmp(pvid_s, existing->dev->pvid))
|
||||
log_error("Found duplicate PV %s: using %s not "
|
||||
"%s", pvid, dev_name(dev),
|
||||
dev_name(existing->dev));
|
||||
}
|
||||
if (strcmp(pvid_s, existing->dev->pvid))
|
||||
log_debug("Updating pvid cache to %s (%s) from %s (%s)",
|
||||
pvid_s, dev_name(dev),
|
||||
existing->dev->pvid, dev_name(existing->dev));
|
||||
/* Switch over to new preferred device */
|
||||
existing->dev = dev;
|
||||
info = existing;
|
||||
@@ -1199,7 +1324,7 @@ static void _lvmcache_destroy_lockname(struct dm_hash_node *n)
|
||||
if (!strcmp(vgname, VG_GLOBAL))
|
||||
_vg_global_lock_held = 1;
|
||||
else
|
||||
log_error("Internal error: Volume Group %s was not unlocked",
|
||||
log_error(INTERNAL_ERROR "Volume Group %s was not unlocked",
|
||||
dm_hash_get_key(_lock_hash, n));
|
||||
}
|
||||
|
||||
@@ -1235,9 +1360,9 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans)
|
||||
_lock_hash = NULL;
|
||||
}
|
||||
|
||||
if (!list_empty(&_vginfos))
|
||||
log_error("Internal error: _vginfos list should be empty");
|
||||
list_init(&_vginfos);
|
||||
if (!dm_list_empty(&_vginfos))
|
||||
log_error(INTERNAL_ERROR "_vginfos list should be empty");
|
||||
dm_list_init(&_vginfos);
|
||||
|
||||
if (retain_orphans)
|
||||
init_lvmcache_orphans(cmd);
|
||||
|
||||
20
lib/cache/lvmcache.h
vendored
20
lib/cache/lvmcache.h
vendored
@@ -35,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;
|
||||
@@ -50,9 +50,9 @@ struct lvmcache_vginfo {
|
||||
|
||||
/* 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;
|
||||
@@ -84,6 +84,7 @@ 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);
|
||||
int lvmcache_verify_lock_order(const char *vgname);
|
||||
|
||||
/* Queries */
|
||||
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
|
||||
@@ -98,18 +99,19 @@ 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);
|
||||
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
|
||||
void lvmcache_commit_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) 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;
|
||||
@@ -104,7 +147,9 @@ static void _init_logging(struct cmd_context *cmd)
|
||||
|
||||
/* Log message formatting */
|
||||
init_indent(find_config_tree_int(cmd, "log/indent",
|
||||
DEFAULT_INDENT));
|
||||
DEFAULT_INDENT));
|
||||
init_abort_on_internal_errors(find_config_tree_int(cmd, "global/abort_on_internal_errors",
|
||||
DEFAULT_ABORT_ON_INTERNAL_ERRORS));
|
||||
|
||||
cmd->default_settings.msg_prefix = find_config_tree_str(cmd,
|
||||
"log/prefix",
|
||||
@@ -119,6 +164,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 +192,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 +200,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 +236,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 +267,42 @@ static int _process_config(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd->default_settings.udev_rules = find_config_tree_int(cmd,
|
||||
"activation/udev_rules",
|
||||
DEFAULT_UDEV_RULES);
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
cmd->si_unit_consistency = find_config_tree_int(cmd,
|
||||
"global/si_unit_consistency",
|
||||
DEFAULT_SI_UNIT_CONSISTENCY);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -322,7 +407,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;
|
||||
}
|
||||
@@ -340,7 +425,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);
|
||||
@@ -355,7 +440,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)
|
||||
@@ -371,7 +456,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;
|
||||
@@ -391,7 +476,7 @@ 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) {
|
||||
dm_list_iterate_items(sl, &cmd->tags) {
|
||||
if (!_load_config_file(cmd, sl->str))
|
||||
return_0;
|
||||
}
|
||||
@@ -411,7 +496,7 @@ 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))
|
||||
return_0;
|
||||
@@ -422,10 +507,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,7 +518,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;
|
||||
}
|
||||
@@ -445,16 +530,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)
|
||||
@@ -534,7 +621,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
||||
*/
|
||||
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++;
|
||||
}
|
||||
|
||||
@@ -592,7 +679,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) {
|
||||
@@ -602,7 +689,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;
|
||||
@@ -620,7 +707,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;
|
||||
|
||||
/*
|
||||
@@ -655,19 +742,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,7 +781,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
|
||||
@@ -702,17 +789,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;
|
||||
}
|
||||
}
|
||||
@@ -725,16 +813,64 @@ int init_lvmcache_orphans(struct cmd_context *cmd)
|
||||
{
|
||||
struct format_type *fmt;
|
||||
|
||||
list_iterate_items(fmt, &cmd->formats)
|
||||
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;
|
||||
@@ -743,41 +879,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) {
|
||||
@@ -785,32 +925,37 @@ static int _init_segtypes(struct cmd_context *cmd)
|
||||
"global/segment_libraries");
|
||||
return 0;
|
||||
}
|
||||
if (!(lib = load_shared_library(cmd, cv->v.str,
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -847,10 +992,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;
|
||||
}
|
||||
|
||||
@@ -866,18 +1011,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;
|
||||
}
|
||||
|
||||
@@ -887,16 +1033,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;
|
||||
}
|
||||
@@ -904,9 +1050,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;
|
||||
|
||||
@@ -928,99 +1089,109 @@ 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->handles_unknown_segments = 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 error;
|
||||
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
|
||||
@@ -1030,24 +1201,53 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
int refresh_filters(struct cmd_context *cmd)
|
||||
{
|
||||
int r, saved_ignore_suspended_devices = ignore_suspended_devices();
|
||||
|
||||
if (cmd->filter) {
|
||||
cmd->filter->destroy(cmd->filter);
|
||||
cmd->filter = NULL;
|
||||
}
|
||||
|
||||
r = _init_filters(cmd, 0);
|
||||
|
||||
/*
|
||||
* During repair code must not reset suspended flag.
|
||||
*/
|
||||
init_ignore_suspended_devices(saved_ignore_suspended_devices);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int refresh_toolcontext(struct cmd_context *cmd)
|
||||
{
|
||||
log_verbose("Reloading config files");
|
||||
@@ -1106,14 +1306,9 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
if (!_init_segtypes(cmd))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we are a long-lived process, write out the updated persistent
|
||||
* device cache for the benefit of short-lived processes.
|
||||
*/
|
||||
if (cmd->is_long_lived && cmd->dump_filter)
|
||||
persistent_filter_dump(cmd->filter);
|
||||
|
||||
cmd->config_valid = 1;
|
||||
|
||||
reset_lvm_errno(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1128,16 +1323,20 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
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_rules;
|
||||
int udev_sync;
|
||||
int cache_vgmetadata;
|
||||
const char *msg_prefix;
|
||||
struct format_type *fmt;
|
||||
@@ -57,22 +59,25 @@ 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 handles_unknown_segments:1;
|
||||
unsigned partial_activation:1;
|
||||
unsigned si_unit_consistency: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;
|
||||
@@ -81,19 +86,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 refresh_filters(struct cmd_context *cmd);
|
||||
int config_files_changed(struct cmd_context *cmd);
|
||||
int init_lvmcache_orphans(struct cmd_context *cmd);
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ struct cs {
|
||||
struct output_line {
|
||||
FILE *fp;
|
||||
struct dm_pool *mem;
|
||||
putline_fn putline;
|
||||
void *putline_baton;
|
||||
};
|
||||
|
||||
static void _get_token(struct parser *p, int tok_prev);
|
||||
@@ -80,8 +82,8 @@ static struct config_node *_section(struct parser *p);
|
||||
static struct config_value *_value(struct parser *p);
|
||||
static struct config_value *_type(struct parser *p);
|
||||
static int _match_aux(struct parser *p, int t);
|
||||
static struct config_value *_create_value(struct parser *p);
|
||||
static struct config_node *_create_node(struct parser *p);
|
||||
static struct config_value *_create_value(struct dm_pool *mem);
|
||||
static struct config_node *_create_node(struct dm_pool *mem);
|
||||
static char *_dup_tok(struct parser *p);
|
||||
|
||||
static const int sep = '/';
|
||||
@@ -186,6 +188,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)
|
||||
@@ -392,10 +405,14 @@ static int _line_end(struct output_line *outline)
|
||||
}
|
||||
|
||||
line = dm_pool_end_object(outline->mem);
|
||||
if (!outline->fp)
|
||||
log_print("%s", line);
|
||||
else
|
||||
fprintf(outline->fp, "%s\n", line);
|
||||
if (outline->putline)
|
||||
outline->putline(line, outline->putline_baton);
|
||||
else {
|
||||
if (!outline->fp)
|
||||
log_print("%s", line);
|
||||
else
|
||||
fprintf(outline->fp, "%s\n", line);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -434,7 +451,7 @@ static int _write_value(struct output_line *outline, struct config_value *v)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _write_config(struct config_node *n, int only_one,
|
||||
static int _write_config(const struct config_node *n, int only_one,
|
||||
struct output_line *outline, int level)
|
||||
{
|
||||
char space[MAX_INDENT + 1];
|
||||
@@ -457,9 +474,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 */
|
||||
@@ -487,6 +504,21 @@ static int _write_config(struct config_node *n, int only_one,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_config_node(const struct config_node *cn, putline_fn putline, void *baton)
|
||||
{
|
||||
struct output_line outline;
|
||||
outline.fp = NULL;
|
||||
outline.mem = dm_pool_create("config_line", 1024);
|
||||
outline.putline = putline;
|
||||
outline.putline_baton = baton;
|
||||
if (!_write_config(cn, 0, &outline, 0)) {
|
||||
dm_pool_destroy(outline.mem);
|
||||
return_0;
|
||||
}
|
||||
dm_pool_destroy(outline.mem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_config_file(struct config_tree *cft, const char *file,
|
||||
int argc, char **argv)
|
||||
{
|
||||
@@ -494,6 +526,7 @@ int write_config_file(struct config_tree *cft, const char *file,
|
||||
int r = 1;
|
||||
struct output_line outline;
|
||||
outline.fp = NULL;
|
||||
outline.putline = NULL;
|
||||
|
||||
if (!file)
|
||||
file = "stdout";
|
||||
@@ -546,6 +579,7 @@ static struct config_node *_file(struct parser *p)
|
||||
root = n;
|
||||
else
|
||||
l->sib = n;
|
||||
n->parent = root;
|
||||
l = n;
|
||||
}
|
||||
return root;
|
||||
@@ -555,7 +589,7 @@ 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)))
|
||||
if (!(root = _create_node(p->mem)))
|
||||
return_0;
|
||||
|
||||
if (!(root->key = _dup_tok(p)))
|
||||
@@ -573,6 +607,7 @@ static struct config_node *_section(struct parser *p)
|
||||
root->child = n;
|
||||
else
|
||||
l->sib = n;
|
||||
n->parent = root;
|
||||
l = n;
|
||||
}
|
||||
match(TOK_SECTION_E);
|
||||
@@ -609,7 +644,7 @@ static struct config_value *_value(struct parser *p)
|
||||
* Special case for an empty array.
|
||||
*/
|
||||
if (!h) {
|
||||
if (!(h = _create_value(p)))
|
||||
if (!(h = _create_value(p->mem)))
|
||||
return NULL;
|
||||
|
||||
h->type = CFG_EMPTY_ARRAY;
|
||||
@@ -624,7 +659,7 @@ static struct config_value *_value(struct parser *p)
|
||||
static struct config_value *_type(struct parser *p)
|
||||
{
|
||||
/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
|
||||
struct config_value *v = _create_value(p);
|
||||
struct config_value *v = _create_value(p->mem);
|
||||
|
||||
if (!v)
|
||||
return NULL;
|
||||
@@ -820,9 +855,9 @@ static void _eat_space(struct parser *p)
|
||||
/*
|
||||
* memory management
|
||||
*/
|
||||
static struct config_value *_create_value(struct parser *p)
|
||||
static struct config_value *_create_value(struct dm_pool *mem)
|
||||
{
|
||||
struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
|
||||
struct config_value *v = dm_pool_alloc(mem, sizeof(*v));
|
||||
|
||||
if (v)
|
||||
memset(v, 0, sizeof(*v));
|
||||
@@ -830,9 +865,9 @@ static struct config_value *_create_value(struct parser *p)
|
||||
return v;
|
||||
}
|
||||
|
||||
static struct config_node *_create_node(struct parser *p)
|
||||
static struct config_node *_create_node(struct dm_pool *mem)
|
||||
{
|
||||
struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
|
||||
struct config_node *n = dm_pool_alloc(mem, sizeof(*n));
|
||||
|
||||
if (n)
|
||||
memset(n, 0, sizeof(*n));
|
||||
@@ -1011,7 +1046,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;
|
||||
|
||||
@@ -1024,9 +1059,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;
|
||||
@@ -1166,7 +1200,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;
|
||||
@@ -1252,6 +1286,10 @@ static unsigned _count_tokens(const char *str, unsigned len, int type)
|
||||
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
|
||||
@@ -1276,8 +1314,38 @@ 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;
|
||||
}
|
||||
|
||||
static struct config_value *_clone_config_value(struct dm_pool *mem, const struct config_value *v)
|
||||
{
|
||||
if (!v)
|
||||
return NULL;
|
||||
struct config_value *new = _create_value(mem);
|
||||
new->type = v->type;
|
||||
if (v->type == CFG_STRING)
|
||||
new->v.str = dm_pool_strdup(mem, v->v.str);
|
||||
else
|
||||
new->v = v->v;
|
||||
new->next = _clone_config_value(mem, v->next);
|
||||
return new;
|
||||
}
|
||||
|
||||
struct config_node *clone_config_node(struct dm_pool *mem, const struct config_node *cn,
|
||||
int siblings)
|
||||
{
|
||||
if (!cn)
|
||||
return NULL;
|
||||
struct config_node *new = _create_node(mem);
|
||||
new->key = dm_pool_strdup(mem, cn->key);
|
||||
new->child = clone_config_node(mem, cn->child, 1);
|
||||
new->v = _clone_config_value(mem, cn->v);
|
||||
if (siblings)
|
||||
new->sib = clone_config_node(mem, cn->sib, siblings);
|
||||
else
|
||||
new->sib = NULL;
|
||||
return new;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -67,6 +69,10 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||
int read_config_file(struct config_tree *cft);
|
||||
int write_config_file(struct config_tree *cft, const char *file,
|
||||
int argc, char **argv);
|
||||
|
||||
typedef int (*putline_fn)(const char *line, void *baton);
|
||||
int write_config_node(const struct config_node *cn, putline_fn putline, void *baton);
|
||||
|
||||
time_t config_file_timestamp(struct config_tree *cft);
|
||||
int config_file_changed(struct config_tree *cft);
|
||||
int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
|
||||
@@ -110,4 +116,8 @@ 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);
|
||||
|
||||
struct config_node *clone_config_node(struct dm_pool *mem, const struct config_node *cn,
|
||||
int siblings);
|
||||
#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,18 +32,25 @@
|
||||
#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_PRIORITISE_WRITE_LOCKS 1
|
||||
|
||||
#define DEFAULT_MIRRORLOG "disk"
|
||||
#define DEFAULT_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
|
||||
#define DEFAULT_MIRROR_IMAGE_FAULT_POLICY "remove"
|
||||
#define DEFAULT_MIRROR_MAX_IMAGES 8 /* limited by kernel DM_KCOPYD_MAX_REGIONS */
|
||||
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
|
||||
#define DEFAULT_DMEVENTD_MONITOR 1
|
||||
#define DEFAULT_BACKGROUND_POLLING 1
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
||||
@@ -53,18 +60,20 @@
|
||||
# define DEFAULT_FALLBACK_TO_LVM1 0
|
||||
#endif
|
||||
|
||||
#ifdef LVM1_SUPPORT
|
||||
# define DEFAULT_FORMAT "lvm1"
|
||||
#else
|
||||
# define DEFAULT_FORMAT "lvm2"
|
||||
#endif
|
||||
#define DEFAULT_FORMAT "lvm2"
|
||||
|
||||
#define DEFAULT_STRIPESIZE 64 /* KB */
|
||||
#define DEFAULT_PVMETADATASIZE 255
|
||||
#define DEFAULT_PVMETADATACOPIES 1
|
||||
#define DEFAULT_LABELSECTOR UINT64_C(1)
|
||||
#define DEFAULT_READ_AHEAD "auto"
|
||||
#define DEFAULT_UDEV_RULES 1
|
||||
#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
|
||||
@@ -78,10 +87,15 @@
|
||||
#define DEFAULT_VERBOSE 0
|
||||
#define DEFAULT_LOGLEVEL 0
|
||||
#define DEFAULT_INDENT 1
|
||||
#define DEFAULT_ABORT_ON_INTERNAL_ERRORS 0
|
||||
#define DEFAULT_UNITS "h"
|
||||
#define DEFAULT_SUFFIX 1
|
||||
#define DEFAULT_HOSTTAGS 0
|
||||
|
||||
#ifndef DEFAULT_SI_UNIT_CONSISTENCY
|
||||
# define DEFAULT_SI_UNIT_CONSISTENCY 1
|
||||
#endif
|
||||
|
||||
#ifdef DEVMAPPER_SUPPORT
|
||||
# define DEFAULT_ACTIVATION 1
|
||||
# define DEFAULT_RESERVED_MEMORY 8192
|
||||
@@ -91,7 +105,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
|
||||
|
||||
@@ -125,4 +139,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,145 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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"
|
||||
|
||||
/*
|
||||
* Initialise a list before use.
|
||||
* The list head's next and previous pointers point back to itself.
|
||||
*/
|
||||
void list_init(struct list *head)
|
||||
{
|
||||
head->n = head->p = head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert an element before 'head'.
|
||||
* If 'head' is the list head, this adds an element to the end of the list.
|
||||
*/
|
||||
void list_add(struct list *head, struct list *elem)
|
||||
{
|
||||
assert(head->n);
|
||||
|
||||
elem->n = head;
|
||||
elem->p = head->p;
|
||||
|
||||
head->p->n = elem;
|
||||
head->p = elem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert an element after 'head'.
|
||||
* If 'head' is the list head, this adds an element to the front of the list.
|
||||
*/
|
||||
void list_add_h(struct list *head, struct list *elem)
|
||||
{
|
||||
assert(head->n);
|
||||
|
||||
elem->n = head->n;
|
||||
elem->p = head;
|
||||
|
||||
head->n->p = elem;
|
||||
head->n = elem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete an element from its list.
|
||||
* Note that this doesn't change the element itself - it may still be safe
|
||||
* to follow its pointers.
|
||||
*/
|
||||
void list_del(struct list *elem)
|
||||
{
|
||||
elem->n->p = elem->p;
|
||||
elem->p->n = elem->n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an element from existing list and insert before 'head'.
|
||||
*/
|
||||
void list_move(struct list *head, struct list *elem)
|
||||
{
|
||||
list_del(elem);
|
||||
list_add(head, elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
*/
|
||||
int list_empty(const struct list *head)
|
||||
{
|
||||
return head->n == head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this the first element of the list?
|
||||
*/
|
||||
int list_start(const struct list *head, const struct list *elem)
|
||||
{
|
||||
return elem->p == head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this the last element of the list?
|
||||
*/
|
||||
int list_end(const struct list *head, const struct list *elem)
|
||||
{
|
||||
return elem->n == head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return first element of the list or NULL if empty
|
||||
*/
|
||||
struct list *list_first(const struct list *head)
|
||||
{
|
||||
return (list_empty(head) ? NULL : head->n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return last element of the list or NULL if empty
|
||||
*/
|
||||
struct list *list_last(const struct list *head)
|
||||
{
|
||||
return (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)
|
||||
{
|
||||
return (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)
|
||||
{
|
||||
return (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 s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LIST_H
|
||||
#define _LVM_LIST_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* A list consists of a list head plus elements.
|
||||
* Each element has 'next' and 'previous' pointers.
|
||||
* The list head's pointers point to the first and the last element.
|
||||
*/
|
||||
|
||||
struct list {
|
||||
struct 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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* Remove an element from existing list and insert before 'head'.
|
||||
*/
|
||||
void list_move(struct list *head, struct list *elem);
|
||||
|
||||
/*
|
||||
* Is the list empty?
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* Is this the last element of the list?
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* Return last element of the list or NULL if empty
|
||||
*/
|
||||
struct list *list_last(const struct 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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* Given the address v of an instance of 'struct list' called 'head'
|
||||
* contained in a structure of type t, return the containing structure.
|
||||
*/
|
||||
#define 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
|
||||
* a structure of type t, return the containing structure.
|
||||
*/
|
||||
#define list_item(v, t) 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) \
|
||||
(((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)
|
||||
|
||||
/*
|
||||
* Set v to each element of a list in turn.
|
||||
*/
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
/*
|
||||
* Set v to each element in a list in turn, starting from the element
|
||||
* in front of 'start'.
|
||||
* You can use this to 'unwind' a list_iterate and back out actions on
|
||||
* already-processed elements.
|
||||
* If 'start' is 'head' it walks the list backwards.
|
||||
*/
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
/*
|
||||
* A safe way to walk a list and delete and free some elements along
|
||||
* the way.
|
||||
* t must be defined as a temporary variable of the same type as v.
|
||||
*/
|
||||
#define 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'.
|
||||
*/
|
||||
#define list_iterate_items_gen(v, head, field) \
|
||||
for (v = list_struct_base((head)->n, typeof(*v), field); \
|
||||
&v->field != (head); \
|
||||
v = 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.
|
||||
*/
|
||||
#define list_iterate_items(v, head) 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'.
|
||||
* 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); \
|
||||
&v->field != (head); \
|
||||
v = t, t = 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.
|
||||
* 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)
|
||||
|
||||
/*
|
||||
* 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'.
|
||||
*/
|
||||
#define list_iterate_back_items_gen(v, head, field) \
|
||||
for (v = list_struct_base((head)->p, typeof(*v), field); \
|
||||
&v->field != (head); \
|
||||
v = 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.
|
||||
*/
|
||||
#define list_iterate_back_items(v, head) 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);
|
||||
|
||||
#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,19 +16,21 @@
|
||||
#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))))
|
||||
return_NULL;
|
||||
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;
|
||||
|
||||
@@ -43,31 +45,31 @@ int str_list_add(struct dm_pool *mem, struct list *sll, const char *str)
|
||||
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) {
|
||||
dm_list_iterate_items(sl, sllold) {
|
||||
if (!str_list_add(mem, sllnew, dm_pool_strdup(mem, sl->str)))
|
||||
return_0;
|
||||
}
|
||||
@@ -78,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;
|
||||
|
||||
@@ -92,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;
|
||||
|
||||
@@ -106,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
|
||||
|
||||
@@ -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 */
|
||||
@@ -240,7 +242,7 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
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;
|
||||
@@ -250,8 +252,8 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
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)");
|
||||
@@ -260,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;
|
||||
}
|
||||
@@ -296,19 +298,19 @@ static int _insert_dev(const char *path, dev_t 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;
|
||||
}
|
||||
|
||||
@@ -443,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;
|
||||
@@ -539,12 +541,12 @@ int dev_cache_init(struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -559,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)
|
||||
@@ -587,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)
|
||||
@@ -613,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;
|
||||
}
|
||||
|
||||
@@ -639,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;
|
||||
}
|
||||
|
||||
@@ -656,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) {
|
||||
@@ -680,8 +682,8 @@ 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;
|
||||
@@ -776,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
|
||||
@@ -262,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)
|
||||
{
|
||||
@@ -431,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",
|
||||
@@ -480,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);
|
||||
@@ -537,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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -124,6 +125,199 @@ 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;
|
||||
|
||||
if (MAJOR(dev) == blkext_major()) {
|
||||
/* lookup parent MD device from blkext partition */
|
||||
if (!get_primary_dev(sysfs_dir, blkdev, &dev))
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (MAJOR(dev) != 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)),
|
||||
@@ -132,4 +326,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"
|
||||
@@ -43,6 +44,10 @@ 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;
|
||||
|
||||
@@ -278,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,15 @@ 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':
|
||||
case 'S':
|
||||
v *= (KILO/2);
|
||||
break;
|
||||
case 'k':
|
||||
v *= KILO;
|
||||
break;
|
||||
@@ -146,27 +147,56 @@ alloc_policy_t get_alloc_from_string(const char *str)
|
||||
return ALLOC_INVALID;
|
||||
}
|
||||
|
||||
#define BASE_UNKNOWN 0
|
||||
#define BASE_SHARED 1
|
||||
#define BASE_1024 7
|
||||
#define BASE_1000 13
|
||||
#define BASE_SPECIAL 19
|
||||
#define NUM_UNIT_PREFIXES 6
|
||||
#define NUM_SPECIAL 3
|
||||
|
||||
/* Size supplied in sectors */
|
||||
static const char *_display_size(const struct cmd_context *cmd,
|
||||
uint64_t size, size_len_t sl)
|
||||
{
|
||||
int s;
|
||||
unsigned base = BASE_UNKNOWN;
|
||||
unsigned s;
|
||||
int suffix = 1, precision;
|
||||
uint64_t byte = UINT64_C(0);
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
const char *size_str[][3] = {
|
||||
{" Exabyte", " EB", "E"},
|
||||
{" Petabyte", " PB", "P"},
|
||||
{" Terabyte", " TB", "T"},
|
||||
{" Gigabyte", " GB", "G"},
|
||||
{" Megabyte", " MB", "M"},
|
||||
{" Kilobyte", " KB", "K"},
|
||||
{"", "", ""},
|
||||
{" Byte ", " B ", "B"},
|
||||
{" Units ", " Un", "U"},
|
||||
{" Sectors ", " Se", "S"},
|
||||
{" ", " ", " "},
|
||||
const char * const size_str[][3] = {
|
||||
/* BASE_UNKNOWN */
|
||||
{" ", " ", " "}, /* [0] */
|
||||
|
||||
/* BASE_SHARED - Used if cmd->si_unit_consistency = 0 */
|
||||
{" Exabyte", " EB", "E"}, /* [1] */
|
||||
{" Petabyte", " PB", "P"}, /* [2] */
|
||||
{" Terabyte", " TB", "T"}, /* [3] */
|
||||
{" Gigabyte", " GB", "G"}, /* [4] */
|
||||
{" Megabyte", " MB", "M"}, /* [5] */
|
||||
{" Kilobyte", " KB", "K"}, /* [6] */
|
||||
|
||||
/* BASE_1024 - Used if cmd->si_unit_consistency = 1 */
|
||||
{" Exbibyte", " EiB", "e"}, /* [7] */
|
||||
{" Pebibyte", " PiB", "p"}, /* [8] */
|
||||
{" Tebibyte", " TiB", "t"}, /* [9] */
|
||||
{" Gibibyte", " GiB", "g"}, /* [10] */
|
||||
{" Mebibyte", " MiB", "m"}, /* [11] */
|
||||
{" Kibibyte", " KiB", "k"}, /* [12] */
|
||||
|
||||
/* BASE_1000 - Used if cmd->si_unit_consistency = 1 */
|
||||
{" Exabyte", " EB", "E"}, /* [13] */
|
||||
{" Petabyte", " PB", "P"}, /* [14] */
|
||||
{" Terabyte", " TB", "T"}, /* [15] */
|
||||
{" Gigabyte", " GB", "G"}, /* [16] */
|
||||
{" Megabyte", " MB", "M"}, /* [17] */
|
||||
{" Kilobyte", " kB", "K"}, /* [18] */
|
||||
|
||||
/* BASE_SPECIAL */
|
||||
{" Byte ", " B ", "B"}, /* [19] */
|
||||
{" Units ", " Un", "U"}, /* [20] */
|
||||
{" Sectors ", " Se", "S"}, /* [21] */
|
||||
};
|
||||
|
||||
if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
|
||||
@@ -176,30 +206,72 @@ static const char *_display_size(const struct cmd_context *cmd,
|
||||
|
||||
suffix = cmd->current_settings.suffix;
|
||||
|
||||
for (s = 0; s < 10; s++)
|
||||
if (toupper((int) cmd->current_settings.unit_type) ==
|
||||
*size_str[s][2])
|
||||
break;
|
||||
if (!cmd->si_unit_consistency) {
|
||||
/* Case-independent match */
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (toupper((int) cmd->current_settings.unit_type) ==
|
||||
*size_str[BASE_SHARED + s][2]) {
|
||||
base = BASE_SHARED;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Case-dependent match for powers of 1000 */
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (cmd->current_settings.unit_type ==
|
||||
*size_str[BASE_1000 + s][2]) {
|
||||
base = BASE_1000;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Case-dependent match for powers of 1024 */
|
||||
if (base == BASE_UNKNOWN)
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (cmd->current_settings.unit_type ==
|
||||
*size_str[BASE_1024 + s][2]) {
|
||||
base = BASE_1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (base == BASE_UNKNOWN)
|
||||
/* Check for special units - s, b or u */
|
||||
for (s = 0; s < NUM_SPECIAL; s++)
|
||||
if (toupper((int) cmd->current_settings.unit_type) ==
|
||||
*size_str[BASE_SPECIAL + s][2]) {
|
||||
base = BASE_SPECIAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (size == UINT64_C(0)) {
|
||||
sprintf(size_buf, "0%s", suffix ? size_str[s][sl] : "");
|
||||
if (base == BASE_UNKNOWN)
|
||||
s = 0;
|
||||
sprintf(size_buf, "0%s", suffix ? size_str[base + s][sl] : "");
|
||||
return size_buf;
|
||||
}
|
||||
|
||||
size *= UINT64_C(512);
|
||||
|
||||
if (s < 10)
|
||||
if (base != BASE_UNKNOWN)
|
||||
byte = cmd->current_settings.unit_factor;
|
||||
else {
|
||||
suffix = 1;
|
||||
if (cmd->current_settings.unit_type == 'H')
|
||||
/* Human-readable style */
|
||||
if (cmd->current_settings.unit_type == 'H') {
|
||||
units = UINT64_C(1000);
|
||||
else
|
||||
base = BASE_1000;
|
||||
} else {
|
||||
units = UINT64_C(1024);
|
||||
base = BASE_1024;
|
||||
}
|
||||
|
||||
if (!cmd->si_unit_consistency)
|
||||
base = BASE_SHARED;
|
||||
|
||||
byte = units * units * units * units * units * units;
|
||||
s = 0;
|
||||
while (size_str[s] && size < byte)
|
||||
s++, byte /= units;
|
||||
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES && size < byte; s++)
|
||||
byte /= units;
|
||||
|
||||
suffix = 1;
|
||||
}
|
||||
|
||||
/* FIXME Make precision configurable */
|
||||
@@ -213,7 +285,7 @@ static const char *_display_size(const struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
|
||||
(double) size / byte, suffix ? size_str[s][sl] : "");
|
||||
(double) size / byte, suffix ? size_str[base + s][sl] : "");
|
||||
|
||||
return size_buf;
|
||||
}
|
||||
@@ -245,7 +317,7 @@ void pvdisplay_colons(const struct physical_volume *pv)
|
||||
return;
|
||||
}
|
||||
|
||||
log_print("%s:%s:%" PRIu64 ":-1:%u:%u:-1:%" PRIu32 ":%u:%u:%u:%s",
|
||||
log_print("%s:%s:%" PRIu64 ":-1:%" PRIu64 ":%" PRIu64 ":-1:%" PRIu32 ":%u:%u:%u:%s",
|
||||
pv_dev_name(pv), pv->vg_name, pv->size,
|
||||
/* FIXME pv->pv_number, Derive or remove? */
|
||||
pv->status, /* FIXME Support old or new format here? */
|
||||
@@ -255,8 +327,6 @@ void pvdisplay_colons(const struct physical_volume *pv)
|
||||
pv->pe_count,
|
||||
pv->pe_count - pv->pe_alloc_count,
|
||||
pv->pe_alloc_count, *uuid ? uuid : "none");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void pvdisplay_segments(const struct physical_volume *pv)
|
||||
@@ -266,7 +336,7 @@ 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);
|
||||
|
||||
@@ -283,7 +353,6 @@ void pvdisplay_segments(const struct physical_volume *pv)
|
||||
}
|
||||
|
||||
log_print(" ");
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME Include label fields */
|
||||
@@ -341,14 +410,17 @@ void pvdisplay_full(const struct cmd_context *cmd,
|
||||
/* LV count is no longer available when displaying PV
|
||||
log_print("Cur LV %u", vg->lv_count);
|
||||
*/
|
||||
log_print("PE Size (KByte) %" PRIu32, pv->pe_size / 2);
|
||||
|
||||
if (cmd->si_unit_consistency)
|
||||
log_print("PE Size %s", display_size(cmd, (uint64_t) pv->pe_size));
|
||||
else
|
||||
log_print("PE Size (KByte) %" PRIu32, pv->pe_size / 2);
|
||||
|
||||
log_print("Total PE %u", pv->pe_count);
|
||||
log_print("Free PE %" PRIu32, pe_free);
|
||||
log_print("Allocated PE %u", pv->pe_alloc_count);
|
||||
log_print("PV UUID %s", *uuid ? uuid : "none");
|
||||
log_print(" ");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int pvdisplay_short(const struct cmd_context *cmd __attribute((unused)),
|
||||
@@ -382,7 +454,7 @@ void lvdisplay_colons(const struct logical_volume *lv)
|
||||
struct lvinfo info;
|
||||
inkernel = lv_info(lv->vg->cmd, lv, &info, 1, 0) && info.exists;
|
||||
|
||||
log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
|
||||
log_print("%s%s/%s:%s:%" PRIu64 ":%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
|
||||
lv->vg->cmd->dev_dir,
|
||||
lv->vg->name,
|
||||
lv->name,
|
||||
@@ -393,7 +465,6 @@ void lvdisplay_colons(const struct logical_volume *lv)
|
||||
/* FIXME Add num allocated to struct! lv->lv_allocated_le, */
|
||||
(lv->alloc == ALLOC_CONTIGUOUS ? 2 : 0), lv->read_ahead,
|
||||
inkernel ? info.major : -1, inkernel ? info.minor : -1);
|
||||
return;
|
||||
}
|
||||
|
||||
int lvdisplay_full(struct cmd_context *cmd,
|
||||
@@ -403,8 +474,9 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
struct lvinfo info;
|
||||
int inkernel, snap_active = 0;
|
||||
char uuid[64] __attribute((aligned(8)));
|
||||
struct lv_segment *snap_seg = NULL;
|
||||
struct lv_segment *snap_seg = NULL, *mirror_seg = NULL;
|
||||
float snap_percent; /* fused, fsize; */
|
||||
percent_range_t percent_range;
|
||||
|
||||
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
@@ -425,28 +497,30 @@ 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,
|
||||
&snap_percent)))
|
||||
if (snap_percent < 0 || snap_percent >= 100)
|
||||
&snap_percent,
|
||||
&percent_range)))
|
||||
if (percent_range == PERCENT_INVALID)
|
||||
snap_active = 0;
|
||||
log_print(" %s%s/%s [%s]",
|
||||
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
snap_seg->cow->name,
|
||||
(snap_active > 0) ? "active" : "INACTIVE");
|
||||
snap_active ? "active" : "INACTIVE");
|
||||
}
|
||||
snap_seg = NULL;
|
||||
} else if ((snap_seg = find_cow(lv))) {
|
||||
if (inkernel &&
|
||||
(snap_active = lv_snapshot_percent(snap_seg->cow,
|
||||
&snap_percent)))
|
||||
if (snap_percent < 0 || snap_percent >= 100)
|
||||
&snap_percent,
|
||||
&percent_range)))
|
||||
if (percent_range == PERCENT_INVALID)
|
||||
snap_active = 0;
|
||||
|
||||
log_print("LV snapshot status %s destination for %s%s/%s",
|
||||
(snap_active > 0) ? "active" : "INACTIVE",
|
||||
snap_active ? "active" : "INACTIVE",
|
||||
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
snap_seg->origin->name);
|
||||
}
|
||||
@@ -483,10 +557,17 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
display_size(cmd, (uint64_t) snap_seg->chunk_size));
|
||||
}
|
||||
|
||||
log_print("Segments %u", list_size(&lv->segments));
|
||||
if (lv->status & MIRRORED) {
|
||||
mirror_seg = first_seg(lv);
|
||||
log_print("Mirrored volumes %" PRIu32, mirror_seg->area_count);
|
||||
if (lv->status & CONVERTING)
|
||||
log_print("LV type Mirror undergoing conversion");
|
||||
}
|
||||
|
||||
log_print("Segments %u", dm_list_size(&lv->segments));
|
||||
|
||||
/********* FIXME Stripes & stripesize for each segment
|
||||
log_print("Stripe size (KByte) %u", lv->stripesize / 2);
|
||||
log_print("Stripe size %s", display_size(cmd, (uint64_t) lv->stripesize));
|
||||
***********/
|
||||
|
||||
log_print("Allocation %s", get_alloc_string(lv->alloc));
|
||||
@@ -551,7 +632,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);
|
||||
|
||||
@@ -567,21 +648,15 @@ int lvdisplay_segments(const struct logical_volume *lv)
|
||||
|
||||
void vgdisplay_extents(const struct volume_group *vg __attribute((unused)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void vgdisplay_full(const struct volume_group *vg)
|
||||
{
|
||||
uint32_t access;
|
||||
uint32_t access_str;
|
||||
uint32_t active_pvs;
|
||||
uint32_t lv_count = 0;
|
||||
struct lv_list *lvl;
|
||||
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);
|
||||
@@ -589,18 +664,18 @@ 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_is_exported(vg) ? "exported/" : "",
|
||||
vg_is_resizeable(vg) ? "" : "NOT ");
|
||||
/* vg number not part of LVM2 design
|
||||
log_print ("VG # %u\n", vg->vg_number);
|
||||
*/
|
||||
@@ -610,12 +685,8 @@ void vgdisplay_full(const struct volume_group *vg)
|
||||
vg->status & SHARED ? "yes" : "no");
|
||||
}
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs)
|
||||
if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
|
||||
lv_count++;
|
||||
|
||||
log_print("MAX LV %u", vg->max_lv);
|
||||
log_print("Cur LV %u", lv_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",
|
||||
@@ -642,8 +713,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;
|
||||
@@ -652,39 +722,28 @@ void vgdisplay_full(const struct volume_group *vg)
|
||||
|
||||
log_print("VG UUID %s", uuid);
|
||||
log_print(" ");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void vgdisplay_colons(const struct volume_group *vg)
|
||||
{
|
||||
uint32_t active_pvs;
|
||||
uint32_t lv_count;
|
||||
struct lv_list *lvl;
|
||||
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;
|
||||
|
||||
list_iterate_items(lvl, &vg->lvs)
|
||||
if (lv_is_visible(lvl->lv) && !(lvl->lv->status & SNAPSHOT))
|
||||
lv_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))) {
|
||||
@@ -692,14 +751,14 @@ void vgdisplay_colons(const struct volume_group *vg)
|
||||
return;
|
||||
}
|
||||
|
||||
log_print("%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
|
||||
log_print("%s:%s:%" PRIu64 ":-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,
|
||||
@@ -711,7 +770,6 @@ void vgdisplay_colons(const struct volume_group *vg)
|
||||
vg->extent_count - vg->free_count,
|
||||
vg->free_count,
|
||||
uuid[0] ? uuid : "none");
|
||||
return;
|
||||
}
|
||||
|
||||
void vgdisplay_short(const struct volume_group *vg)
|
||||
@@ -723,16 +781,14 @@ 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));
|
||||
return;
|
||||
display_size(vg->cmd, vg_free(vg)));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -741,7 +797,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);
|
||||
}
|
||||
}
|
||||
@@ -757,6 +813,7 @@ char yes_no_prompt(const char *prompt, ...)
|
||||
va_start(ap, prompt);
|
||||
vprintf(prompt, ap);
|
||||
va_end(ap);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if ((c = getchar()) == EOF) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user