mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-23 23:33:15 +03:00
Compare commits
2220 Commits
dev-bmr-dm
...
v2_02_23
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de4c1daf29 | ||
|
|
0b55d7d0d8 | ||
|
|
5d86fd8fdb | ||
|
|
1b76eb1f59 | ||
|
|
b05678d8bf | ||
|
|
781f4971c6 | ||
|
|
d02ac7b99a | ||
|
|
b1b6c97f7c | ||
|
|
baee28ab5c | ||
|
|
83edf68ff9 | ||
|
|
c7588f91dd | ||
|
|
30b432adc5 | ||
|
|
7c9733eb5d | ||
|
|
a223c3fea3 | ||
|
|
d5250f4901 | ||
|
|
25f29f4712 | ||
|
|
382af5563d | ||
|
|
8cf3d165d3 | ||
|
|
0fd6ce546f | ||
|
|
b881c372bc | ||
|
|
94c5e7deb0 | ||
|
|
c344766f3c | ||
|
|
67895de0bc | ||
|
|
ff00cb6990 | ||
|
|
2cc75c11ed | ||
|
|
cd79e58eda | ||
|
|
6fa801f3d8 | ||
|
|
684eecba1d | ||
|
|
da9cf7e5de | ||
|
|
f57e7445fd | ||
|
|
fba1388719 | ||
|
|
80ed029c17 | ||
|
|
34a74e81e3 | ||
|
|
cb120ddb15 | ||
|
|
f9ee4395b0 | ||
|
|
71f06d51ed | ||
|
|
217f70952f | ||
|
|
f813d41a76 | ||
|
|
d851289d8a | ||
|
|
b115b8a2ea | ||
|
|
d0f7067471 | ||
|
|
be5b4c38a7 | ||
|
|
d6d597e3dd | ||
|
|
84e348fade | ||
|
|
910054657e | ||
|
|
8357a11249 | ||
|
|
9b021ba057 | ||
|
|
317e588efd | ||
|
|
b1d32a03c7 | ||
|
|
ee6e6529ee | ||
|
|
9d944d6cf9 | ||
|
|
13635d281a | ||
|
|
2493c46970 | ||
|
|
63e4217271 | ||
|
|
f4bd12e8e9 | ||
|
|
df15f46900 | ||
|
|
fb3a732361 | ||
|
|
2d74110feb | ||
|
|
19d102082d | ||
|
|
d2af2c9487 | ||
|
|
82980149fa | ||
|
|
a19bb7b909 | ||
|
|
9d98c3278d | ||
|
|
26376ac1c9 | ||
|
|
8459f99341 | ||
|
|
e5bdb0e0b5 | ||
|
|
1106b7775a | ||
|
|
ae2852156d | ||
|
|
44c6c36c43 | ||
|
|
a81926503d | ||
|
|
af13ccddda | ||
|
|
392e1bc2e8 | ||
|
|
9268d92c70 | ||
|
|
bb3366c07d | ||
|
|
d24d563ebc | ||
|
|
954bd9257b | ||
|
|
5d51a56c02 | ||
|
|
f48648552e | ||
|
|
edb9c3cc9f | ||
|
|
01dc83b936 | ||
|
|
3a8dff3a62 | ||
|
|
13b234ccba | ||
|
|
e451e93664 | ||
|
|
b4f9531475 | ||
|
|
3184ff75c4 | ||
|
|
43243f4d30 | ||
|
|
c975a100b1 | ||
|
|
02bf389425 | ||
|
|
bcb9a3dd04 | ||
|
|
cce3baa275 | ||
|
|
2b48fad426 | ||
|
|
d554b2bc94 | ||
|
|
f66943de43 | ||
|
|
9d1e9bc2fb | ||
|
|
2d6a014920 | ||
|
|
c1952bf257 | ||
|
|
a10227eb03 | ||
|
|
475ae29b85 | ||
|
|
0b9cfc278b | ||
|
|
b57b6b4fba | ||
|
|
7d948f7bc5 | ||
|
|
459023d171 | ||
|
|
fd6570720a | ||
|
|
7831665417 | ||
|
|
7c9920d982 | ||
|
|
cbdccf0a9c | ||
|
|
64fa83ec3f | ||
|
|
faff865cfd | ||
|
|
742ab55a9a | ||
|
|
66e623fb2a | ||
|
|
4ab17ee965 | ||
|
|
7f48ca5132 | ||
|
|
da983848b4 | ||
|
|
bc03f7bad3 | ||
|
|
a1c8bd3846 | ||
|
|
404bc284e0 | ||
|
|
9dee30ff0e | ||
|
|
f91aadbea8 | ||
|
|
aa15a10c91 | ||
|
|
5b03e36351 | ||
|
|
b9ba9ffad2 | ||
|
|
642be5d16c | ||
|
|
ee68d715bf | ||
|
|
224084f056 | ||
|
|
1cd8c849b8 | ||
|
|
169f68bfcd | ||
|
|
d2b7cfa2d1 | ||
|
|
a40c7dff5d | ||
|
|
e8e00630d3 | ||
|
|
e33720c854 | ||
|
|
bd8a4e0d17 | ||
|
|
586a2aef76 | ||
|
|
ce1d8f6754 | ||
|
|
7b0f401065 | ||
|
|
8387016eef | ||
|
|
4e1342b641 | ||
|
|
e45a184d90 | ||
|
|
979e1012d2 | ||
|
|
fe10a50e23 | ||
|
|
8ab6d72519 | ||
|
|
3aada6dd1d | ||
|
|
0933036366 | ||
|
|
05f5abdc06 | ||
|
|
fb875e0709 | ||
|
|
9acdc2f6bf | ||
|
|
028ce4bff6 | ||
|
|
3f245ad6db | ||
|
|
23115f4116 | ||
|
|
cf5f48e6cc | ||
|
|
997fa756ad | ||
|
|
e23f75b1cc | ||
|
|
6531e88761 | ||
|
|
e76a9c2618 | ||
|
|
45be8a836b | ||
|
|
954b6032e7 | ||
|
|
bd95416f27 | ||
|
|
df2577ace2 | ||
|
|
720e6558c9 | ||
|
|
c239f15d8a | ||
|
|
dfa1f80a57 | ||
|
|
15dfb93b17 | ||
|
|
0ec8488c2b | ||
|
|
94b2e29cb1 | ||
|
|
fefa8e9b4d | ||
|
|
32c4c44812 | ||
|
|
05195e2b1d | ||
|
|
4c2ff675b8 | ||
|
|
e5692a4721 | ||
|
|
312e6a0d31 | ||
|
|
5bb8efa41f | ||
|
|
949a835f4a | ||
|
|
85e6042941 | ||
|
|
3cd2f28975 | ||
|
|
2179a72c3a | ||
|
|
a5f282f156 | ||
|
|
40e8631f63 | ||
|
|
9ded05bb97 | ||
|
|
ec8efa35a1 | ||
|
|
f72bf20482 | ||
|
|
ebde2002e8 | ||
|
|
352a66f46f | ||
|
|
d84c5391f7 | ||
|
|
f4c582472b | ||
|
|
1485586f7e | ||
|
|
d5c9024335 | ||
|
|
860cf80703 | ||
|
|
897ff3161f | ||
|
|
b356b2e501 | ||
|
|
1d2733c893 | ||
|
|
32d9126094 | ||
|
|
db43314e50 | ||
|
|
68d2baeb65 | ||
|
|
1fd5f562d3 | ||
|
|
48e02f2086 | ||
|
|
eab7b2b581 | ||
|
|
45abade7fc | ||
|
|
5372fc4b43 | ||
|
|
4e2f240c98 | ||
|
|
bb3605518d | ||
|
|
3ef6d37f27 | ||
|
|
88e9f2f7f4 | ||
|
|
704a447df9 | ||
|
|
a5fcb26a33 | ||
|
|
2491a61481 | ||
|
|
91831d51ed | ||
|
|
174f0c19f7 | ||
|
|
de6fadfb4f | ||
|
|
f946db3e00 | ||
|
|
8d05e5bc31 | ||
|
|
cfb46820e4 | ||
|
|
081f1cbcc2 | ||
|
|
7bc6da326f | ||
|
|
cd95a0df7b | ||
|
|
82fa497c16 | ||
|
|
44fd345206 | ||
|
|
088e1c9db4 | ||
|
|
d4f16e666e | ||
|
|
8233cfd371 | ||
|
|
ff05e2e30d | ||
|
|
a8ea7dd3fb | ||
|
|
96f70a5303 | ||
|
|
f1604c3e69 | ||
|
|
c42c8c5192 | ||
|
|
5facb53a41 | ||
|
|
d039ce89af | ||
|
|
bc7605103f | ||
|
|
d305d655d4 | ||
|
|
4ef1220b16 | ||
|
|
a4fef143cd | ||
|
|
74ecb724a9 | ||
|
|
af235897ab | ||
|
|
5ec4e458b5 | ||
|
|
2dae63ce21 | ||
|
|
be748fe33b | ||
|
|
7408340b6a | ||
|
|
29eb92446e | ||
|
|
ae6918742e | ||
|
|
863484bb65 | ||
|
|
1cd7ebce4c | ||
|
|
eef8c7862e | ||
|
|
b52375d446 | ||
|
|
6e2babc2ce | ||
|
|
08e253bed1 | ||
|
|
c6661477a2 | ||
|
|
415cfd99a0 | ||
|
|
8c2e37381a | ||
|
|
45df79feba | ||
|
|
5824f992b7 | ||
|
|
b0b60fafd5 | ||
|
|
8d98b02ba2 | ||
|
|
a93fe79bc4 | ||
|
|
4aebd7be37 | ||
|
|
3170a5db32 | ||
|
|
3605b9eef6 | ||
|
|
a945f1fde2 | ||
|
|
461a997b5b | ||
|
|
a80afd7b4e | ||
|
|
aad2b51d85 | ||
|
|
36a9a81ff1 | ||
|
|
42c88546ae | ||
|
|
0f0e86ef9b | ||
|
|
98efd9a857 | ||
|
|
a0c27d95b7 | ||
|
|
984651d99d | ||
|
|
c6f7370b30 | ||
|
|
3e4b8e8985 | ||
|
|
73f08b98d2 | ||
|
|
8607a74206 | ||
|
|
8339f3ceb3 | ||
|
|
c0c9f3cc19 | ||
|
|
81f4813c29 | ||
|
|
94f57745b9 | ||
|
|
54fb2ebbe0 | ||
|
|
02d122b65b | ||
|
|
df0a5561a1 | ||
|
|
f7c55da7d0 | ||
|
|
b385f701ce | ||
|
|
05dd42f443 | ||
|
|
36d816d5cb | ||
|
|
92a6746e70 | ||
|
|
1728848a39 | ||
|
|
f9eb4e7487 | ||
|
|
d0b9f33aeb | ||
|
|
718583b241 | ||
|
|
6737127e9a | ||
|
|
19a7b4479b | ||
|
|
c340647502 | ||
|
|
0f987d2982 | ||
|
|
52bcaed169 | ||
|
|
177bd565ac | ||
|
|
c801c32fc5 | ||
|
|
d090cf3058 | ||
|
|
1e4b82cc94 | ||
|
|
3426f31184 | ||
|
|
b4fb7af1df | ||
|
|
b36647598b | ||
|
|
fd6b94f20e | ||
|
|
296dc0ed8a | ||
|
|
4f869e14d6 | ||
|
|
5704270e9d | ||
|
|
505b381e85 | ||
|
|
da6cb15393 | ||
|
|
16843f6cc8 | ||
|
|
64f3ad1fd4 | ||
|
|
ff4c4f99b3 | ||
|
|
f5d2e09569 | ||
|
|
f2bdbe0d4d | ||
|
|
c51a13caa6 | ||
|
|
7840c78a23 | ||
|
|
c706f3246b | ||
|
|
608eedf88d | ||
|
|
a564ca82be | ||
|
|
c868b1fee2 | ||
|
|
22374f718f | ||
|
|
abe3cfcf41 | ||
|
|
59db4b50cd | ||
|
|
bdae38765d | ||
|
|
66d3ceeb61 | ||
|
|
445dd17db3 | ||
|
|
cff78a2577 | ||
|
|
6a09e64195 | ||
|
|
22eabe5eab | ||
|
|
b69ba36c2d | ||
|
|
5240aad22b | ||
|
|
2897eb3cb3 | ||
|
|
d3f2f00c25 | ||
|
|
bacfb913a0 | ||
|
|
c99d0236a0 | ||
|
|
aac2b655f7 | ||
|
|
126c41e73a | ||
|
|
359ee54f0d | ||
|
|
28ab560907 | ||
|
|
ead252fee4 | ||
|
|
abf67914c4 | ||
|
|
127884e9dd | ||
|
|
654f5049eb | ||
|
|
979ca34259 | ||
|
|
4dd1086805 | ||
|
|
3503d4b72c | ||
|
|
b8d32a0d33 | ||
|
|
45dca55fc8 | ||
|
|
445d8ecd9f | ||
|
|
c980add503 | ||
|
|
133842392a | ||
|
|
8baf2ef155 | ||
|
|
20b71340bc | ||
|
|
61d8baf8b1 | ||
|
|
56a9645aa5 | ||
|
|
85877000a6 | ||
|
|
2f7d2477b6 | ||
|
|
21ea3f05f4 | ||
|
|
79d3492e90 | ||
|
|
5972777abe | ||
|
|
8e373ff868 | ||
|
|
a4db92da3a | ||
|
|
9b777eb281 | ||
|
|
bd3c652184 | ||
|
|
800f747570 | ||
|
|
2b8423437e | ||
|
|
8b4b6945f8 | ||
|
|
e5ecfec5c4 | ||
|
|
f95dbff71f | ||
|
|
098f6830a6 | ||
|
|
d1ecebdb52 | ||
|
|
590b654251 | ||
|
|
3bf190c8ab | ||
|
|
dcca7638e0 | ||
|
|
70e45ad37b | ||
|
|
db88210289 | ||
|
|
d2e0d96cc3 | ||
|
|
3feba82ccc | ||
|
|
db924da231 | ||
|
|
fc55ae7e6d | ||
|
|
86e757a6ad | ||
|
|
4790715cd3 | ||
|
|
e7e9c60042 | ||
|
|
1c3bc52cc4 | ||
|
|
5227dff0e1 | ||
|
|
33f0b5b7c2 | ||
|
|
0a02968303 | ||
|
|
f7bf658c07 | ||
|
|
8d16a0abad | ||
|
|
c974b97ca3 | ||
|
|
b8025bfebd | ||
|
|
30323b253f | ||
|
|
535c3ede96 | ||
|
|
89fed8ca33 | ||
|
|
f43c77aaed | ||
|
|
96c676b371 | ||
|
|
113047e1a2 | ||
|
|
abed57cb53 | ||
|
|
c01a800a6b | ||
|
|
d648832a2d | ||
|
|
f06833fbd2 | ||
|
|
c561addc94 | ||
|
|
702f5f1f4c | ||
|
|
1273f179e8 | ||
|
|
5d02f60bde | ||
|
|
4cf7a108e8 | ||
|
|
42635c3938 | ||
|
|
ed43dc842b | ||
|
|
49d4db6cd2 | ||
|
|
ea80ab2cae | ||
|
|
382e808b8d | ||
|
|
846befa7e0 | ||
|
|
74dd29f843 | ||
|
|
b0473bffcb | ||
|
|
24dd9ab1a7 | ||
|
|
49d3037e87 | ||
|
|
37ad2bd4e8 | ||
|
|
7d7b332b02 | ||
|
|
ac033b8612 | ||
|
|
a7b98dfe25 | ||
|
|
7fb7c86c46 | ||
|
|
ed036598a9 | ||
|
|
160bb70cdf | ||
|
|
c2e61f3c21 | ||
|
|
18218467f3 | ||
|
|
17e298ad2a | ||
|
|
d031a374f9 | ||
|
|
55f69c98cb | ||
|
|
71f2e4306d | ||
|
|
f8af23a025 | ||
|
|
4ef55a6cd3 | ||
|
|
312f866723 | ||
|
|
0ebe1f6dec | ||
|
|
2ad92e0e6e | ||
|
|
ac8823cdcf | ||
|
|
77565f7ee4 | ||
|
|
d656d90fa8 | ||
|
|
175b3b0834 | ||
|
|
7477e6b714 | ||
|
|
cd6568db69 | ||
|
|
6aff325fb2 | ||
|
|
0d603cfe9c | ||
|
|
34a1f14a17 | ||
|
|
efe1c8a070 | ||
|
|
1575844344 | ||
|
|
221ac1c208 | ||
|
|
57442db759 | ||
|
|
5fdb3e7cd6 | ||
|
|
96f259726c | ||
|
|
4936efba5e | ||
|
|
d5a3559a2f | ||
|
|
114a1c7f52 | ||
|
|
ce5265c203 | ||
|
|
1a575d926f | ||
|
|
85c818a39e | ||
|
|
4ffa2defe4 | ||
|
|
8825157fbb | ||
|
|
966d608dc5 | ||
|
|
b808c89471 | ||
|
|
75d4e6490f | ||
|
|
a82775f544 | ||
|
|
6a22ad0171 | ||
|
|
c854e88186 | ||
|
|
d02203060c | ||
|
|
cf703b0433 | ||
|
|
c0197a72d3 | ||
|
|
e5a543e283 | ||
|
|
b8b029b7d3 | ||
|
|
370f368b1a | ||
|
|
8288b45b4f | ||
|
|
fe529faf8e | ||
|
|
ab931b177d | ||
|
|
9aa3465513 | ||
|
|
6c70fc1a6c | ||
|
|
1ccc39962a | ||
|
|
99c941fc85 | ||
|
|
19729fdcc2 | ||
|
|
02e17998ce | ||
|
|
459e00c67a | ||
|
|
292f665650 | ||
|
|
93bbb79569 | ||
|
|
273e724f2b | ||
|
|
5d2615c56f | ||
|
|
bfaaf21330 | ||
|
|
dcb8415b7a | ||
|
|
699e1c75ce | ||
|
|
465b6e613e | ||
|
|
05fa105855 | ||
|
|
d7a0cdebe5 | ||
|
|
b049ab31eb | ||
|
|
6db4dcff7a | ||
|
|
3eeaef00ec | ||
|
|
8bf4c38a00 | ||
|
|
3a32b09ad1 | ||
|
|
6315982752 | ||
|
|
374a171e82 | ||
|
|
fc5d801f91 | ||
|
|
5146641848 | ||
|
|
cdd0ac42cf | ||
|
|
e5895500a2 | ||
|
|
9cb4dde3fa | ||
|
|
3c2a4370a5 | ||
|
|
e7a360dd6f | ||
|
|
c814c2fd35 | ||
|
|
fefa7fe262 | ||
|
|
26f01a29d1 | ||
|
|
169d4090ab | ||
|
|
0b43754d60 | ||
|
|
8b3b26b813 | ||
|
|
5426af4f81 | ||
|
|
4e2c3a579d | ||
|
|
5ae2693241 | ||
|
|
41c86b0d19 | ||
|
|
40788e8c3d | ||
|
|
0d29120033 | ||
|
|
4be598f865 | ||
|
|
558a6d509e | ||
|
|
75cd02aad2 | ||
|
|
e4c4451482 | ||
|
|
0671632477 | ||
|
|
54c230c264 | ||
|
|
64ba878eda | ||
|
|
01acd6dd76 | ||
|
|
9d819b52d3 | ||
|
|
37bac5cdc9 | ||
|
|
78c718c591 | ||
|
|
284b8bf6ca | ||
|
|
5a5084b837 | ||
|
|
3b8058e1f1 | ||
|
|
2a3168e0d6 | ||
|
|
a8ac6e4a15 | ||
|
|
6172cf9fba | ||
|
|
b728ec3909 | ||
|
|
61a53bbcff | ||
|
|
17d13dd084 | ||
|
|
edcb28d591 | ||
|
|
ad101119a7 | ||
|
|
bc36676d31 | ||
|
|
d76fe120ab | ||
|
|
2e95949b80 | ||
|
|
ae14d85e24 | ||
|
|
fad6304c60 | ||
|
|
a4dd3c8ce9 | ||
|
|
6d1a5d45e2 | ||
|
|
a6c7043e03 | ||
|
|
bcc400dafa | ||
|
|
8fbedf3441 | ||
|
|
2e8a9c9874 | ||
|
|
44fc41b3e5 | ||
|
|
7212c20a1b | ||
|
|
7ff142de1c | ||
|
|
e67efb199d | ||
|
|
20128bd04b | ||
|
|
c0fefdde28 | ||
|
|
f6ee160e66 | ||
|
|
06acc2004f | ||
|
|
43ac2ce4c8 | ||
|
|
b32bf72b5f | ||
|
|
c6880c957e | ||
|
|
095b71ed96 | ||
|
|
9160e496bc | ||
|
|
2a7ac78f02 | ||
|
|
64efa4627d | ||
|
|
f7e35569ce | ||
|
|
e8af32ec2b | ||
|
|
e092ce51f6 | ||
|
|
7b78edb1b7 | ||
|
|
b332e7090e | ||
|
|
67eb7723d6 | ||
|
|
251d138474 | ||
|
|
1170dfac05 | ||
|
|
4157f141c7 | ||
|
|
f569abd28a | ||
|
|
088f9687c0 | ||
|
|
e23df1f07a | ||
|
|
c818540dfd | ||
|
|
21365cbe1a | ||
|
|
5471a80a96 | ||
|
|
d7b6fa9cd0 | ||
|
|
dfdc2e02ef | ||
|
|
893ec9a302 | ||
|
|
05f65c38e6 | ||
|
|
2e9d062ec0 | ||
|
|
6b0b394e61 | ||
|
|
25621396c9 | ||
|
|
82aa0271f3 | ||
|
|
653cab13f8 | ||
|
|
b526f86b49 | ||
|
|
53c0f00888 | ||
|
|
f0c4d9de40 | ||
|
|
03ef8cec83 | ||
|
|
85f2a2e8c2 | ||
|
|
584b3e6642 | ||
|
|
39b7ef841d | ||
|
|
aa16a9098d | ||
|
|
7b8c2707bc | ||
|
|
60e26a31a7 | ||
|
|
3473c25c14 | ||
|
|
e52f022026 | ||
|
|
b1a7df8e43 | ||
|
|
0fd2479b7c | ||
|
|
273857f914 | ||
|
|
a08b85dbc8 | ||
|
|
a0aedf299a | ||
|
|
3c61426844 | ||
|
|
786f228076 | ||
|
|
004da28792 | ||
|
|
6e2be6efb6 | ||
|
|
a994dfcfbc | ||
|
|
7a8ea2ac93 | ||
|
|
0da3965d19 | ||
|
|
885fd7bb46 | ||
|
|
08771f9c89 | ||
|
|
8be48195a5 | ||
|
|
98ce2d650e | ||
|
|
3af327116a | ||
|
|
b75434db93 | ||
|
|
04e912aacd | ||
|
|
d7be352f87 | ||
|
|
96be3ec22c | ||
|
|
32e7e0d790 | ||
|
|
becc320e62 | ||
|
|
7666ed57d1 | ||
|
|
5e61d0955e | ||
|
|
e8a4662ae7 | ||
|
|
a48da3bd3b | ||
|
|
5f1a5d7b99 | ||
|
|
3e28a9db8f | ||
|
|
ebf6071d77 | ||
|
|
47a35fb9fb | ||
|
|
48e88aba44 | ||
|
|
b85f99c140 | ||
|
|
0a5e0e1f71 | ||
|
|
85dc22ebb7 | ||
|
|
5c21526009 | ||
|
|
14dff1cefc | ||
|
|
39fbb844f9 | ||
|
|
ca4e0c973a | ||
|
|
ecb42bee80 | ||
|
|
674ed2a9f3 | ||
|
|
252daf9717 | ||
|
|
196b8eaad3 | ||
|
|
8e526ba1bf | ||
|
|
19225828d9 | ||
|
|
7e594126be | ||
|
|
d2529e6334 | ||
|
|
97344f18e2 | ||
|
|
33934db629 | ||
|
|
6c6165c9f5 | ||
|
|
853460b20d | ||
|
|
cc4d9676c5 | ||
|
|
1cf1b819f4 | ||
|
|
f916c66d2b | ||
|
|
550aa86b45 | ||
|
|
014e764758 | ||
|
|
d1fc28432b | ||
|
|
879576f0a2 | ||
|
|
69098210be | ||
|
|
99df4f892d | ||
|
|
7bc04fbad3 | ||
|
|
8a74ce578d | ||
|
|
0805e4e5de | ||
|
|
f1060fc88e | ||
|
|
7d3d3d0a3a | ||
|
|
40377032e3 | ||
|
|
b2971edd7d | ||
|
|
c37d723692 | ||
|
|
30f9026e1d | ||
|
|
332286072e | ||
|
|
d6da172a2a | ||
|
|
ebfe584afc | ||
|
|
6250023583 | ||
|
|
6b4f3d63b8 | ||
|
|
56db773a09 | ||
|
|
fc6c472401 | ||
|
|
2cd42a6866 | ||
|
|
36a90c345c | ||
|
|
ef1e82c72c | ||
|
|
88f9534685 | ||
|
|
68254a052a | ||
|
|
2425b3a166 | ||
|
|
5524ed753b | ||
|
|
89711723da | ||
|
|
bed2740ffd | ||
|
|
751d633c3d | ||
|
|
45952cbdf2 | ||
|
|
b355dd7b23 | ||
|
|
48a186f172 | ||
|
|
39dc7ec2ab | ||
|
|
2fedabd3b9 | ||
|
|
6d719e9480 | ||
|
|
05e278afda | ||
|
|
87dbf462cb | ||
|
|
40e896bc5b | ||
|
|
3e940f80c7 | ||
|
|
dbf2888d43 | ||
|
|
d412355324 | ||
|
|
178732217f | ||
|
|
de17b95c3d | ||
|
|
d14e774525 | ||
|
|
ca5402a7fa | ||
|
|
7a6fa7c5b4 | ||
|
|
da36c286a6 | ||
|
|
d3901bcf2e | ||
|
|
94c8d4fdfb | ||
|
|
ab8bdc18bb | ||
|
|
c9dcd7442a | ||
|
|
34c8f13346 | ||
|
|
7a8ccda95c | ||
|
|
44a1448542 | ||
|
|
c87d89ffaf | ||
|
|
0868749d42 | ||
|
|
1d40ee23f0 | ||
|
|
8893f32603 | ||
|
|
adcf7e8dc3 | ||
|
|
901f7c5c36 | ||
|
|
775bb413b3 | ||
|
|
64cd5b5a46 | ||
|
|
ae356609b1 | ||
|
|
6102a5d2b0 | ||
|
|
f8782ee2d7 | ||
|
|
6181ec4c77 | ||
|
|
e0e7a685ef | ||
|
|
ae1f8cdad2 | ||
|
|
a4cf792e6d | ||
|
|
89109ded53 | ||
|
|
e20e52a4b2 | ||
|
|
20c4b1cbec | ||
|
|
5238b0241d | ||
|
|
9cdf6c203d | ||
|
|
839335cae6 | ||
|
|
a99b2ce167 | ||
|
|
b695141d87 | ||
|
|
92d5c9f866 | ||
|
|
7f18a1ffe0 | ||
|
|
8c3fdaaa62 | ||
|
|
5ac1c69710 | ||
|
|
de2d5fba63 | ||
|
|
33d516748f | ||
|
|
de17f6f0fd | ||
|
|
756731fc02 | ||
|
|
e46be0415f | ||
|
|
aa02fb50bf | ||
|
|
8b6cd9c772 | ||
|
|
cdd0d3351a | ||
|
|
8b6d584529 | ||
|
|
f49fdd4141 | ||
|
|
b26e1be81a | ||
|
|
bacab38d7f | ||
|
|
701c05ce96 | ||
|
|
438c452585 | ||
|
|
0a7a1eff3f | ||
|
|
87e743e381 | ||
|
|
a03f1b3d55 | ||
|
|
2d8dc3d243 | ||
|
|
b982232cc5 | ||
|
|
61c8d728ac | ||
|
|
851a2bf855 | ||
|
|
e0bdde3630 | ||
|
|
6a0dcd7f0e | ||
|
|
75f0b4c879 | ||
|
|
db536a9504 | ||
|
|
0fb114dede | ||
|
|
e703342179 | ||
|
|
35c8f4a611 | ||
|
|
7c89ae44a9 | ||
|
|
84fe06da22 | ||
|
|
806318c8b3 | ||
|
|
3aac2e1822 | ||
|
|
168baef433 | ||
|
|
6dba6cd78d | ||
|
|
502250d08f | ||
|
|
7395f0e680 | ||
|
|
494d3fdaca | ||
|
|
7b86a157de | ||
|
|
0988c41785 | ||
|
|
522db1bf01 | ||
|
|
06f066f90d | ||
|
|
f37b20677b | ||
|
|
cd2eac1032 | ||
|
|
8ac38d58d7 | ||
|
|
4c80cc313a | ||
|
|
1c65fee9b4 | ||
|
|
90dda7edc1 | ||
|
|
da054fae20 | ||
|
|
bdb6611e30 | ||
|
|
9284f973f1 | ||
|
|
2bfd64c3c9 | ||
|
|
939d24cce5 | ||
|
|
27b0183c46 | ||
|
|
d14efacac7 | ||
|
|
150a002c40 | ||
|
|
ce0def3bd8 | ||
|
|
ee20fa97c2 | ||
|
|
7403b7d700 | ||
|
|
87ef173e0a | ||
|
|
52a3fb6bc7 | ||
|
|
92e2a257a6 | ||
|
|
32e175752c | ||
|
|
d43f7180dc | ||
|
|
0129c2b0fc | ||
|
|
4ed1990001 | ||
|
|
5bd6ab27ae | ||
|
|
f3593b89fa | ||
|
|
23d84b2310 | ||
|
|
fdc49402ec | ||
|
|
5457c133e1 | ||
|
|
292e588ee3 | ||
|
|
243494c25e | ||
|
|
e4365f3706 | ||
|
|
310f3038d3 | ||
|
|
4e6033273d | ||
|
|
73718586d3 | ||
|
|
011abe61e8 | ||
|
|
fe3a37f89d | ||
|
|
8aea44e77b | ||
|
|
5529aec0d6 | ||
|
|
369549d23f | ||
|
|
181ea9a381 | ||
|
|
76b8f2854e | ||
|
|
320e5198f9 | ||
|
|
e522539e2d | ||
|
|
7c996b83d2 | ||
|
|
3dd354d7aa | ||
|
|
f4ad6e2157 | ||
|
|
8b170dc2bf | ||
|
|
dcb9d779bf | ||
|
|
80f736d670 | ||
|
|
8502c6da3c | ||
|
|
b131449422 | ||
|
|
6eebc4a620 | ||
|
|
4661ab1179 | ||
|
|
86046445ed | ||
|
|
baea9bf944 | ||
|
|
0951ee9e63 | ||
|
|
5492528287 | ||
|
|
14dbd220c2 | ||
|
|
babc890c59 | ||
|
|
6f7b47ff40 | ||
|
|
3991f03202 | ||
|
|
27271d5da7 | ||
|
|
627312e1de | ||
|
|
bfc9550e4e | ||
|
|
2b9c21268b | ||
|
|
3dce4ed6f1 | ||
|
|
0f16c2ea87 | ||
|
|
9a635f0686 | ||
|
|
6a0d4b2baa | ||
|
|
ac017098ad | ||
|
|
98fef2640d | ||
|
|
8bb66e133a | ||
|
|
68a582901d | ||
|
|
c094f4c06e | ||
|
|
f7ca545544 | ||
|
|
69b4716894 | ||
|
|
7e44dcc5bf | ||
|
|
ab9843e183 | ||
|
|
01af706ade | ||
|
|
9ebdb08e99 | ||
|
|
a74ffe25d9 | ||
|
|
7f95e27707 | ||
|
|
1facf5bba3 | ||
|
|
03d77009eb | ||
|
|
8afd6812b5 | ||
|
|
ec9ad78fcf | ||
|
|
6f4e93dc90 | ||
|
|
a38e43862d | ||
|
|
39294bb037 | ||
|
|
edc5e59b78 | ||
|
|
c00fd9fd37 | ||
|
|
b3e621dd9f | ||
|
|
6e8c49b978 | ||
|
|
398d57133d | ||
|
|
16521a6feb | ||
|
|
3ca0b37a3e | ||
|
|
cf2ec1229d | ||
|
|
fe9b1e5f9b | ||
|
|
f5b96ddf01 | ||
|
|
2fe076fb27 | ||
|
|
99249cff04 | ||
|
|
0cdf7b0613 | ||
|
|
90bcf4f157 | ||
|
|
03c3ec4e12 | ||
|
|
ca9bb20d64 | ||
|
|
c6bc078fd9 | ||
|
|
2f4bd6e52c | ||
|
|
2affe53727 | ||
|
|
09654d7dd8 | ||
|
|
90a4e37815 | ||
|
|
60889c0c79 | ||
|
|
20f3408d96 | ||
|
|
e9d86789db | ||
|
|
5152b7c66c | ||
|
|
c494c4e12c | ||
|
|
54d58ccb7e | ||
|
|
714a77bfbe | ||
|
|
d48f8bf5cc | ||
|
|
99d97754a6 | ||
|
|
b9d437de2a | ||
|
|
11403f2019 | ||
|
|
1ca102d639 | ||
|
|
339ba55111 | ||
|
|
14ae59885a | ||
|
|
e3ef54f99b | ||
|
|
001901f9a9 | ||
|
|
6a98f60e2e | ||
|
|
6f2e24c47d | ||
|
|
aafa368923 | ||
|
|
eb783cab4c | ||
|
|
6533aa865a | ||
|
|
f1a1e1bc07 | ||
|
|
953f4838dd | ||
|
|
130b892d34 | ||
|
|
6ad525c77e | ||
|
|
d0ca74ad27 | ||
|
|
9806f69b4d | ||
|
|
34d9b5e3d7 | ||
|
|
3bf5189d86 | ||
|
|
12e5b0681b | ||
|
|
8c0285d608 | ||
|
|
36558fa3b8 | ||
|
|
235f940cde | ||
|
|
803d61fcbc | ||
|
|
ffbd7d8de4 | ||
|
|
4ed924d7c7 | ||
|
|
798dc9948b | ||
|
|
13515f7ee4 | ||
|
|
ef80824c26 | ||
|
|
c8503fd65e | ||
|
|
b3c454fb1c | ||
|
|
1d7723e873 | ||
|
|
77100b2365 | ||
|
|
259a788134 | ||
|
|
39511455cb | ||
|
|
b04c16178e | ||
|
|
49a959c06e | ||
|
|
096a8932b4 | ||
|
|
e39e66df93 | ||
|
|
513633f49a | ||
|
|
eb3740daaf | ||
|
|
f7947b148a | ||
|
|
9a2a702f3f | ||
|
|
c65d95bf29 | ||
|
|
753a5edc4f | ||
|
|
0b3f853c2d | ||
|
|
3527fcf1d5 | ||
|
|
4544a89c7a | ||
|
|
ffeae9005e | ||
|
|
47217bcfb7 | ||
|
|
80ff58b57a | ||
|
|
d15dd368f1 | ||
|
|
8a2ec32bd8 | ||
|
|
410496ed52 | ||
|
|
b7b07552e5 | ||
|
|
44486e80d9 | ||
|
|
7890c527d8 | ||
|
|
2c82ab79a7 | ||
|
|
e3ebe5fc53 | ||
|
|
0ac430892e | ||
|
|
a7739c942c | ||
|
|
24581482d0 | ||
|
|
0571c3b453 | ||
|
|
73e7f5a0b0 | ||
|
|
20c0adb961 | ||
|
|
a01e03562f | ||
|
|
d184ed0130 | ||
|
|
089e1c2aee | ||
|
|
ebab0e91ee | ||
|
|
858a2b1b88 | ||
|
|
02bd59827c | ||
|
|
4991428510 | ||
|
|
3b245f5dc1 | ||
|
|
c9c81da901 | ||
|
|
4919cdc3fb | ||
|
|
e90e1f577d | ||
|
|
afd4284403 | ||
|
|
150b350d31 | ||
|
|
2818520bd1 | ||
|
|
2819952292 | ||
|
|
5af71af51c | ||
|
|
07a55b51df | ||
|
|
66dd68b49d | ||
|
|
9812657777 | ||
|
|
0b09312fc6 | ||
|
|
d0a7ac6b74 | ||
|
|
ff9a238fbd | ||
|
|
359fffa5f1 | ||
|
|
5bf92ced1a | ||
|
|
340bcc7b45 | ||
|
|
ef03742bd4 | ||
|
|
20431ec16d | ||
|
|
becba8157b | ||
|
|
51fd3bb0eb | ||
|
|
4bbd3acb4e | ||
|
|
3bc930ea7b | ||
|
|
d1b26f8e86 | ||
|
|
fdf15caaff | ||
|
|
c7b4a53c0b | ||
|
|
af78dc0308 | ||
|
|
5ad39493c4 | ||
|
|
61f597b408 | ||
|
|
2162825240 | ||
|
|
2b780e70d1 | ||
|
|
a3823f818e | ||
|
|
1f7c47bcaf | ||
|
|
ec53c365a2 | ||
|
|
793ad1f2d4 | ||
|
|
9bc733b76c | ||
|
|
21b28f0217 | ||
|
|
d3e23caa52 | ||
|
|
9e7518de67 | ||
|
|
679f0047aa | ||
|
|
d77d5ce14b | ||
|
|
33ec22a2af | ||
|
|
353053225f | ||
|
|
b7f3d6f7f7 | ||
|
|
e34577499d | ||
|
|
4cf8960c0c | ||
|
|
1f93ea0675 | ||
|
|
25b705c3a8 | ||
|
|
0725588731 | ||
|
|
fc5c61cc8b | ||
|
|
ac282e63c6 | ||
|
|
c3941941ce | ||
|
|
46cdd53323 | ||
|
|
3ff3e302c3 | ||
|
|
f2ceecf95c | ||
|
|
9314c7c881 | ||
|
|
54abb2c572 | ||
|
|
8fa3bdd025 | ||
|
|
5e7a308528 | ||
|
|
7952177786 | ||
|
|
9afbe49c84 | ||
|
|
9f06ba2db3 | ||
|
|
fe55bfddcf | ||
|
|
c0842e6444 | ||
|
|
3fed20d06a | ||
|
|
5e8f2e2c04 | ||
|
|
e4df99ea84 | ||
|
|
b3276f5f11 | ||
|
|
32667ca256 | ||
|
|
bed122a170 | ||
|
|
14adc9b875 | ||
|
|
a8778bbc5a | ||
|
|
a54e641f44 | ||
|
|
5c99efe87a | ||
|
|
7da1d731ff | ||
|
|
af9828e819 | ||
|
|
7a27136142 | ||
|
|
012ad2d423 | ||
|
|
ef3bdbf4da | ||
|
|
b3bb698f7b | ||
|
|
1ed5d1e4c1 | ||
|
|
bdee01a03d | ||
|
|
458f7376d7 | ||
|
|
cb3a00e027 | ||
|
|
482eb1f3fb | ||
|
|
6e0f638f5e | ||
|
|
bab349047d | ||
|
|
28ea6b8de8 | ||
|
|
9d51bbdae8 | ||
|
|
d622f79533 | ||
|
|
04c8515ad1 | ||
|
|
53bc4251d1 | ||
|
|
a5a751f02f | ||
|
|
66ed5f82c4 | ||
|
|
c802a9e6aa | ||
|
|
880f210946 | ||
|
|
4f9f7eb6a6 | ||
|
|
f910c4a8e7 | ||
|
|
529686d965 | ||
|
|
84dfd1536f | ||
|
|
85dedc324c | ||
|
|
d639237411 | ||
|
|
449aaf75f1 | ||
|
|
b1fda66caa | ||
|
|
66a8e90fd9 | ||
|
|
37b487d191 | ||
|
|
6c59fe3577 | ||
|
|
1cbb70c992 | ||
|
|
e06b39f882 | ||
|
|
2602b1493e | ||
|
|
989d14502d | ||
|
|
f78a550282 | ||
|
|
54a1abb284 | ||
|
|
97b492a8e2 | ||
|
|
0873bd14a9 | ||
|
|
eff6ba429a | ||
|
|
8c18064be4 | ||
|
|
44a1ac0cf3 | ||
|
|
28dc8d88dd | ||
|
|
2c0c2b64ba | ||
|
|
bd3e0f5248 | ||
|
|
cd52d98938 | ||
|
|
894c70e7f8 | ||
|
|
51d70c2edd | ||
|
|
7d4b355240 | ||
|
|
3b56193b98 | ||
|
|
b16045b57d | ||
|
|
9e8b0fca5b | ||
|
|
35cf1b3b5b | ||
|
|
83f788af57 | ||
|
|
2ffe378d3f | ||
|
|
38b33a4a5e | ||
|
|
60bf9ed0a0 | ||
|
|
16adf4de1b | ||
|
|
80de983023 | ||
|
|
8703ca623f | ||
|
|
286253a73f | ||
|
|
bd806a41df | ||
|
|
b89c4e9002 | ||
|
|
6dbf31c0c3 | ||
|
|
060c45d8a1 | ||
|
|
33d3e82e4d | ||
|
|
4bb074514d | ||
|
|
e3f8892003 | ||
|
|
9d00ad5f18 | ||
|
|
dae4344850 | ||
|
|
aa7f3fabe2 | ||
|
|
f93434a8ce | ||
|
|
25dee56be9 | ||
|
|
ce9a3f3797 | ||
|
|
11e384920a | ||
|
|
a0a1f1e536 | ||
|
|
3b3d0ea9eb | ||
|
|
2f4d78286d | ||
|
|
677dc6f985 | ||
|
|
d52057e732 | ||
|
|
fa2a1cb1fb | ||
|
|
19a0fb04ad | ||
|
|
947352f2fe | ||
|
|
adcbedb686 | ||
|
|
7732f92acd | ||
|
|
ad8a001688 | ||
|
|
9121eada08 | ||
|
|
49bd4d25a2 | ||
|
|
d80b4129c6 | ||
|
|
7edb4172d5 | ||
|
|
c3a4677990 | ||
|
|
5cbb893a3b | ||
|
|
f28a2a432b | ||
|
|
03b75a2d27 | ||
|
|
859fe69083 | ||
|
|
f6f2205ddb | ||
|
|
0f9a03ef61 | ||
|
|
9aa417c084 | ||
|
|
7b70952f5d | ||
|
|
edd3d07b49 | ||
|
|
5293d0a4ec | ||
|
|
3c8c7beae1 | ||
|
|
9c3ba9fdcd | ||
|
|
fb1748fb0f | ||
|
|
0a109fbd03 | ||
|
|
5cf64db74e | ||
|
|
488cc94f36 | ||
|
|
e15846bf79 | ||
|
|
752bd00674 | ||
|
|
7fadfcbe32 | ||
|
|
41141e75bb | ||
|
|
50f641e627 | ||
|
|
c7883fd093 | ||
|
|
4fcb24b2b1 | ||
|
|
5003557935 | ||
|
|
bdf1ba84da | ||
|
|
b0b4def983 | ||
|
|
cc184bbe9e | ||
|
|
ad30c830aa | ||
|
|
1d791a8af4 | ||
|
|
e63c51cd97 | ||
|
|
f202e32908 | ||
|
|
26e1a08e82 | ||
|
|
4d5119d435 | ||
|
|
75e34ea62e | ||
|
|
0a183d6274 | ||
|
|
21d8060aea | ||
|
|
9cbe906f60 | ||
|
|
8ce4137399 | ||
|
|
5f8a139347 | ||
|
|
9bb009a3fe | ||
|
|
726d65923f | ||
|
|
8a6be4cb2d | ||
|
|
10b06beb8e | ||
|
|
81318c7968 | ||
|
|
47a2c1c6e5 | ||
|
|
39cee65c6b | ||
|
|
8582ec724e | ||
|
|
b0139682e8 | ||
|
|
d39c475a6d | ||
|
|
48f38354c6 | ||
|
|
cd5a920ed5 | ||
|
|
71bc1f378d | ||
|
|
0ee6c31cff | ||
|
|
af89a9971e | ||
|
|
c718a8ef72 | ||
|
|
8c8ad0faf0 | ||
|
|
314d5bbb7f | ||
|
|
102255757a | ||
|
|
914067a0d0 | ||
|
|
06e3ae2536 | ||
|
|
7f9b252556 | ||
|
|
3d700e243f | ||
|
|
bcfc78ce11 | ||
|
|
09241765d5 | ||
|
|
671c83c265 | ||
|
|
772d28b766 | ||
|
|
c26fcea58d | ||
|
|
1e5e26dbff | ||
|
|
742fc54864 | ||
|
|
49738f43c0 | ||
|
|
9f85f61010 | ||
|
|
239f422039 | ||
|
|
67af3c37be | ||
|
|
a9442385c4 | ||
|
|
8c9cd10b8b | ||
|
|
72542059dd | ||
|
|
a843fc6d40 | ||
|
|
4beed60c08 | ||
|
|
4049c1e480 | ||
|
|
8449314da2 | ||
|
|
63ad057028 | ||
|
|
e720464330 | ||
|
|
24036afef9 | ||
|
|
c78fa1a1bc | ||
|
|
faa8b9022c | ||
|
|
729bafef7a | ||
|
|
590b028632 | ||
|
|
8150d00f36 | ||
|
|
060065926f | ||
|
|
70babe8a28 | ||
|
|
c36e09664f | ||
|
|
a9672246f3 | ||
|
|
ff571884e9 | ||
|
|
475138bceb | ||
|
|
4a8af199c2 | ||
|
|
bdabf5db72 | ||
|
|
6a5f21b34e | ||
|
|
d608be103c | ||
|
|
374bb5d18a | ||
|
|
031d6c25ff | ||
|
|
223fb7b075 | ||
|
|
a746741971 | ||
|
|
120faf2a58 | ||
|
|
990bca0dc6 | ||
|
|
3406472db7 | ||
|
|
1bd733c9f6 | ||
|
|
238c7f982e | ||
|
|
fcb81147cb | ||
|
|
1915b73783 | ||
|
|
ee79e621fb | ||
|
|
d203275a3b | ||
|
|
9e8a996222 | ||
|
|
0126b0b3ed | ||
|
|
458928612c | ||
|
|
e33f88e28d | ||
|
|
be570bbf9e | ||
|
|
f59b4be110 | ||
|
|
37336e41be | ||
|
|
d24a1a3f0a | ||
|
|
f7258955bd | ||
|
|
2a1eae5d6f | ||
|
|
50ee0a4adb | ||
|
|
955a26584e | ||
|
|
1d3e407c8f | ||
|
|
cb809c4596 | ||
|
|
53bbe2888e | ||
|
|
7246f476a5 | ||
|
|
0785d1c390 | ||
|
|
85d2c49d14 | ||
|
|
8b77d62b7f | ||
|
|
373058a32a | ||
|
|
e6293c2c8c | ||
|
|
eff181c959 | ||
|
|
54752c2305 | ||
|
|
b4753c044f | ||
|
|
26493424ae | ||
|
|
0282fd1332 | ||
|
|
b9a019a08b | ||
|
|
66f6a0e687 | ||
|
|
2dd1b9f97d | ||
|
|
89615f3045 | ||
|
|
7e46192f67 | ||
|
|
e78d985cdf | ||
|
|
e8c4bf56fe | ||
|
|
e6aa7d323d | ||
|
|
fca8e25929 | ||
|
|
8e8ac286b4 | ||
|
|
7d9770b9a2 | ||
|
|
1996230460 | ||
|
|
de7897a864 | ||
|
|
e2884dcdb7 | ||
|
|
544a53a42b | ||
|
|
2e4787bfc8 | ||
|
|
1829eeb171 | ||
|
|
c7488e3c4a | ||
|
|
3bf9606383 | ||
|
|
4f43f18f0a | ||
|
|
5b7f197397 | ||
|
|
018141c97f | ||
|
|
4d7813e57c | ||
|
|
605c60208f | ||
|
|
884fafcc30 | ||
|
|
56baa90320 | ||
|
|
6bb20ee09e | ||
|
|
541356430c | ||
|
|
2f4d91fd69 | ||
|
|
f58c5e6b30 | ||
|
|
0311d0132c | ||
|
|
c946c97402 | ||
|
|
84a6f51318 | ||
|
|
24a1501b0d | ||
|
|
383b6f5fcc | ||
|
|
633dd7ff9b | ||
|
|
580624fad6 | ||
|
|
a8190f7efa | ||
|
|
dd2157534b | ||
|
|
38a90e7669 | ||
|
|
6bfc526dcd | ||
|
|
aadb8a7405 | ||
|
|
27082bf77e | ||
|
|
a2903c80cd | ||
|
|
9a77c5369c | ||
|
|
3c30741a19 | ||
|
|
7028ad4ec0 | ||
|
|
8de750c6aa | ||
|
|
04f98de9ee | ||
|
|
a1a019784b | ||
|
|
4aeeae77bd | ||
|
|
651cfc2b78 | ||
|
|
2ef8af25e2 | ||
|
|
0b13852a5b | ||
|
|
13427578c9 | ||
|
|
d89ca2087e | ||
|
|
8b0ea9fba6 | ||
|
|
9f0b653d5a | ||
|
|
659a339233 | ||
|
|
4c29f177a0 | ||
|
|
d664e63d55 | ||
|
|
2493509dbe | ||
|
|
1c8b27f554 | ||
|
|
68297b7186 | ||
|
|
34dd8d0a91 | ||
|
|
81c44790d5 | ||
|
|
d557b335cf | ||
|
|
e2adc28cff | ||
|
|
0fef6a6ecc | ||
|
|
f2fd4b8a1f | ||
|
|
95bd5605a8 | ||
|
|
497cca7eca | ||
|
|
54f78feedd | ||
|
|
76408e53ae | ||
|
|
be19e74d30 | ||
|
|
dac578a775 | ||
|
|
04732ce74b | ||
|
|
a6c95a2374 | ||
|
|
f68622abe9 | ||
|
|
83a9a7bdb2 | ||
|
|
6500afc0ca | ||
|
|
c69b7ecc96 | ||
|
|
615ef1e2d2 | ||
|
|
cf69a0cd7f | ||
|
|
06e892fb33 | ||
|
|
e6c5dd6865 | ||
|
|
247efdebdb | ||
|
|
76f3792287 | ||
|
|
64d8e2c727 | ||
|
|
ead0bd9cb0 | ||
|
|
66fc13b2ec | ||
|
|
f3af4128b0 | ||
|
|
0e43107c87 | ||
|
|
1ee3e7997e | ||
|
|
50fd61d91f | ||
|
|
e4cdc051a9 | ||
|
|
778e846e96 | ||
|
|
a27759b647 | ||
|
|
b75eceab41 | ||
|
|
e748a5d5f4 | ||
|
|
99c5a3ae46 | ||
|
|
51da710f5a | ||
|
|
569d69b3d2 | ||
|
|
059a6b1d90 | ||
|
|
990af7548a | ||
|
|
a38aefdfc8 | ||
|
|
3bcb12e7d1 | ||
|
|
7904ecb462 | ||
|
|
9ba4d45109 | ||
|
|
56b8afe19d | ||
|
|
f7aed9a94c | ||
|
|
e12a7e881d | ||
|
|
5afb65325d | ||
|
|
135f520f32 | ||
|
|
bc251f4ff6 | ||
|
|
b8769751f6 | ||
|
|
eff96d839e | ||
|
|
aa34c23807 | ||
|
|
195acdac8c | ||
|
|
903e03c56c | ||
|
|
0892767b8a | ||
|
|
83ebfa772c | ||
|
|
1583641322 | ||
|
|
9510e2c256 | ||
|
|
a9dbabe07e | ||
|
|
12884008fa | ||
|
|
02543bad1c | ||
|
|
a8c56a5251 | ||
|
|
4e5a855f3f | ||
|
|
7e497a951e | ||
|
|
cd08eabbfa | ||
|
|
f7e62d9f81 | ||
|
|
9a3761e86e | ||
|
|
3619a68693 | ||
|
|
efaf3c3bf9 | ||
|
|
0e4e6a6f67 | ||
|
|
42458e6278 | ||
|
|
41ec995377 | ||
|
|
4f37599326 | ||
|
|
4144520e5c | ||
|
|
6c4800546c | ||
|
|
733733c8a7 | ||
|
|
2aa67cc946 | ||
|
|
9385981a9d | ||
|
|
fff780035d | ||
|
|
46127e673d | ||
|
|
70df59b224 | ||
|
|
0fdbaa803f | ||
|
|
6af1830eff | ||
|
|
6f860e2bd5 | ||
|
|
20a492f7ee | ||
|
|
63875e7591 | ||
|
|
0ad98cabde | ||
|
|
668879d2e1 | ||
|
|
2e09783302 | ||
|
|
49734114b3 | ||
|
|
950d9d6ee7 | ||
|
|
f7974aee2e | ||
|
|
c870a82621 | ||
|
|
984929a001 | ||
|
|
7f9e2c1db8 | ||
|
|
324e8389dc | ||
|
|
6f448c5a38 | ||
|
|
ec43efbb20 | ||
|
|
3ed065de37 | ||
|
|
8152f0d72c | ||
|
|
f8047f4736 | ||
|
|
b93c66dc2d | ||
|
|
ac877b3065 | ||
|
|
dee8abfdde | ||
|
|
cef3841d73 | ||
|
|
3cd5e8a041 | ||
|
|
515b5f866e | ||
|
|
321f62bf92 | ||
|
|
f94fa47b52 | ||
|
|
c502f8a722 | ||
|
|
59b4868ac3 | ||
|
|
3634e12cce | ||
|
|
6d45445391 | ||
|
|
4f47e268cc | ||
|
|
0035b31cdb | ||
|
|
f2565aee03 | ||
|
|
5bd85668dd | ||
|
|
20f990b6ce | ||
|
|
6821379586 | ||
|
|
73b040eb49 | ||
|
|
49aa4b2e1e | ||
|
|
972241c74c | ||
|
|
680750e3c2 | ||
|
|
5e7d4d9d15 | ||
|
|
1e57e60613 | ||
|
|
3ac7ce605a | ||
|
|
b720dea9f0 | ||
|
|
c80722aefe | ||
|
|
a84fa69f28 | ||
|
|
e33781e59f | ||
|
|
8824bc7ece | ||
|
|
c2e3b0e448 | ||
|
|
f61a38e85a | ||
|
|
d23e948216 | ||
|
|
58bdaa31f0 | ||
|
|
b6491d88a6 | ||
|
|
f6061ba62e | ||
|
|
427899ddce | ||
|
|
c4ab7d2dbd | ||
|
|
0fd2ba033f | ||
|
|
ed38939a93 | ||
|
|
c7ee26ce5a | ||
|
|
909b8cb303 | ||
|
|
b0277370cf | ||
|
|
2ec8656bea | ||
|
|
b2ef256910 | ||
|
|
63d6ce95db | ||
|
|
a9532b189c | ||
|
|
844545411f | ||
|
|
4e23a2b9b8 | ||
|
|
5deba027eb | ||
|
|
fc8b7efc6f | ||
|
|
a1c2d9c0f3 | ||
|
|
4ca49a0501 | ||
|
|
493c53d090 | ||
|
|
b27e956d35 | ||
|
|
35ebed75c6 | ||
|
|
7bfdb5f77f | ||
|
|
8d8c02317f | ||
|
|
a34482feab | ||
|
|
cbdc8fd4a6 | ||
|
|
8d3afaa53c | ||
|
|
7ced9ef3df | ||
|
|
e8a9ae7e80 | ||
|
|
73a88ab3d3 | ||
|
|
aaed82738a | ||
|
|
de7f7b96db | ||
|
|
1a669b3e68 | ||
|
|
333af9b13a | ||
|
|
a5bca5e240 | ||
|
|
c885633e02 | ||
|
|
ca7e20b7ca | ||
|
|
545e11a3d7 | ||
|
|
44f5287664 | ||
|
|
cf510897f1 | ||
|
|
1d171345f8 | ||
|
|
4fa7e1cd49 | ||
|
|
acd008298e | ||
|
|
83a8021515 | ||
|
|
cf88dfb1db | ||
|
|
8937c4b481 | ||
|
|
cc6af10a4d | ||
|
|
6d94578955 | ||
|
|
08442ab71e | ||
|
|
10d91d213f | ||
|
|
b7a3b06994 | ||
|
|
5f12c37f23 | ||
|
|
585edebccd | ||
|
|
9921c62234 | ||
|
|
1ac76d2e16 | ||
|
|
6e983bf400 | ||
|
|
6a8fd4fa6e | ||
|
|
3698eaa2d2 | ||
|
|
8d97ca433c | ||
|
|
23cc65e537 | ||
|
|
2f5a3c2bbe | ||
|
|
f6485616cd | ||
|
|
6544fb43d9 | ||
|
|
a954b32dcc | ||
|
|
426dc7836c | ||
|
|
ff941ffc16 | ||
|
|
a063c201df | ||
|
|
e2be3fa0aa | ||
|
|
609da6fb50 | ||
|
|
fc9f3ccec3 | ||
|
|
f7baa67a0a | ||
|
|
e8d78c2cdb | ||
|
|
9d33366092 | ||
|
|
f5d61515c2 | ||
|
|
711a04a972 | ||
|
|
e5b470a3f1 | ||
|
|
31820e1e22 | ||
|
|
4849e8cd6d | ||
|
|
77e3b460aa | ||
|
|
b5321001f8 | ||
|
|
38eba9f5ea | ||
|
|
ea6f399454 | ||
|
|
f8bf2d7b7d | ||
|
|
c4856caebb | ||
|
|
fc1030bb22 | ||
|
|
9eb6cad8dc | ||
|
|
0fa2a78dce | ||
|
|
a56fa1558b | ||
|
|
261c73a997 | ||
|
|
929c1333ca | ||
|
|
286a79d94d | ||
|
|
8b951f99da | ||
|
|
abb449bca0 | ||
|
|
bd084028d1 | ||
|
|
138a27570b | ||
|
|
c2ed40a74f | ||
|
|
a7e7a00cab | ||
|
|
64a31ab3cd | ||
|
|
71958bc0f1 | ||
|
|
366ec35612 | ||
|
|
3738f6e8ae | ||
|
|
051a8e2af1 | ||
|
|
2f43f28d5e | ||
|
|
b64769754b | ||
|
|
a97daa18d1 | ||
|
|
b6556dce8b | ||
|
|
aa8d8bc8b5 | ||
|
|
0800dcfdc4 | ||
|
|
12b0101e94 | ||
|
|
021b391a02 | ||
|
|
d11e2b6057 | ||
|
|
264d90e7e5 | ||
|
|
f9f3da9e78 | ||
|
|
6435b49153 | ||
|
|
f9aa2941cf | ||
|
|
5a933d4bee | ||
|
|
5536aea0df | ||
|
|
976666d216 | ||
|
|
9a5bcd4392 | ||
|
|
812060a118 | ||
|
|
089b5052e6 | ||
|
|
874e5d72f4 | ||
|
|
6b11de1329 | ||
|
|
2245a7ad8d | ||
|
|
ee5ec1b870 | ||
|
|
74ccfe851b | ||
|
|
e1c24bd5a2 | ||
|
|
1349b79728 | ||
|
|
d294d7604c | ||
|
|
01df2cf464 | ||
|
|
45b7322488 | ||
|
|
b3055e992f | ||
|
|
3da548565c | ||
|
|
a975e85548 | ||
|
|
c4b5ade752 | ||
|
|
a4b61b0794 | ||
|
|
f6011184b8 | ||
|
|
74de118c6e | ||
|
|
9c25e77c17 | ||
|
|
440113e67e | ||
|
|
a11b60c445 | ||
|
|
a6052681ad | ||
|
|
482d50536a | ||
|
|
25c79a4fcd | ||
|
|
02946144ac | ||
|
|
71a360e9a3 | ||
|
|
f7912d88b1 | ||
|
|
975101d7d2 | ||
|
|
ef58c5ff55 | ||
|
|
e10221804a | ||
|
|
284ed9ee0e | ||
|
|
5d7b961997 | ||
|
|
c699a5c4b4 | ||
|
|
1f4ceb89cf | ||
|
|
0934ca0040 | ||
|
|
4738f892c2 | ||
|
|
33004fcf33 | ||
|
|
34d214c166 | ||
|
|
a56cd92a1e | ||
|
|
7251348507 | ||
|
|
01cd5c84d6 | ||
|
|
e210599fa6 | ||
|
|
dbe7cee7e9 | ||
|
|
7370d88ceb | ||
|
|
34458e0c57 | ||
|
|
05c8c3abf2 | ||
|
|
e9d464b4d3 | ||
|
|
6968c3ab9b | ||
|
|
131a8a9650 | ||
|
|
379ecbf9a9 | ||
|
|
7b9dfa9a28 | ||
|
|
fbd0f5eed2 | ||
|
|
5970f904ae | ||
|
|
8cbcb2868d | ||
|
|
8ff2a4b026 | ||
|
|
ae14d205a5 | ||
|
|
ec5d560ec5 | ||
|
|
fb543b53c0 | ||
|
|
39c16422e2 | ||
|
|
4d5b273ebe | ||
|
|
ed6a860fad | ||
|
|
423e579292 | ||
|
|
ee11aa9e75 | ||
|
|
c46d20fa92 | ||
|
|
dc8d17574c | ||
|
|
5c17cd04c8 | ||
|
|
67ada02076 | ||
|
|
32d94c2eaf | ||
|
|
687b39a12a | ||
|
|
705af407bf | ||
|
|
080052da2e | ||
|
|
ef735fd92a | ||
|
|
17c16dcafc | ||
|
|
a89b3018fb | ||
|
|
851e2ebd32 | ||
|
|
1225ce7fe8 | ||
|
|
7e77a31b96 | ||
|
|
d146b9002f | ||
|
|
1f9d567b23 | ||
|
|
ed1b3a023c | ||
|
|
1ca18f501a | ||
|
|
49588ccd98 | ||
|
|
098dedc092 | ||
|
|
b06f6b9545 | ||
|
|
ba3cb94999 | ||
|
|
74c67fbf4b | ||
|
|
32b46e4910 | ||
|
|
ecf5539ed2 | ||
|
|
ac9db4e4d5 | ||
|
|
0eb96094b0 | ||
|
|
30b3ac7dc5 | ||
|
|
0092790c7d | ||
|
|
28909d8a51 | ||
|
|
b20cfbb7b6 | ||
|
|
97639bd0a8 | ||
|
|
161ec73c96 | ||
|
|
957d6bea15 | ||
|
|
f8b6e5b414 | ||
|
|
1ab450870e | ||
|
|
de45f4884c | ||
|
|
5da1f3e7c8 | ||
|
|
983014952b | ||
|
|
55298019a3 | ||
|
|
a1ffc3f271 | ||
|
|
2fb60aa997 | ||
|
|
f5ec76537a | ||
|
|
728491fd2b | ||
|
|
d9d3f2b9e4 | ||
|
|
3fe4864f65 | ||
|
|
0b156f22a4 | ||
|
|
35b1d93813 | ||
|
|
d770851ac0 | ||
|
|
989e7b1033 | ||
|
|
c4e0eb7b49 | ||
|
|
71f5d0dac7 | ||
|
|
561b0c4381 | ||
|
|
995fbc7330 | ||
|
|
10ab8949c4 | ||
|
|
c441202fea | ||
|
|
ca261b0bee | ||
|
|
52f3709f67 | ||
|
|
c2ca6187fe | ||
|
|
671a13d295 | ||
|
|
14c3e2eccf | ||
|
|
08e5b852c2 | ||
|
|
1c9606c824 | ||
|
|
3cd47b5c9b | ||
|
|
aedc729087 | ||
|
|
5f7cfa3fa9 | ||
|
|
0083f30af5 | ||
|
|
4a06f05ef5 | ||
|
|
8f37cadce8 | ||
|
|
a11603ca6c | ||
|
|
86274842e9 | ||
|
|
cf9c955a44 | ||
|
|
55d828c35f | ||
|
|
cdff28aca6 | ||
|
|
b9da39274f | ||
|
|
c379aa5782 | ||
|
|
9dcabac9dd | ||
|
|
794f3a2b9f | ||
|
|
2066121b7c | ||
|
|
0c4067f143 | ||
|
|
8aa69243b7 | ||
|
|
8697263bde | ||
|
|
ea25c4f65c | ||
|
|
82ac3ebd7e | ||
|
|
13cb94909c | ||
|
|
b57ca2a763 | ||
|
|
83c49e9745 | ||
|
|
e15771d78d | ||
|
|
6edc4920ba | ||
|
|
302bb1bd93 | ||
|
|
529b1bceee | ||
|
|
42cd47d32e | ||
|
|
711d884c2e | ||
|
|
183d1c4674 | ||
|
|
faed63a0bb | ||
|
|
53bff262f8 | ||
|
|
3251a708e4 | ||
|
|
b5dbdbf7b2 | ||
|
|
a9649e92c9 | ||
|
|
b561f1fa8b | ||
|
|
cecd7491b5 | ||
|
|
55a66322b5 | ||
|
|
155c31a2d7 | ||
|
|
a89ce91089 | ||
|
|
b897fe6700 | ||
|
|
548a351b06 | ||
|
|
4b1da57ca1 | ||
|
|
529aec7f25 | ||
|
|
1661e545cb | ||
|
|
ec71d08878 | ||
|
|
ac258b7dd7 | ||
|
|
0f57876233 | ||
|
|
1d25a3693d | ||
|
|
45fa428bf1 | ||
|
|
177fa80f1a | ||
|
|
3261261bfe | ||
|
|
d4de7934f8 | ||
|
|
c3475af809 | ||
|
|
b12f707812 | ||
|
|
22c0c34d60 | ||
|
|
a60b66f230 | ||
|
|
83f6e93628 | ||
|
|
222b5f0229 | ||
|
|
30aa383e26 | ||
|
|
676b401294 | ||
|
|
ebf57159de | ||
|
|
199d2aafec | ||
|
|
81952f56fd | ||
|
|
c5bac82b43 | ||
|
|
081b86109c | ||
|
|
8ac2028a75 | ||
|
|
264fed1c9f | ||
|
|
dd59f7b2c7 | ||
|
|
9245a760db | ||
|
|
b61b32bbc3 | ||
|
|
09b3914f5d | ||
|
|
fe644e4c9e | ||
|
|
7b09bf2156 | ||
|
|
987d0aae66 | ||
|
|
9cbcbc1c22 | ||
|
|
cfc4e2bc60 | ||
|
|
a03405fa81 | ||
|
|
d5c9ccbe6e | ||
|
|
e52772d65f | ||
|
|
1e3259e728 | ||
|
|
e905a20a60 | ||
|
|
88e2be7a33 | ||
|
|
8939131600 | ||
|
|
ba37ebff8b | ||
|
|
28f4cb7e07 | ||
|
|
db1e7102cd | ||
|
|
07eb7a5830 | ||
|
|
b7c6c685fa | ||
|
|
212134df70 | ||
|
|
6eeb5528f5 | ||
|
|
54fad845c9 | ||
|
|
d6c0de6fc7 | ||
|
|
649c8649f7 | ||
|
|
da2f53d1b1 | ||
|
|
405139e3b8 | ||
|
|
4f8d347171 | ||
|
|
bf0db4876c | ||
|
|
47a14884d6 | ||
|
|
3a7bbc8b08 | ||
|
|
1b1d65372c | ||
|
|
fd2faaa16e | ||
|
|
0609cdb9ea | ||
|
|
d3bb140f89 | ||
|
|
b31dc66628 | ||
|
|
09476171a6 | ||
|
|
33dee813b5 | ||
|
|
bb4e73c40b | ||
|
|
b1f23ffa94 | ||
|
|
b0e8cec1e7 | ||
|
|
5077ae19bc | ||
|
|
0d8447bf59 | ||
|
|
c6cf08a274 | ||
|
|
dc49ae519e | ||
|
|
904539476a | ||
|
|
3fbf02dc82 | ||
|
|
c9392a840d | ||
|
|
d164e8ab72 | ||
|
|
6dc62c9fb6 | ||
|
|
87a9684d66 | ||
|
|
94525e2f44 | ||
|
|
b408b1b3b9 | ||
|
|
27c2f09e32 | ||
|
|
19bc4d3349 | ||
|
|
f2b6c424d6 | ||
|
|
a49d4453e9 | ||
|
|
65e50087b9 | ||
|
|
2d90f759d9 | ||
|
|
4230ac7674 | ||
|
|
d96e9182e9 | ||
|
|
68c87b9616 | ||
|
|
7f8e9a0b6d | ||
|
|
81a229f2a5 | ||
|
|
8be7ae2733 | ||
|
|
846bca4cb1 | ||
|
|
f36f353789 | ||
|
|
939a2731ed | ||
|
|
835dab97ff | ||
|
|
fa904b53be | ||
|
|
0ec52dddce | ||
|
|
c289355a3a | ||
|
|
02a13a5a18 | ||
|
|
6cf2a0281b | ||
|
|
120d35f9af | ||
|
|
2b15d5e7b3 | ||
|
|
fc167bd3f0 | ||
|
|
91b04abf05 | ||
|
|
77faac8740 | ||
|
|
43b3d54855 | ||
|
|
69e9b85700 | ||
|
|
0b6d132759 | ||
|
|
7c233c6c0c | ||
|
|
c35b290fa4 | ||
|
|
3d95cfb367 | ||
|
|
b90fc3a56e | ||
|
|
1ef3fdccf5 | ||
|
|
02b7f77bd8 | ||
|
|
0ac7ead922 | ||
|
|
da9d0e03ce | ||
|
|
120f65f672 | ||
|
|
200a14caa4 | ||
|
|
35bf6da8e2 | ||
|
|
f08f70276c | ||
|
|
1ae50fd95b | ||
|
|
40512beb47 | ||
|
|
0d7f9b2c94 | ||
|
|
52f42140a7 | ||
|
|
3f6c50297f | ||
|
|
f72d80afc5 | ||
|
|
7c5cb13b22 | ||
|
|
d728750eb2 | ||
|
|
02a70e5667 | ||
|
|
44e51ea5fa | ||
|
|
87e201460a | ||
|
|
039bd945e2 | ||
|
|
e9e52d2b4b | ||
|
|
2bf92e7399 | ||
|
|
5b0df241f0 | ||
|
|
76f5b05eff | ||
|
|
40fb6c998f | ||
|
|
33f50a342d | ||
|
|
81523ab68a | ||
|
|
2bf8cc62cf | ||
|
|
1ae8247af3 | ||
|
|
5ef32227ec | ||
|
|
6456e773bd | ||
|
|
234fe53ca3 | ||
|
|
7c93e7a7b3 | ||
|
|
8afc6c7f4b | ||
|
|
4609d0fa3a | ||
|
|
d452c035c6 | ||
|
|
45113c8f5a | ||
|
|
0acdd3c62b | ||
|
|
96d7d0a33e | ||
|
|
b6b280267b | ||
|
|
6e6d253b1a | ||
|
|
d92c105db2 | ||
|
|
906db728d6 | ||
|
|
c4b7411565 | ||
|
|
de06396046 | ||
|
|
ee6bfeb8e3 | ||
|
|
058347321f | ||
|
|
feefe49324 | ||
|
|
187381a9a2 | ||
|
|
993dfa4368 | ||
|
|
7e35a16440 | ||
|
|
e4eeb15926 | ||
|
|
634e0db26d | ||
|
|
56855c23e1 | ||
|
|
0b00f742e3 | ||
|
|
b7ab3f673c | ||
|
|
be04ea1e35 | ||
|
|
1f8e695802 | ||
|
|
2d82b2c64f | ||
|
|
d076caf473 | ||
|
|
c7abdefa31 | ||
|
|
ba772c0bca | ||
|
|
5bad234119 | ||
|
|
c7e7baaf23 | ||
|
|
36658a671b | ||
|
|
045f2e10ba | ||
|
|
fb5a7db66d | ||
|
|
ba7d33982e | ||
|
|
c62279a755 | ||
|
|
17fa1a7ffb | ||
|
|
e89ceac351 | ||
|
|
0b8c30c109 | ||
|
|
9ab0f463cc | ||
|
|
6433dda7b8 | ||
|
|
fa7a2f4be4 | ||
|
|
ba90e16505 | ||
|
|
008f710203 | ||
|
|
df2740f126 | ||
|
|
2db89d143e | ||
|
|
0525d49da3 | ||
|
|
e2b0745882 | ||
|
|
92e804fc50 | ||
|
|
67abf45576 | ||
|
|
d2c9c814e7 | ||
|
|
22f8881a64 | ||
|
|
4ab20322fe | ||
|
|
5370eeecea | ||
|
|
ba71cb5dd7 | ||
|
|
9aad6c2c52 | ||
|
|
4d9627f20c | ||
|
|
c142492e91 | ||
|
|
6bf8d9e207 | ||
|
|
4f9a6168c1 | ||
|
|
38397f99aa | ||
|
|
f8686d0e75 | ||
|
|
549e3c8f9d | ||
|
|
bb56225b95 | ||
|
|
f00be261ba | ||
|
|
9cd94f26d0 | ||
|
|
4d8f5c80a7 | ||
|
|
24a23acc3d | ||
|
|
ca8703cfd8 | ||
|
|
6dcbb5b2f8 | ||
|
|
a84fdddb2a | ||
|
|
38bb2f8ceb | ||
|
|
23f5ef4345 | ||
|
|
ef8a2a9054 | ||
|
|
96103d0e36 | ||
|
|
ff5f6748df | ||
|
|
1c1fd6c366 | ||
|
|
32d37d00cb | ||
|
|
82f6cda966 | ||
|
|
f1ff8ff0d0 | ||
|
|
756c72902f | ||
|
|
73f8f0bbd0 | ||
|
|
18ed528f5d | ||
|
|
8fd2f136bc | ||
|
|
0524b1bf67 | ||
|
|
15716f65ce | ||
|
|
d46bdba332 | ||
|
|
760728110a | ||
|
|
12d0a194ca | ||
|
|
4104543508 | ||
|
|
5c211db015 | ||
|
|
2dc6180f8d | ||
|
|
e222a34b69 | ||
|
|
ef17d95063 | ||
|
|
853502e5d7 | ||
|
|
c18e297e77 | ||
|
|
c5a49599ba | ||
|
|
df9da9edf5 | ||
|
|
e2200fd050 | ||
|
|
c6207f5d9c | ||
|
|
4302b7ff6b | ||
|
|
50a7923438 | ||
|
|
ab416445c8 | ||
|
|
a54698d43c | ||
|
|
c5a77cc1c0 | ||
|
|
a9ffa811fc | ||
|
|
080a2608e0 | ||
|
|
57f2e83d6a | ||
|
|
5b030139d3 | ||
|
|
0da1ff42d1 | ||
|
|
2c599b7baa | ||
|
|
5c8af8d21a | ||
|
|
026f3cfde2 | ||
|
|
f6349180e8 | ||
|
|
aa6421921c | ||
|
|
7d41d2dab2 | ||
|
|
f0b4d18f93 | ||
|
|
6750f06e10 | ||
|
|
b2bd38fa9e | ||
|
|
3482a01e22 | ||
|
|
6335467552 | ||
|
|
4a39e65b62 | ||
|
|
c50a23e918 | ||
|
|
1e76b72b98 | ||
|
|
b94cf39eef | ||
|
|
fef254ffff | ||
|
|
e5495863a2 | ||
|
|
3b4df2abf0 | ||
|
|
aef2aee6a4 | ||
|
|
d0d9519149 | ||
|
|
685df1d2c5 | ||
|
|
08e6b6f2e7 | ||
|
|
66c887d0f3 | ||
|
|
22e9960697 | ||
|
|
64aa6e1f2d | ||
|
|
7a93ed9d04 | ||
|
|
a905e922e9 | ||
|
|
f9f08fc720 | ||
|
|
8d402d76d0 | ||
|
|
46fda6281c | ||
|
|
a14dbe1ea6 | ||
|
|
18810a4c16 | ||
|
|
147bc80dba | ||
|
|
c7a484195a | ||
|
|
4968eb6503 | ||
|
|
a6f2d698a9 | ||
|
|
ea5ed93ea5 | ||
|
|
e1140134c6 | ||
|
|
5ed11e012e | ||
|
|
5380bd39ca | ||
|
|
2ee2685688 | ||
|
|
782002245b | ||
|
|
7fc0905843 | ||
|
|
72ecb99e54 | ||
|
|
c863507d08 | ||
|
|
cff86c9093 | ||
|
|
0479dfcc54 | ||
|
|
68dd67f21c | ||
|
|
540f6858b5 | ||
|
|
b61e791a4f | ||
|
|
d0986f9482 | ||
|
|
112cb0dc28 | ||
|
|
0d3d7fdcf2 | ||
|
|
5d6b89ef3b | ||
|
|
ed0b26c09e | ||
|
|
ae292bd920 | ||
|
|
6c85a90723 | ||
|
|
852592066c | ||
|
|
96e1bc9b44 | ||
|
|
b41d81ed31 | ||
|
|
e241ec2244 | ||
|
|
16e1f1a94c | ||
|
|
7a68c42b26 | ||
|
|
37ccc2e118 | ||
|
|
4192fe1ab2 | ||
|
|
d5c743d7bb | ||
|
|
11814d63e8 | ||
|
|
b753656d50 | ||
|
|
f7e87611fc | ||
|
|
1fb0e1900e | ||
|
|
954a9731e0 | ||
|
|
65c3364ad8 | ||
|
|
3d72b7dccc | ||
|
|
13ee569f06 | ||
|
|
d79ef23a75 | ||
|
|
5d0797d4ba | ||
|
|
47a8d7475f | ||
|
|
4939053121 | ||
|
|
b525bf554e | ||
|
|
f00285d2b2 | ||
|
|
040f8d6eda | ||
|
|
66d905325c | ||
|
|
8b0cd95e73 | ||
|
|
d867cca6d9 | ||
|
|
a28f736369 | ||
|
|
5c3a71cc59 | ||
|
|
cef6dadb08 | ||
|
|
36be817a3e | ||
|
|
02f571f081 | ||
|
|
157159e487 | ||
|
|
02ada9f800 | ||
|
|
6fcf9a97bb | ||
|
|
17a5d8799f | ||
|
|
31f3fe7a22 | ||
|
|
89e46d3d83 | ||
|
|
885795e67d | ||
|
|
92bfb53dd4 | ||
|
|
4cecbeb115 | ||
|
|
5971480f55 | ||
|
|
05bebea511 | ||
|
|
76fa6c5cfb | ||
|
|
633b68b518 | ||
|
|
6913d8e995 | ||
|
|
f3654e6f8d | ||
|
|
d685dbcf22 | ||
|
|
6a57fa079e | ||
|
|
0a91d145ba | ||
|
|
c2866e799d | ||
|
|
d8cffcaae7 | ||
|
|
30abca7be2 | ||
|
|
edce87f3fb | ||
|
|
66bac98fc2 | ||
|
|
59156de92b | ||
|
|
e0d7d10600 | ||
|
|
daaf862257 | ||
|
|
9de53d4b59 | ||
|
|
f1571e2d46 | ||
|
|
bd28d06298 | ||
|
|
a24e4655eb | ||
|
|
20a6c8d8e5 | ||
|
|
98d264faf4 | ||
|
|
321902a9b5 | ||
|
|
8df5d06f9a | ||
|
|
e69ea529cc | ||
|
|
15405b1119 | ||
|
|
d2f97ce2da | ||
|
|
543ca631e9 | ||
|
|
f184886db1 | ||
|
|
8432ab4324 | ||
|
|
6c05b37ca3 | ||
|
|
35f4beeb47 | ||
|
|
cbad7caa68 | ||
|
|
b0388a4012 | ||
|
|
df3fab4d55 | ||
|
|
da49f88a03 | ||
|
|
e28feceb06 | ||
|
|
50496a164d | ||
|
|
6f1dce1572 | ||
|
|
6847776ae7 | ||
|
|
67bd53bdd8 | ||
|
|
e735abfdfd | ||
|
|
1de93a2d6d | ||
|
|
36f9e7c742 | ||
|
|
9462763bbb | ||
|
|
4ae0880ea6 | ||
|
|
6ae2b6c835 | ||
|
|
a0f180fd48 | ||
|
|
bf1cf89914 | ||
|
|
297a047fb4 | ||
|
|
52ffc15ffc | ||
|
|
e478c9c693 | ||
|
|
d004f28074 | ||
|
|
bc68ed8b1d | ||
|
|
04555ae650 | ||
|
|
e8f62085be | ||
|
|
f430bffe2a | ||
|
|
1f0520634f | ||
|
|
902d4c31fb | ||
|
|
17364ac09f | ||
|
|
0b889f8f81 | ||
|
|
40e349ff35 | ||
|
|
c943b1b1df | ||
|
|
912bc1d4e1 | ||
|
|
cacb1533a3 | ||
|
|
f0feaca9d7 | ||
|
|
b6656f171b | ||
|
|
6206ab3931 | ||
|
|
c35fc58b1f | ||
|
|
deed8abed7 | ||
|
|
7151ad23f0 | ||
|
|
0166d938af | ||
|
|
6194aeddb0 | ||
|
|
903dbf2c30 | ||
|
|
9380f9ff57 | ||
|
|
259ed95486 | ||
|
|
2ebc92681e | ||
|
|
195a1ffe13 | ||
|
|
a8c2978185 | ||
|
|
140f97a457 | ||
|
|
7f94445a1e | ||
|
|
82a89aec65 | ||
|
|
7e95110232 | ||
|
|
ec4aaaad89 | ||
|
|
1b790fde24 | ||
|
|
aaccea731e | ||
|
|
29e31d7610 | ||
|
|
aa51f4a98f | ||
|
|
e6ccd12f00 | ||
|
|
b134315df1 | ||
|
|
7f34dffa13 | ||
|
|
fa239e78c9 | ||
|
|
707a6c4d6a | ||
|
|
e5da303b43 | ||
|
|
84ccd66331 | ||
|
|
ad8cc2baea | ||
|
|
7c4cf70309 | ||
|
|
c3211e9b4f | ||
|
|
268d94c983 | ||
|
|
0bcacbba58 | ||
|
|
8cdc26add9 | ||
|
|
e0b2238886 | ||
|
|
369a2e4029 | ||
|
|
c4089e3b51 | ||
|
|
9e2e9bc5b8 | ||
|
|
a9e44426ed |
0
CONTRIBUTORS
Normal file
0
CONTRIBUTORS
Normal file
340
COPYING
Normal file
340
COPYING
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
||||||
483
COPYING.LIB
Normal file
483
COPYING.LIB
Normal file
@@ -0,0 +1,483 @@
|
|||||||
|
|
||||||
|
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the library GPL. It is
|
||||||
|
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Library General Public License, applies to some
|
||||||
|
specially designated Free Software Foundation software, and to any
|
||||||
|
other libraries whose authors decide to use it. You can use it for
|
||||||
|
your libraries, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if
|
||||||
|
you distribute copies of the library, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link a program with the library, you must provide
|
||||||
|
complete object files to the recipients so that they can relink them
|
||||||
|
with the library, after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
Our method of protecting your rights has two steps: (1) copyright
|
||||||
|
the library, and (2) offer you this license which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
Also, for each distributor's protection, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
library. If the library is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original
|
||||||
|
version, so that any problems introduced by others will not reflect on
|
||||||
|
the original authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that companies distributing free
|
||||||
|
software will individually obtain patent licenses, thus in effect
|
||||||
|
transforming the program into proprietary software. To prevent this,
|
||||||
|
we have made it clear that any patent must be licensed for everyone's
|
||||||
|
free use or not licensed at all.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the ordinary
|
||||||
|
GNU General Public License, which was designed for utility programs. This
|
||||||
|
license, the GNU Library General Public License, applies to certain
|
||||||
|
designated libraries. This license is quite different from the ordinary
|
||||||
|
one; be sure to read it in full, and don't assume that anything in it is
|
||||||
|
the same as in the ordinary license.
|
||||||
|
|
||||||
|
The reason we have a separate public license for some libraries is that
|
||||||
|
they blur the distinction we usually make between modifying or adding to a
|
||||||
|
program and simply using it. Linking a program with a library, without
|
||||||
|
changing the library, is in some sense simply using the library, and is
|
||||||
|
analogous to running a utility program or application program. However, in
|
||||||
|
a textual and legal sense, the linked executable is a combined work, a
|
||||||
|
derivative of the original library, and the ordinary General Public License
|
||||||
|
treats it as such.
|
||||||
|
|
||||||
|
Because of this blurred distinction, using the ordinary General
|
||||||
|
Public License for libraries did not effectively promote software
|
||||||
|
sharing, because most developers did not use the libraries. We
|
||||||
|
concluded that weaker conditions might promote sharing better.
|
||||||
|
|
||||||
|
However, unrestricted linking of non-free programs would deprive the
|
||||||
|
users of those programs of all benefit from the free status of the
|
||||||
|
libraries themselves. This Library General Public License is intended to
|
||||||
|
permit developers of non-free programs to use free libraries, while
|
||||||
|
preserving your freedom as a user of such programs to change the free
|
||||||
|
libraries that are incorporated in them. (We have not seen how to achieve
|
||||||
|
this as regards changes in header files, but we have achieved it as regards
|
||||||
|
changes in the actual functions of the Library.) The hope is that this
|
||||||
|
will lead to faster development of free libraries.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, while the latter only
|
||||||
|
works together with the library.
|
||||||
|
|
||||||
|
Note that it is possible for a library to be covered by the ordinary
|
||||||
|
General Public License rather than by this special one.
|
||||||
|
|
||||||
|
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library which
|
||||||
|
contains a notice placed by the copyright holder or other authorized
|
||||||
|
party saying it may be distributed under the terms of this Library
|
||||||
|
General Public License (also called "this License"). Each licensee is
|
||||||
|
addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also compile or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
c) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
d) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the source code distributed need not include anything that is normally
|
||||||
|
distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Library General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
Appendix: How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
MA 02111-1307, USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
45
INSTALL
Normal file
45
INSTALL
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
LVM2 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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
3) Build and install LVM2.
|
||||||
|
|
||||||
|
Run 'make install' from the top directory.
|
||||||
|
|
||||||
|
|
||||||
|
4) 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.
|
||||||
|
|
||||||
70
Makefile.in
Normal file
70
Makefile.in
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004 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@
|
||||||
|
|
||||||
|
SUBDIRS = doc include man scripts
|
||||||
|
|
||||||
|
ifeq ("@INTL@", "yes")
|
||||||
|
SUBDIRS += po
|
||||||
|
endif
|
||||||
|
|
||||||
|
SUBDIRS += lib tools daemons
|
||||||
|
|
||||||
|
ifeq ("@DMEVENTD@", "yes")
|
||||||
|
SUBDIRS += dmeventd
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(MAKECMDGOALS),distclean)
|
||||||
|
SUBDIRS += daemons/clvmd \
|
||||||
|
dmeventd \
|
||||||
|
lib/format1 \
|
||||||
|
lib/format_pool \
|
||||||
|
lib/locking \
|
||||||
|
lib/mirror \
|
||||||
|
lib/snapshot \
|
||||||
|
po \
|
||||||
|
test/mm test/device test/format1 test/regex test/filters
|
||||||
|
DISTCLEAN_TARGETS += lib/misc/configure.h
|
||||||
|
endif
|
||||||
|
|
||||||
|
include make.tmpl
|
||||||
|
|
||||||
|
daemons: lib
|
||||||
|
lib: include
|
||||||
|
tools: lib
|
||||||
|
dmeventd: tools
|
||||||
|
po: tools daemons dmeventd
|
||||||
|
|
||||||
|
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
|
||||||
|
pofile: po.pofile
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ("@CFLOW_CMD@", "")
|
||||||
|
tools.cflow: lib.cflow
|
||||||
|
cflow: tools.cflow
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ("@CSCOPE_CMD@", "")
|
||||||
|
cscope.out: tools
|
||||||
|
@CSCOPE_CMD@ -b -R
|
||||||
|
all: cscope.out
|
||||||
|
endif
|
||||||
25
README
25
README
@@ -1,2 +1,23 @@
|
|||||||
This is pretty much empty so far...if you can't see subdirectories,
|
This directory contains LVM2, the new version of the userland LVM
|
||||||
try 'cvs -f update'
|
tools designed for the new device-mapper for the Linux kernel.
|
||||||
|
|
||||||
|
The device-mapper needs to be installed before compiling these LVM2 tools.
|
||||||
|
|
||||||
|
For more information about LVM2 read 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.
|
||||||
|
linux-lvm@redhat.com
|
||||||
|
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
|
||||||
|
|
||||||
|
|||||||
941
WHATS_NEW
Normal file
941
WHATS_NEW
Normal file
@@ -0,0 +1,941 @@
|
|||||||
|
Version 2.02.23 - 8th March 2008
|
||||||
|
====================================
|
||||||
|
Fix vgrename active LV check to ignore differing vgids.
|
||||||
|
Remove no-longer-used uuid_out parameter from activation info functions.
|
||||||
|
Fix two more segfaults if an empty config file section encountered.
|
||||||
|
Move .cache file into a new /etc/lvm/cache directory by default.
|
||||||
|
Add devices/cache_dir & devices/cache_file_prefix, deprecating devices/cache.
|
||||||
|
Create directory in fcntl_lock_file() if required.
|
||||||
|
Exclude readline support from lvm.static.
|
||||||
|
Fix a leak in a reporting error path (2.02.19).
|
||||||
|
|
||||||
|
Version 2.02.22 - 13th February 2007
|
||||||
|
====================================
|
||||||
|
Correct -b and -P on a couple of man pages.
|
||||||
|
Add global/units to example.conf.
|
||||||
|
Fix loading of segment_libraries.
|
||||||
|
If a PV reappears after it was removed from its VG, make it an orphan.
|
||||||
|
Don't update metadata automatically if VGIDs don't match.
|
||||||
|
Fix some vgreduce --removemissing command line validation.
|
||||||
|
|
||||||
|
Version 2.02.21 - 30th January 2007
|
||||||
|
===================================
|
||||||
|
Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
|
||||||
|
Fix vgsplit to handle mirrors.
|
||||||
|
Reorder fields in reporting field definitions.
|
||||||
|
Fix vgs to treat args as VGs even when PV fields are displayed.
|
||||||
|
Fix md signature check to handle both endiannesses.
|
||||||
|
|
||||||
|
Version 2.02.20 - 25th January 2007
|
||||||
|
===================================
|
||||||
|
dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.
|
||||||
|
Add devices/ignore_suspended_devices to ignore suspended dm devices.
|
||||||
|
Add some missing close() and fclose() return code checks.
|
||||||
|
Fix exit statuses of reporting tools (2.02.19).
|
||||||
|
Add init script for dmeventd monitoring.
|
||||||
|
lvm.static no longer interacts with dmeventd unless explicitly asked to.
|
||||||
|
Add field definitions to report help text.
|
||||||
|
Remove unnecessary cmd arg from target_*monitor_events().
|
||||||
|
Add private variable to dmeventd shared library interface.
|
||||||
|
Long-lived processes write out persistent dev cache in refresh_toolcontext().
|
||||||
|
Fix refresh_toolcontext() always to wipe persistent device filter cache.
|
||||||
|
Add is_long_lived to toolcontext.
|
||||||
|
Add --clustered to man pages.
|
||||||
|
Streamline dm_report_field_* interface.
|
||||||
|
Change remaining dmeventd terminology 'register' to 'monitor'.
|
||||||
|
Update reporting man pages.
|
||||||
|
No longer necessary to specify alignment type for report fields.
|
||||||
|
|
||||||
|
Version 2.02.19 - 17th January 2007
|
||||||
|
===================================
|
||||||
|
Fix a segfault if an empty config file section encountered.
|
||||||
|
Move basic reporting functions into libdevmapper.
|
||||||
|
Fix partition table processing after sparc changes (2.02.16).
|
||||||
|
Fix cmdline PE range processing segfault (2.02.13).
|
||||||
|
Some libdevmapper-event interface changes.
|
||||||
|
Report dmeventd mirror monitoring status.
|
||||||
|
Fix dmeventd mirror status line processing.
|
||||||
|
|
||||||
|
Version 2.02.18 - 11th January 2007
|
||||||
|
===================================
|
||||||
|
Revised libdevmapper-event interface for dmeventd.
|
||||||
|
Remove dmeventd mirror status line word limit.
|
||||||
|
Use CFLAGS when linking so mixed sparc builds can supply -m64.
|
||||||
|
Prevent permission changes on active mirrors.
|
||||||
|
Print warning instead of error message if lvconvert cannot zero volume.
|
||||||
|
Add snapshot options to lvconvert man page.
|
||||||
|
dumpconfig accepts a list of configuration variables to display.
|
||||||
|
Change dumpconfig to use --file to redirect output to a file.
|
||||||
|
Avoid vgreduce error when mirror code removes the log LV.
|
||||||
|
Remove 3 redundant AC_MSG_RESULTs from configure.in.
|
||||||
|
Free memory in _raw_read_mda_header() error paths.
|
||||||
|
Fix ambiguous vgsplit error message for split LV.
|
||||||
|
Fix lvextend man page typo.
|
||||||
|
Add configure --with-dmdir to compile against a device-mapper source tree.
|
||||||
|
Use no flush suspending for mirrors.
|
||||||
|
Add dmeventd_mirror register_mutex, tidy initialisation & add memlock.
|
||||||
|
Fix create mirror with name longer than 22 chars.
|
||||||
|
Fix some activate.c prototypes when compiled without devmapper.
|
||||||
|
Fix dmeventd mirror to cope if monitored device disappears.
|
||||||
|
|
||||||
|
Version 2.02.17 - 14th December 2006
|
||||||
|
====================================
|
||||||
|
Add missing pvremove error message when device doesn't exist.
|
||||||
|
When lvconvert allocates a mirror log, respect parallel area constraints.
|
||||||
|
Use loop to iterate through the now-ordered policy list in _allocate().
|
||||||
|
Check for failure to allocate just the mirror log.
|
||||||
|
Introduce calc_area_multiple().
|
||||||
|
Support mirror log allocation when there is only one PV: area_count now 0.
|
||||||
|
Fix detection of smallest area in _alloc_parallel_area() for cling policy.
|
||||||
|
Add manpage entry for clvmd -T
|
||||||
|
Fix gulm operation of clvmd, including a hang when doing lvchange -aey
|
||||||
|
Fix hang in clvmd if a pre-command failed.
|
||||||
|
|
||||||
|
Version 2.02.16 - 1st December 2006
|
||||||
|
===================================
|
||||||
|
Fix VG clustered read locks to use PR not CR.
|
||||||
|
Adjust some alignments for ia64/sparc.
|
||||||
|
Fix mirror segment removal to use temporary error segment.
|
||||||
|
Always compile debug logging into clvmd.
|
||||||
|
Add startup timeout to RHEL4 clvmd startup script.
|
||||||
|
Add -T (startup timeout) switch to clvmd.
|
||||||
|
Improve lvm_dump.sh robustness.
|
||||||
|
Update lvm2create_initrd to support gentoo.
|
||||||
|
|
||||||
|
Version 2.02.15 - 21st November 2006
|
||||||
|
====================================
|
||||||
|
Fix clvmd_init_rhel4 line truncation (2.02.14).
|
||||||
|
Install lvmdump by default.
|
||||||
|
Fix check for snapshot module when activating snapshot.
|
||||||
|
Fix pvremove error path for case when PV is in use.
|
||||||
|
Warn if certain duplicate config file entries are seen.
|
||||||
|
Enhance lvm_dump.sh for sysreport integration and add man page.
|
||||||
|
Fix --autobackup argument which could never disable backups.
|
||||||
|
Fix a label_verify error path.
|
||||||
|
|
||||||
|
Version 2.02.14 - 10th November 2006
|
||||||
|
====================================
|
||||||
|
Fix adjusted_mirror_region_size() to handle 64-bit size.
|
||||||
|
Add some missing bounds checks on 32-bit extent counters.
|
||||||
|
Add Petabyte and Exabyte support.
|
||||||
|
Fix lvcreate error message when 0 extents requested.
|
||||||
|
lvremove man page: volumes must be cluster inactive before being removed.
|
||||||
|
Protect .cache manipulations with fcntl locking.
|
||||||
|
Change .cache timestamp comparisons to use ctime.
|
||||||
|
Fix mirror log LV writing to set all bits in whole LV.
|
||||||
|
Fix clustered VG detection and default runlevels in clvmd_init_rhel4.
|
||||||
|
Fix high-level free space check for partial allocations.
|
||||||
|
|
||||||
|
Version 2.02.13 - 27th October 2006
|
||||||
|
===================================
|
||||||
|
Add couple of missing files to tools/Makefile CLEAN_TARGETS.
|
||||||
|
When adding snapshot leave cow LV mapped device active after zeroing.
|
||||||
|
Fix a clvmd debug message.
|
||||||
|
Add dev_flush() to set_lv().
|
||||||
|
Add lvchange --resync.
|
||||||
|
Perform high-level free space check before each allocation attempt.
|
||||||
|
Don't allow a node to remove an LV that's exclusively active on anther node.
|
||||||
|
Cope if same PV is included more than once in cmdline PE range list.
|
||||||
|
Set PV size to current device size if it is found to be zero.
|
||||||
|
Add segment parameter to target_present functions.
|
||||||
|
|
||||||
|
Version 2.02.12 - 16th October 2006
|
||||||
|
===================================
|
||||||
|
Fix pvdisplay to use vg_read() for non-orphans.
|
||||||
|
Fall back to internal locking if external locking lib is missing or fails.
|
||||||
|
Retain activation state after changing LV minor number with --force.
|
||||||
|
Propagate clustered flag in vgsplit and require resizeable flag.
|
||||||
|
|
||||||
|
Version 2.02.11 - 12th October 2006
|
||||||
|
===================================
|
||||||
|
Add clvmd function to return the cluster name. not used by LVM yet.
|
||||||
|
Add cling allocation policy.
|
||||||
|
Change _check_contiguous() to use _for_each_pv().
|
||||||
|
Extend _for_each_pv() to allow termination without error.
|
||||||
|
Abstract _is_contiguous().
|
||||||
|
Remove duplicated pv arg from _check_contiguous().
|
||||||
|
Accept regionsize with lvconvert.
|
||||||
|
Add report columns with underscore before field names ending 'size'.
|
||||||
|
Correct regionsize default on lvcreate man page (MB).
|
||||||
|
Fix clvmd bug that could cause it to die when a node with a long name crashed.
|
||||||
|
Add device size to text metadata.
|
||||||
|
Fix format_text mda_setup pv->size and pv_setup pe_count calculations.
|
||||||
|
Fix _for_each_pv() for mirror with core log.
|
||||||
|
Add lvm_dump.sh script to create a tarball of debugging info from a system.
|
||||||
|
Capture error messages in clvmd and pass them back to the user.
|
||||||
|
Remove unused #defines from filter-md.c.
|
||||||
|
Make clvmd restart init script wait until clvmd has died before starting it.
|
||||||
|
Add -R to clvmd which tells running clvmds to reload their device cache.
|
||||||
|
Add LV column to reports listing kernel modules needed for activation.
|
||||||
|
Show available fields if report given invalid field. (e.g. lvs -o list)
|
||||||
|
Add timestamp functions with --disable-realtime configure option.
|
||||||
|
Add %VG, %LV and %FREE suffices to lvcreate/lvresize --extents arg.
|
||||||
|
Fix two potential NULL pointer derefs in error cases in vg_read().
|
||||||
|
Separate --enable-cluster from locking lib options in lvmconf.sh.
|
||||||
|
Add a missing comma in lvcreate man page.
|
||||||
|
|
||||||
|
Version 2.02.10 - 19th September 2006
|
||||||
|
=====================================
|
||||||
|
Fix lvconvert mirror change case detection logic.
|
||||||
|
Fix mirror log detachment so it correctly becomes a standalone LV.
|
||||||
|
Extend _check_contiguous() to detect single-area LVs.
|
||||||
|
Include mirror log (untested) in _for_each_pv() processing.
|
||||||
|
Use MIRROR_LOG_SIZE constant.
|
||||||
|
Remove struct seg_pvs from _for_each_pv() to generalise.
|
||||||
|
Avoid adding duplicates to list of parallel PVs to avoid.
|
||||||
|
Fix several incorrect comparisons in parallel area avoidance code.
|
||||||
|
Fix segment lengths when flattening existing parallel areas.
|
||||||
|
Log existing parallel areas prior to allocation.
|
||||||
|
Fix mirror log creation when activation disabled.
|
||||||
|
Don't attempt automatic recovery without proper locking.
|
||||||
|
When using local file locking, skip clustered VGs.
|
||||||
|
Add fallback_to_clustered_locking and fallback_to_local_locking parameters.
|
||||||
|
lvm.static uses built-in cluster locking instead of external locking.
|
||||||
|
Don't attempt to load shared libraries if built statically.
|
||||||
|
Change default locking_lib to liblvm2clusterlock.so.
|
||||||
|
Add skip_dev_dir() to process command line VGs.
|
||||||
|
Stop clvmd complaining about nodes that have left the cluster.
|
||||||
|
Move lvm_snprintf(), split_words() and split_dm_name() into libdevmapper.
|
||||||
|
Add lvconvert man page.
|
||||||
|
Add mirror options to man pages.
|
||||||
|
Prevent mirror renames.
|
||||||
|
Move CMDLIB code into separate file and record whether static build.
|
||||||
|
|
||||||
|
Version 2.02.09 - 17th August 2006
|
||||||
|
==================================
|
||||||
|
Fix PE_ALIGN for pagesize over 32KB.
|
||||||
|
Separate out LVM1_PE_ALIGN and pe_align().
|
||||||
|
Add lvm_getpagesize wrapper.
|
||||||
|
Add --maxphysicalvolumes to vgchange.
|
||||||
|
|
||||||
|
Version 2.02.08 - 15th August 2006
|
||||||
|
==================================
|
||||||
|
Add checks for duplicate LV name, lvid and PV id before writing metadata.
|
||||||
|
Report all sanity check failures, not just the first.
|
||||||
|
Fix missing lockfs on first snapshot creation.
|
||||||
|
Add unreliable --trustcache option to reporting commands.
|
||||||
|
Fix locking for mimage removal.
|
||||||
|
Fix clvmd_init_rhel4 'status' exit code.
|
||||||
|
|
||||||
|
Version 2.02.07 - 17th July 2006
|
||||||
|
================================
|
||||||
|
Fix activation logic in lvchange --persistent.
|
||||||
|
Don't ignore persistent minor numbers when activating.
|
||||||
|
Use RTLD_GLOBAL when loading shared libraries.
|
||||||
|
Add some forgotten memlock checks to _vg_read to protect against full scans.
|
||||||
|
Add mutex to dmeventd_mirror to avoid concurrent execution.
|
||||||
|
Fix vgreduce --removemissing to return success if VG is already consistent.
|
||||||
|
Fix return code if VG specified on command line is not found.
|
||||||
|
Fix PV tools to include orphaned PVs in default output again.
|
||||||
|
Fixed unaligned access when using clvm.
|
||||||
|
Fix an extra dev_close in a label_read error path.
|
||||||
|
Append patches to commit emails.
|
||||||
|
Fix target_register_events args.
|
||||||
|
Prevent snapshots of mirrors.
|
||||||
|
Add DISTCLEAN_TARGETS to make template for configure.h.
|
||||||
|
More fixes to error paths.
|
||||||
|
Fix lvcreate corelog validation.
|
||||||
|
Add --config for overriding most config file settings from cmdline.
|
||||||
|
Quote arguments when printing command line.
|
||||||
|
Remove linefeed from 'initialising logging' message.
|
||||||
|
Add 'Completed' debug message.
|
||||||
|
Don't attempt library exit after reloading config files.
|
||||||
|
Always compile with libdevmapper, even if device-mapper is disabled.
|
||||||
|
|
||||||
|
Version 2.02.06 - 12th May 2006
|
||||||
|
===============================
|
||||||
|
Propagate --monitor around cluster.
|
||||||
|
Add --monitor to vgcreate and lvcreate to control dmeventd registration.
|
||||||
|
Filter LCK_NONBLOCK in clvmd lock_vg.
|
||||||
|
Add --nosync to lvcreate with LV flag NOTSYNCED.
|
||||||
|
Use mirror's uuid for a core log.
|
||||||
|
Add mirror log fault-handling policy.
|
||||||
|
Improve mirror warning messages and tidy dmeventd syslog output.
|
||||||
|
Propagate nosync flag around cluster.
|
||||||
|
Allow vgreduce to handle mirror log failures.
|
||||||
|
Add --corelog to lvcreate and lvconvert.
|
||||||
|
Create a log header for replacement in-sync mirror log.
|
||||||
|
Use set_lv() and dev_set() to wipe sections of devices.
|
||||||
|
Add mirror_in_sync() flag to avoid unnecessary resync on activation.
|
||||||
|
Add mirror_library description to example.conf.
|
||||||
|
Fix uuid_from_num() buffer overrun.
|
||||||
|
Make SIZE_SHORT the default for display_size().
|
||||||
|
Fix some memory leaks in error paths found by coverity.
|
||||||
|
Use C99 struct initialisers.
|
||||||
|
Move DEFS into configure.h.
|
||||||
|
Clean-ups to remove miscellaneous compiler warnings.
|
||||||
|
Improve stripe size validation.
|
||||||
|
Increase maximum stripe size limit to physical extent size for lvm2 metadata.
|
||||||
|
Fix activation code to check for pre-existing mirror logs.
|
||||||
|
Tighten region size validation.
|
||||||
|
Ignore empty strings in config files.
|
||||||
|
Require non-zero regionsize and document parameter on lvcreate man page.
|
||||||
|
Invalidate cache if composition of VG changed externally.
|
||||||
|
|
||||||
|
Version 2.02.05 - 21st April 2006
|
||||||
|
=================================
|
||||||
|
Fix vgid string termination in recent cache code.
|
||||||
|
|
||||||
|
Version 2.02.04 - 19th April 2006
|
||||||
|
=================================
|
||||||
|
Check for libsepol.
|
||||||
|
Add some cflow & scope support.
|
||||||
|
Separate out DEFS from CFLAGS.
|
||||||
|
Remove inlines and use unique function names.
|
||||||
|
|
||||||
|
Version 2.02.03 - 14th April 2006
|
||||||
|
=================================
|
||||||
|
vgrename accepts vgid and exported VG.
|
||||||
|
Add --partial to pvs.
|
||||||
|
When choosing between identically-named VGs, also consider creation_host.
|
||||||
|
Provide total log suppression with 2.
|
||||||
|
Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct.
|
||||||
|
Add vgid to struct physical_volume and pass with vg_name to some functions.
|
||||||
|
If two or more VGs are found with the same name, use one that is not exported.
|
||||||
|
Whenever vgname is captured, also capture vgid and whether exported.
|
||||||
|
Remove an incorrect unlock_vg() from process_each_lv().
|
||||||
|
Update extent size information in vgchange and vgcreate man pages.
|
||||||
|
Introduce origin_from_cow() and lv_is_visible().
|
||||||
|
pvremove without -f now fails if there's no PV label.
|
||||||
|
Support lvconvert -s.
|
||||||
|
Suppress locking library load failure message if --ignorelockingfailure.
|
||||||
|
Propagate partial mode around cluster.
|
||||||
|
Fix archive file expiration.
|
||||||
|
Fix dmeventd build.
|
||||||
|
clvmd now uses libcman rather than cman ioctls.
|
||||||
|
clvmd will allow new cman to shutdown on request.
|
||||||
|
|
||||||
|
Version 2.02.02 - 7th February 2006
|
||||||
|
===================================
|
||||||
|
Add %.so: %.a make template rule.
|
||||||
|
Switchover library building to use LIB_SUFFIX.
|
||||||
|
Only do lockfs filesystem sync when suspending snapshots.
|
||||||
|
Always print warning if activation is disabled.
|
||||||
|
vgreduce removes mirror images.
|
||||||
|
Add --mirrorsonly to vgreduce.
|
||||||
|
vgreduce replaces active LVs with error segment before removing them.
|
||||||
|
Set block_on_error parameter if available.
|
||||||
|
Add target_version.
|
||||||
|
Add details to format1 'Invalid LV in extent map' error message.
|
||||||
|
Fix lvscan snapshot full display.
|
||||||
|
Bring lvdisplay man page example into line.
|
||||||
|
Add mirror dmeventd library.
|
||||||
|
Add some activation logic to remove_mirror_images().
|
||||||
|
lvconvert can remove specified PVs from a mirror.
|
||||||
|
lvconvert turns an existing LV into a mirror.
|
||||||
|
Allow signed mirrors arguments.
|
||||||
|
Move create_mirror_log() into toollib.
|
||||||
|
Determine parallel PVs to avoid with ALLOC_NORMAL allocation.
|
||||||
|
Fix lv_empty.
|
||||||
|
|
||||||
|
Version 2.02.01 - 23rd November 2005
|
||||||
|
====================================
|
||||||
|
Fix lvdisplay cmdline to accept snapshots.
|
||||||
|
Fix open RO->RW promotion.
|
||||||
|
Fix missing vg_revert in lvcreate error path.
|
||||||
|
|
||||||
|
Version 2.02.00 - 10th November 2005
|
||||||
|
====================================
|
||||||
|
Extend allocation areas to avoid overflow with contiguous with other PVs.
|
||||||
|
Stop lvcreate attempting to wipe zero or error segments.
|
||||||
|
Added new lvs table attributes.
|
||||||
|
Separated out activation preload.
|
||||||
|
Moved activation functions into libdevmapper.
|
||||||
|
Fixed build_dm_name.
|
||||||
|
Add return macros.
|
||||||
|
Added xen xvd devices.
|
||||||
|
Clear up precommitted metadata better.
|
||||||
|
A pvresize implementation.
|
||||||
|
Fix contiguous allocation when there are no preceding segments.
|
||||||
|
Add mirror_seg pointer to lv_segment struct.
|
||||||
|
Only keep a device open if it's known to belong to a locked VG.
|
||||||
|
Fix lvdisplay to show all mirror destinations.
|
||||||
|
Replacement suspend code using libdevmapper dependency tree.
|
||||||
|
Add DEFS to make.tmpl.
|
||||||
|
Use dm_is_dm_major instead of local copy.
|
||||||
|
Allow mapped devices to be used as PVs.
|
||||||
|
Move set_selinux_context into libdevmapper.
|
||||||
|
Fix automatic text metadata buffer expansion (using macro).
|
||||||
|
Cache formatted text metadata buffer between metadata area writes.
|
||||||
|
Add pe_start field to pvs.
|
||||||
|
Add 'LVM-' prefix to uuids.
|
||||||
|
Split lv_segment_area from lv_segment to permit extension.
|
||||||
|
Replacement deactivation code using libdevmapper dependency tree.
|
||||||
|
Simplify dev_manager_info().
|
||||||
|
Attempt to load missing targets using modprobe.
|
||||||
|
Add -a to lvscan.
|
||||||
|
Move mknodes into libdevmapper.
|
||||||
|
Move bitset, hash, pool and dbg_malloc into libdevmapper.
|
||||||
|
|
||||||
|
Version 2.01.15 - 16th October 2005
|
||||||
|
===================================
|
||||||
|
Refuse to run pvcreate/pvremove on devices we can't open exclusively.
|
||||||
|
Use ORPHAN lock definition throughout.
|
||||||
|
Validate chunksize in lvcreate.
|
||||||
|
Reduce chunksize limit to 512k.
|
||||||
|
Fix chunksize field in reports.
|
||||||
|
Don't hide snapshots from default 'lvs' output.
|
||||||
|
Add is_dm_major() for use in duplicate device detection in lvmcache_add().
|
||||||
|
Really switch device number in lvmcache when it says it is doing so.
|
||||||
|
Option for bitset memory allocation using malloc as well as pool.
|
||||||
|
Don't assume exactly two mirrors when parsing mirror status.
|
||||||
|
Suppress fsync() error message on filesystems that don't support it.
|
||||||
|
Fix yes_no_prompt() error handling.
|
||||||
|
Add lvm.conf comment warning against multiple filter lines.
|
||||||
|
Tidy lvmconf.sh.
|
||||||
|
Add format1 dev_write debug messages.
|
||||||
|
Add clustered VG attribute to report.
|
||||||
|
Move lvconvert parameters into struct lvconvert_params.
|
||||||
|
Add clustered VG flag to LV lock requests.
|
||||||
|
Change LV locking macros to take lv instead of lvid.
|
||||||
|
Prepend 'cluster' activation parameter to mirror log when appropriate.
|
||||||
|
Pass exclusive flag to lv_activate and on to target activation code.
|
||||||
|
Prevent snapshot creation in a clustered VG for now.
|
||||||
|
Factor out adjusted_mirror_region_size() and generate_log_name_format().
|
||||||
|
Move compose_log_line() into mirror directory.
|
||||||
|
Factor out _get_library_path().
|
||||||
|
Don't kill idling clvmd threads.
|
||||||
|
clvmd no longer takes out locks for non-clustered LVs.
|
||||||
|
Recognise ATA over Ethernet (aoe) devices.
|
||||||
|
|
||||||
|
Version 2.01.14 - 4th August 2005
|
||||||
|
=================================
|
||||||
|
Fix lvconvert PV parameter in help string.
|
||||||
|
Prevent snapshots getting activated in a clustered VG.
|
||||||
|
Separate out _build_dev_string.
|
||||||
|
Move zero_lv to toollib.
|
||||||
|
Fix pool format handler to work with pv segment code.
|
||||||
|
|
||||||
|
Version 2.01.13 - 13th July 2005
|
||||||
|
================================
|
||||||
|
Fix pvmove segment splitting.
|
||||||
|
Abstract vg_validate.
|
||||||
|
Only make one attempt at contiguous allocation.
|
||||||
|
Fix lvm1 format metadata read.
|
||||||
|
Fix lvm1 format non-mirror lvcreate.
|
||||||
|
|
||||||
|
Version 2.01.12 - 14th June 2005
|
||||||
|
================================
|
||||||
|
Various allocation-related pvmove fixes.
|
||||||
|
Log an error if clvmd can't resolve a host name got from CCS.
|
||||||
|
Fix potential spin loop in clvmd.
|
||||||
|
|
||||||
|
Version 2.01.11 - 13th June 2005
|
||||||
|
================================
|
||||||
|
Added lvmconf.sh.
|
||||||
|
Use matchpathcon mode parameter.
|
||||||
|
Don't defer closing dead FDs in clvmd.
|
||||||
|
Remove hard-coded 64k text metadata writing restriction.
|
||||||
|
Make VG name restrictions consistent.
|
||||||
|
Introduce lvconvert. So far only removes mirror images.
|
||||||
|
Allow mirror images to be resized.
|
||||||
|
Allow mirror images to have more than one segment.
|
||||||
|
Centralise restrictions on LV names.
|
||||||
|
Always insert an intermediate layer for mirrors.
|
||||||
|
Suppress hidden LVs from reports unless --all is given.
|
||||||
|
Use square brackets for hidden LVs in reports.
|
||||||
|
Allow the creation of mirrors with contiguous extents.
|
||||||
|
Always perform sanity checks against metadata before committing it to disk.
|
||||||
|
Split lv_extend into two steps: choosing extents + allocation to LV(s).
|
||||||
|
Add mirror log region size to metadata.
|
||||||
|
Use list_iterate_items throughout and add list*back macros.
|
||||||
|
Introduce seg_ macros to access areas.
|
||||||
|
Add segtype_is_ macros.
|
||||||
|
Support tiny metadata areas for pool conversions.
|
||||||
|
Mirror activation handles disk log as well as core.
|
||||||
|
Activation code recognises mirror log dependency.
|
||||||
|
Add mirror_log and regionsize fields to report.
|
||||||
|
Fix non-orphan pvchange -u.
|
||||||
|
Fix vgmerge to handle duplicate LVIDs.
|
||||||
|
Move archiver code from tools into library.
|
||||||
|
vgscan/change/display/vgs automatically create metadata backups if needed.
|
||||||
|
Merge cloned allocation functions.
|
||||||
|
Fix contiguous allocation policy with linear.
|
||||||
|
Cope with missing format1 PVs again.
|
||||||
|
Remove lists of free PV segments.
|
||||||
|
Simplify pv_maps code and remove slow bitset algorithm.
|
||||||
|
Red-Hat-ify the clvmd rhel4 initscript.
|
||||||
|
%Zu->%zu
|
||||||
|
Fix loopfiles alias alloc & mem debugging.
|
||||||
|
Un-inline dbg_strdup.
|
||||||
|
lv_reduce tidying.
|
||||||
|
Remove some unnecessary parameters.
|
||||||
|
Introduce seg_is macros.
|
||||||
|
|
||||||
|
Version 2.01.10 - 3rd May 2005
|
||||||
|
==============================
|
||||||
|
Don't create backup and archive dirs till needed.
|
||||||
|
Reinstate full PV size when removing from VG.
|
||||||
|
Support loopfiles for testing.
|
||||||
|
Tidy lv_segment interface.
|
||||||
|
pv_segment support.
|
||||||
|
vgchange --physicalextentsize
|
||||||
|
Internal snapshot restructuring.
|
||||||
|
Remove unused internal non-persistent snapshot option.
|
||||||
|
Allow offline extension of snapshot volumes.
|
||||||
|
Move from 2-step to 3-step on-disk metadata commit.
|
||||||
|
Scan ramdisks too and allow non-O_DIRECT fallback.
|
||||||
|
Annotate, tidy and extend list.h.
|
||||||
|
Alignment tidying.
|
||||||
|
Make clvmd work around some "bugs" in gulm's node state notifications.
|
||||||
|
Tidy clvmd's SIGHUP handler
|
||||||
|
|
||||||
|
Version 2.01.09 - 4th April 2005
|
||||||
|
================================
|
||||||
|
Add --ignorelockingfailure to vgmknodes.
|
||||||
|
clvmd: Don't allow user operations to start until the lvm thread is fully up.
|
||||||
|
clvmd-gulm: set KEEPALIVE on sockets.
|
||||||
|
|
||||||
|
Version 2.01.08 - 22nd March 2005
|
||||||
|
=================================
|
||||||
|
Add clustered attribute so vgchange can identify clustered VGs w/o locking.
|
||||||
|
Improve detection of external changes affecting internal cache.
|
||||||
|
Add 'already in device cache' debug message.
|
||||||
|
Add -a to pvdisplay -C.
|
||||||
|
Avoid rmdir opendir error messsages when dir was already removed.
|
||||||
|
Tighten signal handlers.
|
||||||
|
Avoid some compiler warnings.
|
||||||
|
Additional rename failure error message.
|
||||||
|
read/write may be macros.
|
||||||
|
clvmd: don't take out lvm thread lock at startup, it only protects jobs list.
|
||||||
|
|
||||||
|
Version 2.01.07 - 8th March 2005
|
||||||
|
================================
|
||||||
|
Cope with new devices appearing by rescanning /dev if a uuid can't be found.
|
||||||
|
Remove DESTDIR from LVM_SHARED_PATH.
|
||||||
|
clvmd fixes: make FDs close-on-exec
|
||||||
|
gulm unlocks VG & orphan locks at startup in case they are stale
|
||||||
|
gulm now unlocks VG & orphan locks if client dies.
|
||||||
|
|
||||||
|
Version 2.01.06 - 1st March 2005
|
||||||
|
================================
|
||||||
|
Suppress 'open failed' error messages during scanning.
|
||||||
|
Option to suppress warnings of file descriptors left open.
|
||||||
|
Fix default value of metadatacopies in documentation (2->1).
|
||||||
|
Fix clvmd-gulm locking.
|
||||||
|
./configure --enable-debug now enables debugging code in clvmd.
|
||||||
|
Fix clvmd-gulm node up/down code so it actually works.
|
||||||
|
clvmd-gulm now releases locks when shut down.
|
||||||
|
|
||||||
|
Version 2.01.05 - 18th February 2005
|
||||||
|
====================================
|
||||||
|
Static binary invokes dynamic binary if appropriate.
|
||||||
|
Make clvmd config check a little more tolerant.
|
||||||
|
gulm clvmd can now cope with >1 message arriving in a TCP message.
|
||||||
|
|
||||||
|
Version 2.01.04 - 9th February 2005
|
||||||
|
===================================
|
||||||
|
Add fixed offset to imported pool minor numbers.
|
||||||
|
Update binary pathnames in clvmd_init_rhel4.
|
||||||
|
lvm2cmd.so should skip the check for open fds.
|
||||||
|
Remove unused -f from pvmove.
|
||||||
|
Gulm clvmd doesn't report "connection refused" errors.
|
||||||
|
clvmd does a basic config file sanity check at startup.
|
||||||
|
Fix potential thread shutdown race in clvmd.
|
||||||
|
|
||||||
|
Version 2.01.03 - 1st February 2005
|
||||||
|
===================================
|
||||||
|
More 64-bit display/report fixes.
|
||||||
|
More informative startup mesg if can't create /etc/lvm.
|
||||||
|
Fix snapshot device size bug (since 2.01.01).
|
||||||
|
clvmd announces startup and cluster connection in syslog.
|
||||||
|
Gulm clvmd doesn't hang trying to talk to a rebooted node.
|
||||||
|
Gulm clvmd doesn't print cman error on startup.
|
||||||
|
|
||||||
|
Version 2.01.02 - 21st January 2005
|
||||||
|
===================================
|
||||||
|
Update clvmd_init_rhel4: use lvm.static and don't load dlm.
|
||||||
|
Fix some size_t printing.
|
||||||
|
Fix 64 bit xlate consts.
|
||||||
|
Split out pool sptype_names to avoid unused const.
|
||||||
|
Always fail if random id generation fails.
|
||||||
|
Recognise gnbd devices.
|
||||||
|
Fix clvmd startup bug introduced in cman/gulm amalgamation.
|
||||||
|
Improve reporting of node-specific locking errors.
|
||||||
|
|
||||||
|
Version 2.01.01 - 19th January 2005
|
||||||
|
===================================
|
||||||
|
Fix clvmd lv_info_by_lvid open_count.
|
||||||
|
Store snapshot and origin sizes separately.
|
||||||
|
Update vgcreate man page.
|
||||||
|
|
||||||
|
Version 2.01.00 - 17th January 2005
|
||||||
|
===================================
|
||||||
|
Fix vgscan metadata auto-correction.
|
||||||
|
Only ask libdevmapper for open_count when we need it.
|
||||||
|
Adjust RHEL4 clvmd init script priority.
|
||||||
|
Enable building of CMAN & GULM versions of clvmd into a single binary
|
||||||
|
|
||||||
|
Version 2.00.33 - 7th January 2005
|
||||||
|
==================================
|
||||||
|
pvcreate wipes first 4 sectors unless given --zero n.
|
||||||
|
gulm clvmd now uses new ccsd key names.
|
||||||
|
gulm clvmd now doesn't ignore the first node in cluster.conf
|
||||||
|
Improve clvmd failure message if it's already running.
|
||||||
|
Allow user to kill clvmd during initialisation.
|
||||||
|
Fix off-by-one error in cluster_locking that could cause read hangs.
|
||||||
|
|
||||||
|
Version 2.00.32 - 22nd December 2004
|
||||||
|
====================================
|
||||||
|
Drop static/dl restriction for now.
|
||||||
|
Fix an error fprintf.
|
||||||
|
Fix vgdisplay -s. Breaks (undocumented) lvs/pvs/vgs -s instead for now.
|
||||||
|
Fix device reference counting on re-opens.
|
||||||
|
Ignore sysfs symlinks when DT_UNKNOWN.
|
||||||
|
Add clvmd init script for RHEL4.
|
||||||
|
Skip devices that are too small to be PVs.
|
||||||
|
Fix pvchange -x segfault with lvm2-format orphan.
|
||||||
|
Cope with empty msdos partition tables.
|
||||||
|
Add CONTRIBUTORS file.
|
||||||
|
|
||||||
|
Version 2.00.31 - 12th December 2004
|
||||||
|
====================================
|
||||||
|
Reopen RO file descriptors RW if necessary.
|
||||||
|
|
||||||
|
Version 2.00.30 - 10th December 2004
|
||||||
|
====================================
|
||||||
|
Additional device-handling debug messages.
|
||||||
|
Additional verbosity level -vvvv includes line numbers and backtraces.
|
||||||
|
Verbose messages now go to stderr not stdout.
|
||||||
|
Close any stray file descriptors before starting.
|
||||||
|
Refine partitionable checks for certain device types.
|
||||||
|
Allow devices/types to override built-ins.
|
||||||
|
Fix lvreduce man page .i->.I
|
||||||
|
Fix vgsplit man page title.
|
||||||
|
Fix clvmd man makefile.
|
||||||
|
Extend dev_open logging.
|
||||||
|
Make clvmd_fix_conf.sh UNDOable.
|
||||||
|
|
||||||
|
Version 2.00.29 - 27th November 2004
|
||||||
|
====================================
|
||||||
|
xlate compilation fix.
|
||||||
|
|
||||||
|
Version 2.00.28 - 27th November 2004
|
||||||
|
====================================
|
||||||
|
Fix partition table & md signature detection.
|
||||||
|
Minor configure/makefile tidy.
|
||||||
|
Export version.h from tools for clvmd.
|
||||||
|
|
||||||
|
Version 2.00.27 - 24th November 2004
|
||||||
|
====================================
|
||||||
|
Trap large memory allocation requests.
|
||||||
|
Fix to partition table detection code.
|
||||||
|
Improve filter debug mesgs.
|
||||||
|
Make clvmd_fix_conf.sh UNDOable
|
||||||
|
|
||||||
|
Version 2.00.26 - 23rd November 2004
|
||||||
|
====================================
|
||||||
|
Improve pool debugging stats.
|
||||||
|
Detect partition table signature.
|
||||||
|
pvcreate wipes md superblocks. (With --uuid or --restorefile it prompts.)
|
||||||
|
Separate out md superblock detection code.
|
||||||
|
Prevent snapshot origin resizing.
|
||||||
|
Improve a vgremove error message.
|
||||||
|
Update some man pages.
|
||||||
|
Allow y/n with -ae args (exclusive activation).
|
||||||
|
Fixes to lvcreate vgname parsing.
|
||||||
|
Fix dm_name string size calculation.
|
||||||
|
Improve clvmd error reporting during startup.
|
||||||
|
Make clvmd cope with large gaps in node numbers IDs.
|
||||||
|
Make clvmd initialisation cope better with debugging output.
|
||||||
|
Tidy clvmd socket callbacks so all work happens outside main loop.
|
||||||
|
clvmd -V now displays lvm version too.
|
||||||
|
Add optional gulm build for clvmd
|
||||||
|
|
||||||
|
Version 2.00.25 - 29th September 2004
|
||||||
|
=====================================
|
||||||
|
Fix return code from rm_link for vgmknodes.
|
||||||
|
Make clvmd LV hash table thread-safe.
|
||||||
|
Fix clvmd locking so it will lock out multiple users on the same node.
|
||||||
|
Fix clvmd VG locking to it can cope with multiple VG locks.
|
||||||
|
Remove spurious trailing dot in lvreduce man page.
|
||||||
|
Fix vgremove locking.
|
||||||
|
|
||||||
|
Version 2.00.24 - 16th September 2004
|
||||||
|
=====================================
|
||||||
|
Fix pool_empty so it really does empty the memory pool.
|
||||||
|
Rename old segtypes files to segtype.
|
||||||
|
Some fixes to memory debugging code.
|
||||||
|
Exclude internal commands formats & segtypes from install.
|
||||||
|
|
||||||
|
Version 2.00.23 - 15th September 2004
|
||||||
|
=====================================
|
||||||
|
Export dm name build & split functions.
|
||||||
|
Use O_NOATIME on devices if available.
|
||||||
|
Write log message when each segtype/format gets initialised.
|
||||||
|
New commands 'segtypes' and 'formats'.
|
||||||
|
Suppress pvmove abort message in test mode.
|
||||||
|
Improve pvcreate/remove device not found error message.
|
||||||
|
Allow pvmove to move data within the same PV.
|
||||||
|
Describe how pvmove works on man page.
|
||||||
|
Test for incompatible format/segtype combinations in lv_extend.
|
||||||
|
Fix lvchange example on man page.
|
||||||
|
|
||||||
|
Version 2.00.22 - 3rd September 2004
|
||||||
|
====================================
|
||||||
|
Fix /dev/vgname perms.
|
||||||
|
Restructure xlate.h.
|
||||||
|
Add clvmd man page.
|
||||||
|
|
||||||
|
Version 2.00.21 - 19th August 2004
|
||||||
|
==================================
|
||||||
|
Update cnxman-socket.h from cman.
|
||||||
|
Recognise iseries/vd devices.
|
||||||
|
Use 'make install_cluster' to install cluster extensions only.
|
||||||
|
Cope with DT_UNKNOWN in sysfs.
|
||||||
|
Fix extents_moved metadata size comment.
|
||||||
|
Remove duplicate line in pvremove help text.
|
||||||
|
Support variable mirror region size.
|
||||||
|
Support PE ranges in pvmove source PV.
|
||||||
|
Fixes to as-yet-unused LV segment splitting code.
|
||||||
|
Change alloc_areas to pe_ranges and allow suppression of availability checks.
|
||||||
|
Add dev_size column to pvs.
|
||||||
|
Add report columns for in-kernel device number.
|
||||||
|
|
||||||
|
Version 2.00.20 - 3 July 2004
|
||||||
|
=============================
|
||||||
|
More autoconf fixes.
|
||||||
|
Fix device number handling for 2.6 kernels.
|
||||||
|
|
||||||
|
Version 2.00.19 - 29 June 2004
|
||||||
|
==============================
|
||||||
|
Reduce severity of setlocale failure message.
|
||||||
|
Recognise argv[0] "initrd-lvm" (pld-linux).
|
||||||
|
Make -O2 configurable.
|
||||||
|
Added --disable-selinux to configure script.
|
||||||
|
LD_FLAGS->LDFLAGS & LD_DEPS->LDDEPS in configure script.
|
||||||
|
Add init_debug to clvmd.
|
||||||
|
|
||||||
|
Version 2.00.18 - 24 June 2004
|
||||||
|
==============================
|
||||||
|
Fix vgchange activation.
|
||||||
|
Add cluster support.
|
||||||
|
|
||||||
|
Version 2.00.17 - 20 June 2004
|
||||||
|
==============================
|
||||||
|
configure --enable-fsadm to try out fsadm. fsadm is not tested yet.
|
||||||
|
Display all filtered devices, not just PVs, with pvs -a.
|
||||||
|
Fix sync_dir() when no / in filename
|
||||||
|
vgcfgbackup -f accepts template with %s for VG name.
|
||||||
|
Extend hash functions to handle non-null-terminated data.
|
||||||
|
Add local activation support.
|
||||||
|
Tidy relative paths in makefile includes.
|
||||||
|
fsadm support for fsck and resizing - needs testing.
|
||||||
|
Add read-only GFS pool support.
|
||||||
|
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
|
||||||
|
Fix rounding of large diplayed sizes.
|
||||||
|
Suppress decimal point when using units of sectors/bytes.
|
||||||
|
Additional kernel target checks before pvmove & snapshot creation.
|
||||||
|
Add i2o_block.
|
||||||
|
|
||||||
|
Version 2.00.16 - 24 May 2004
|
||||||
|
=============================
|
||||||
|
Set area_count within alloc_lv_segment.
|
||||||
|
Remove error labels from lvresize.
|
||||||
|
Fix a pvs error path.
|
||||||
|
xxchange -ae for exclusive activation.
|
||||||
|
Don't return non-zero status if there aren't any volume groups.
|
||||||
|
Add --alloc argument to tools.
|
||||||
|
Rename allocation policies to contiguous, normal, anywhere, inherit.
|
||||||
|
nextfree becomes normal; anywhere isn't implemented yet.
|
||||||
|
LV inherits allocation policy from VG. Defaults: LV - inherit; VG - normal
|
||||||
|
Additional status character added to vgs to indicate allocation policy.
|
||||||
|
Add reset_fn to external_locking.
|
||||||
|
Ensure presence of virtual targets before attempting activating.
|
||||||
|
Attempt to fix resizing of snapshot origins.
|
||||||
|
Restructure lvresize, bringing it closer to lvcreate.
|
||||||
|
A quick sanity check on vg_disk struct when read in. More checks needed.
|
||||||
|
Only include visible LVs in active/open counts.
|
||||||
|
Add virtual segment types, zero and error. A large sparse device can be
|
||||||
|
constructed as a writeable snapshot of a large zero segment.
|
||||||
|
Add --type to lvcreate/resize.
|
||||||
|
Push lv_create & alloc policy up to tool level.
|
||||||
|
Fix pvdisplay return code.
|
||||||
|
Detect invalid LV names in arg lists.
|
||||||
|
Reporting uses line-at-a-time output.
|
||||||
|
lvm2 format sets unlimited_vols format flag.
|
||||||
|
Internal-only metadata flag support.
|
||||||
|
Basic checking for presence of device-mapper targets.
|
||||||
|
Separate out polldaemon.
|
||||||
|
Revise internal locking semantics.
|
||||||
|
Move find_pv_by_name to library.
|
||||||
|
Rename move->copy.
|
||||||
|
Add devices to segments report.
|
||||||
|
Begin separating out segment code. There's a lot of change here.
|
||||||
|
Compress any (obsolete) long LVM1 pvids encountered.
|
||||||
|
Support for tagged config files.
|
||||||
|
Don't abort operations if selinux present but disabled.
|
||||||
|
Fix typo in configure which left HAVE_LIBDL unset.
|
||||||
|
|
||||||
|
Version 2.00.15 - 19 Apr 2004
|
||||||
|
=============================
|
||||||
|
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
|
||||||
|
|
||||||
|
Version 2.00.14 - 16 Apr 2004
|
||||||
|
=============================
|
||||||
|
Use 64-bit file functions by default.
|
||||||
|
|
||||||
|
Version 2.00.13 - 16 Apr 2004
|
||||||
|
=============================
|
||||||
|
Set devices/md_component_detection = 1 to ignore devices containing md
|
||||||
|
superblocks. [Luca Berra]
|
||||||
|
Ignore error setting selinux file context if fs doesn't support it.
|
||||||
|
|
||||||
|
Version 2.00.12 - 14 Apr 2004
|
||||||
|
=============================
|
||||||
|
Install a default lvm.conf into /etc/lvm if there isn't one already.
|
||||||
|
Allow different installation dir for lvm.static (configure --staticdir=)
|
||||||
|
Fix inverted selinux error check.
|
||||||
|
Recognise power2 in /proc/devices.
|
||||||
|
Fix counting in lvs_in_vg_opened. [It ignored devices open more than once.]
|
||||||
|
|
||||||
|
Version 2.00.11 - 8 Apr 2004
|
||||||
|
============================
|
||||||
|
Set fallback_to_lvm1 in lvm.conf (or configure --enable-lvm1_fallback)
|
||||||
|
to run lvm1 binaries if running a 2.4 kernel without device-mapper.
|
||||||
|
|
||||||
|
Version 2.00.10 - 7 Apr 2004
|
||||||
|
============================
|
||||||
|
More fixes for static build.
|
||||||
|
Add basic selinux support.
|
||||||
|
Fix sysfs detection.
|
||||||
|
|
||||||
|
Version 2.00.09 - 31 Mar 2004
|
||||||
|
=============================
|
||||||
|
Update copyright notices for Red Hat.
|
||||||
|
Fix vgmknodes to remove dud /dev/mapper entries. (libdevmapper update reqd).
|
||||||
|
Add LVM1-style colon output to vgdisplay.
|
||||||
|
lvchange --refresh to reload active LVs.
|
||||||
|
Add string display to memory leak dump.
|
||||||
|
Add locking flags & memlock option.
|
||||||
|
Add list_versions to library.
|
||||||
|
Ignore open hidden LVs when checking if deactivation is OK.
|
||||||
|
Suppress move percentage when device inactive.
|
||||||
|
Add lv_info_by_lvid.
|
||||||
|
Various tidy-ups to the build process.
|
||||||
|
Rebaseline internal verbose level.
|
||||||
|
Add --nolocking option for read operations if locking is failing.
|
||||||
|
Add option to compile into a library.
|
||||||
|
When compiled without libdevmapper, only print warning message once.
|
||||||
|
Fix lvreduce PV extent calculations.
|
||||||
|
Fix DESTDIR to work with configure path overrides.
|
||||||
|
Always use / as config file separator & rename internal config file variables.
|
||||||
|
Add support for tagging PV/VG/LVs and hosts.
|
||||||
|
Fix rare bug in recognition of long cmdline argument forms.
|
||||||
|
Add basic internationalisation infrastructure.
|
||||||
|
Don't recurse symlinked dirs such as /dev/fd on 2.6 kernels.
|
||||||
|
Update autoconf files.
|
||||||
|
Add sysfs block device filtering for 2.6 kernels.
|
||||||
|
Update refs for move to sources.redhat.com.
|
||||||
|
|
||||||
|
Friday 14th November 2003
|
||||||
|
=========================
|
||||||
|
Some bug fixes & minor enhancements, including:
|
||||||
|
Backwards compatibility with LVM1 metadata improved.
|
||||||
|
Missing man pages written.
|
||||||
|
Tool error codes made more consistent.
|
||||||
|
vgmknodes written.
|
||||||
|
O_DIRECT can be turned off if it doesn't work in your kernel.
|
||||||
|
dumpconfig to display the active configuration file
|
||||||
|
|
||||||
|
You need to update libdevmapper before using 'vgmknodes' or 'vgscan --mknodes'.
|
||||||
|
If your root filesystem is on an LV, you should run one of those two
|
||||||
|
commands to fix up the special files in /dev in your real root filesystem
|
||||||
|
after finishing with your initrd. Also, remember you can use
|
||||||
|
'vgchange --ignorelockingfailure' on your initrd if the tool fails because
|
||||||
|
it can't write a lock file to a read-only filesystem.
|
||||||
|
|
||||||
|
Wednesday 30th April 2003
|
||||||
|
=========================
|
||||||
|
A pvmove implementation is now available for the new metadata format.
|
||||||
|
|
||||||
|
When running a command that allocates space (e.g. lvcreate), you can now
|
||||||
|
restrict not only which disk(s) may be used but also the Physical Extents
|
||||||
|
on those disks. e.g. lvcreate -L 10 vg1 /dev/hda6:1000-2000:3000-4000
|
||||||
|
|
||||||
|
|
||||||
|
Monday 18th November 2002
|
||||||
|
========================
|
||||||
|
|
||||||
|
The new format of LVM metadata is ready for you to test!
|
||||||
|
We expect it to be more efficient and more robust than the original format.
|
||||||
|
It's more compact and supports transactional changes and replication.
|
||||||
|
Should things go wrong on a system, it's human-readable (and editable).
|
||||||
|
|
||||||
|
Please report any problems you find to the mailing list,
|
||||||
|
linux-lvm@sistina.com. The software has NOT yet been thoroughly
|
||||||
|
tested and so quite possibly there'll still be some bugs in it.
|
||||||
|
Be aware of the disclaimer in the COPYING file.
|
||||||
|
|
||||||
|
While testing, we recommend turning logging on in the configuration file
|
||||||
|
to provide us with diagnostic information:
|
||||||
|
log {
|
||||||
|
file="/tmp/lvm2.log"
|
||||||
|
level=7
|
||||||
|
activation=1
|
||||||
|
}
|
||||||
|
|
||||||
|
You should schedule regular backups of your configuration file and
|
||||||
|
metadata backups and archives (normally kept under /etc/lvm).
|
||||||
|
|
||||||
|
Please read docs/example.conf and "man lvm.conf" to find out more about
|
||||||
|
the configuration file.
|
||||||
|
|
||||||
|
To convert an existing volume group called vg1 to the new format using
|
||||||
|
the default settings, use "vgconvert -M2 vg1". See "man vgconvert".
|
||||||
|
|
||||||
|
-M (or --metadatatype in its long form) is a new flag to indicate which
|
||||||
|
format of metadata the command should use for anything it creates.
|
||||||
|
Currently, the valid types are "lvm1" and "lvm2" and they can be
|
||||||
|
abbreviated to "1" and "2" respectively. The default value for this
|
||||||
|
flag can be changed in the global section in the config file.
|
||||||
|
|
||||||
|
Backwards-compatible support for the original LVM1 metadata format is
|
||||||
|
maintained, but it can be moved into a shared library or removed
|
||||||
|
completely with configure's --with-lvm1 option.
|
||||||
|
|
||||||
|
Under LVM2, the basic unit of metadata is the volume group. Different
|
||||||
|
volume groups can use different formats of metadata - vg1 could use
|
||||||
|
the original LVM1 format while vg2 used the new format - but you can't
|
||||||
|
mix formats within a volume group. So to add a PV to an LVM2-format
|
||||||
|
volume group you must run "pvcreate -M2" on it, followed by "vgextend".
|
||||||
|
|
||||||
|
With LVM2-format metadata, lvextend will let you specify striping
|
||||||
|
parameters. So an LV could consist of two or more "segments" - the
|
||||||
|
first segment could have 3 stripes while the second segment has just 2.
|
||||||
|
|
||||||
|
LVM2 maintains a backup of the current metadata for each volume group
|
||||||
|
in /etc/lvm/backup, and puts copies of previous versions in
|
||||||
|
/etc/lvm/archive. "vgcfgbackup" and "vgcfgrestore" can be used to
|
||||||
|
create and restore from these files. If you fully understand what
|
||||||
|
you're doing, metadata can be changed by editing a copy of a current
|
||||||
|
backup file and using vgcfgrestore to reload it.
|
||||||
|
|
||||||
|
Please read the pvcreate man page for more information on the new
|
||||||
|
format for metadata.
|
||||||
|
|
||||||
|
All tools that can change things have a --test flag which can be used
|
||||||
|
to check the effect of a set of cmdline args without really making the
|
||||||
|
changes.
|
||||||
|
|
||||||
|
|
||||||
|
What's not finished?
|
||||||
|
====================
|
||||||
|
The internal cache. If you turn on debugging output you'll see lots of
|
||||||
|
repeated messages, many of which will eventually get optimised out.
|
||||||
|
|
||||||
|
--test sometimes causes a command to fail (e.g. vgconvert --test) even
|
||||||
|
though the real command would work: again, fixing this is waiting for
|
||||||
|
the work on the cache.
|
||||||
|
|
||||||
|
Several of the tools do not yet contain the logic to handle full
|
||||||
|
recovery: combinations of pvcreate and vgcfgrestore may sometimes be
|
||||||
|
needed to restore metadata if a tool gets interrupted or crashes or
|
||||||
|
finds something unexpected. This applies particularly to tools that
|
||||||
|
work on more than one volume group at once (e.g. vgsplit).
|
||||||
|
|
||||||
|
Display output. Some metadata information cannot yet be displayed.
|
||||||
|
|
||||||
|
Recovery tools to salvage "lost" metadata directly from the disks:
|
||||||
|
but we hope the new format will mean such tools are hardly ever needed!
|
||||||
|
|
||||||
274
WHATS_NEW_DM
Normal file
274
WHATS_NEW_DM
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
Version 1.02.19 -
|
||||||
|
====================================
|
||||||
|
Fix a few leaks in reporting error paths. [1.02.15+]
|
||||||
|
|
||||||
|
Version 1.02.18 - 13th February 2007
|
||||||
|
====================================
|
||||||
|
Improve dmeventd messaging protocol: drain pipe and tag messages.
|
||||||
|
|
||||||
|
Version 1.02.17 - 29th January 2007
|
||||||
|
===================================
|
||||||
|
Add recent reporting options to dmsetup man page.
|
||||||
|
Revise some report fields names.
|
||||||
|
Add dmsetup 'help' command and update usage text.
|
||||||
|
Use fixed-size fields in report interface and reorder.
|
||||||
|
|
||||||
|
Version 1.02.16 - 25th January 2007
|
||||||
|
===================================
|
||||||
|
Add some missing close() and fclose() return value checks.
|
||||||
|
Migrate dmsetup column-based output over to new libdevmapper report framework.
|
||||||
|
Add descriptions to reporting field definitions.
|
||||||
|
Add a dso-private variable to dmeventd dso interface.
|
||||||
|
Add dm_event_handler_[gs]et_timeout functions.
|
||||||
|
Streamline dm_report_field_* interface.
|
||||||
|
Add cmdline debug & version options to dmeventd.
|
||||||
|
Add DM_LIB_VERSION definition to configure.h.
|
||||||
|
Suppress 'Unrecognised field' error if report field is 'help'.
|
||||||
|
Add --separator and --sort to dmsetup (unused).
|
||||||
|
Make alignment flag optional when specifying report fields.
|
||||||
|
|
||||||
|
Version 1.02.15 - 17th January 2007
|
||||||
|
===================================
|
||||||
|
Add basic reporting functions to libdevmapper.
|
||||||
|
Fix a malloc error path in dmsetup message.
|
||||||
|
More libdevmapper-event interface changes and fixes.
|
||||||
|
Rename dm_saprintf() to dm_asprintf().
|
||||||
|
Report error if NULL pointer is supplied to dm_strdup_aux().
|
||||||
|
Reinstate dm_event_get_registered_device.
|
||||||
|
|
||||||
|
Version 1.02.14 - 11th January 2007
|
||||||
|
===================================
|
||||||
|
Add dm_saprintf().
|
||||||
|
Use CFLAGS when linking so mixed sparc builds can supply -m64.
|
||||||
|
Add dm_tree_use_no_flush_suspend().
|
||||||
|
Lots of dmevent changes including revised interface.
|
||||||
|
Export dm_basename().
|
||||||
|
Cope with a trailing space when comparing tables prior to possible reload.
|
||||||
|
Fix dmeventd to cope if monitored device disappears.
|
||||||
|
|
||||||
|
Version 1.02.13 - 28 Nov 2006
|
||||||
|
=============================
|
||||||
|
Update dmsetup man page (setgeometry & message).
|
||||||
|
Fix dmsetup free after getline with debug.
|
||||||
|
Suppress encryption key in 'dmsetup table' output unless --showkeys supplied.
|
||||||
|
|
||||||
|
Version 1.02.12 - 13 Oct 2006
|
||||||
|
=============================
|
||||||
|
Avoid deptree attempting to suspend a device that's already suspended.
|
||||||
|
|
||||||
|
Version 1.02.11 - 12 Oct 2006
|
||||||
|
==============================
|
||||||
|
Add suspend noflush support.
|
||||||
|
Add basic dmsetup loop support.
|
||||||
|
Switch dmsetup to use dm_malloc and dm_free.
|
||||||
|
|
||||||
|
Version 1.02.10 - 19 Sep 2006
|
||||||
|
=============================
|
||||||
|
Add dm_snprintf(), dm_split_words() and dm_split_lvm_name() to libdevmapper.
|
||||||
|
Reorder mm bounds_check code to reduce window for a dmeventd race.
|
||||||
|
|
||||||
|
Version 1.02.09 - 15 Aug 2006
|
||||||
|
=============================
|
||||||
|
Add --table argument to dmsetup for a one-line table.
|
||||||
|
Abort if errors are found during cmdline option processing.
|
||||||
|
Add lockfs indicator to debug output.
|
||||||
|
|
||||||
|
Version 1.02.08 - 17 July 2006
|
||||||
|
==============================
|
||||||
|
Append full patch to check in emails.
|
||||||
|
Avoid duplicate dmeventd subdir with 'make distclean'.
|
||||||
|
Update dmsetup man page.
|
||||||
|
Add --force to dmsetup remove* to load error target.
|
||||||
|
dmsetup remove_all also performs mknodes.
|
||||||
|
Don't suppress identical table reloads if permission changes.
|
||||||
|
Fix corelog segment line.
|
||||||
|
Suppress some compiler warnings.
|
||||||
|
|
||||||
|
Version 1.02.07 - 11 May 2006
|
||||||
|
=============================
|
||||||
|
Add DM_CORELOG flag to dm_tree_node_add_mirror_target().
|
||||||
|
Avoid a dmeventd compiler warning.
|
||||||
|
|
||||||
|
Version 1.02.06 - 10 May 2006
|
||||||
|
=============================
|
||||||
|
Move DEFS into configure.h.
|
||||||
|
Fix leaks in error paths found by coverity.
|
||||||
|
Remove dmsetup line buffer limitation.
|
||||||
|
|
||||||
|
Version 1.02.05 - 19 Apr 2006
|
||||||
|
=============================
|
||||||
|
Separate install_include target in makefiles.
|
||||||
|
Separate out DEFS from CFLAGS.
|
||||||
|
Support pkg-config.
|
||||||
|
Check for libsepol.
|
||||||
|
|
||||||
|
Version 1.02.04 - 14 Apr 2006
|
||||||
|
=============================
|
||||||
|
Bring dmsetup man page up-to-date.
|
||||||
|
Use name-based device refs if kernel doesn't support device number refs.
|
||||||
|
Fix memory leak (struct dm_ioctl) when struct dm_task is reused.
|
||||||
|
If _create_and_load_v4 fails part way through, revert the creation.
|
||||||
|
dmeventd thread/fifo fixes.
|
||||||
|
Add file & line to dm_strdup_aux().
|
||||||
|
Add setgeometry.
|
||||||
|
|
||||||
|
Version 1.02.03 - 7 Feb 2006
|
||||||
|
============================
|
||||||
|
Add exported functions to set uid, gid and mode.
|
||||||
|
Rename _log to dm_log and export.
|
||||||
|
Add dm_tree_skip_lockfs.
|
||||||
|
Fix dm_strdup debug definition.
|
||||||
|
Fix hash function to avoid using a negative array offset.
|
||||||
|
Don't inline _find in hash.c and tidy signed/unsigned etc.
|
||||||
|
Fix libdevmapper.h #endif.
|
||||||
|
Fix dmsetup version driver version.
|
||||||
|
Add sync, nosync and block_on_error mirror log parameters.
|
||||||
|
Add hweight32.
|
||||||
|
Fix dmeventd build.
|
||||||
|
|
||||||
|
Version 1.02.02 - 2 Dec 2005
|
||||||
|
============================
|
||||||
|
dmeventd added.
|
||||||
|
Export dm_task_update_nodes.
|
||||||
|
Use names instead of numbers in messages when ioctls fail.
|
||||||
|
|
||||||
|
Version 1.02.01 - 23 Nov 2005
|
||||||
|
=============================
|
||||||
|
Resume snapshot-origins last.
|
||||||
|
Drop leading zeros from dm_format_dev.
|
||||||
|
Suppress attempt to reload identical table.
|
||||||
|
Additional LVM- prefix matching for transitional period.
|
||||||
|
|
||||||
|
Version 1.02.00 - 10 Nov 2005
|
||||||
|
=============================
|
||||||
|
Added activation functions to library.
|
||||||
|
Added return macros.
|
||||||
|
Also suppress error if device doesn't exist with DM_DEVICE_STATUS.
|
||||||
|
Export dm_set_selinux_context().
|
||||||
|
Add dm_driver_version().
|
||||||
|
Added dependency tree functions to library.
|
||||||
|
Added hash, bitset, pool, dbg_malloc to library.
|
||||||
|
Added ls --tree to dmsetup.
|
||||||
|
Added dmsetup --nolockfs support for suspend/reload.
|
||||||
|
|
||||||
|
Version 1.01.05 - 26 Sep 2005
|
||||||
|
=============================
|
||||||
|
Resync list.h with LVM2.
|
||||||
|
Remember increased buffer size and use for subsequent calls.
|
||||||
|
On 'buffer full' condition, double buffer size and repeat ioctl.
|
||||||
|
Fix termination of getopt_long() option array.
|
||||||
|
Report 'buffer full' condition with v4 ioctl as well as with v1.
|
||||||
|
|
||||||
|
Version 1.01.04 - 2 Aug 2005
|
||||||
|
============================
|
||||||
|
Fix dmsetup ls -j and status --target with empty table.
|
||||||
|
|
||||||
|
Version 1.01.03 - 13 Jun 2005
|
||||||
|
=============================
|
||||||
|
Use matchpathcon mode parameter.
|
||||||
|
Fix configure script to re-enable selinux.
|
||||||
|
|
||||||
|
Version 1.01.02 - 17 May 2005
|
||||||
|
=============================
|
||||||
|
Call dm_lib_exit() and dm_lib_release() automatically now.
|
||||||
|
Add --target <target_type> filter to dmsetup table/status/ls.
|
||||||
|
Add --exec <command> to dmsetup ls.
|
||||||
|
Fix dmsetup getopt_long usage.
|
||||||
|
|
||||||
|
Version 1.01.01 - 29 Mar 2005
|
||||||
|
=============================
|
||||||
|
Update dmsetup man page.
|
||||||
|
Drop-in devmap_name replacement.
|
||||||
|
Add option to compile without ioctl for testing.
|
||||||
|
Fix DM_LIB_VERSION sed.
|
||||||
|
|
||||||
|
Version 1.01.00 - 17 Jan 2005
|
||||||
|
=============================
|
||||||
|
Add dm_task_no_open_count() to skip getting open_count.
|
||||||
|
|
||||||
|
Version 1.00.21 - 7 Jan 2005
|
||||||
|
============================
|
||||||
|
Fix /proc/devices parsing.
|
||||||
|
|
||||||
|
Version 1.00.20 - 6 Jan 2005
|
||||||
|
============================
|
||||||
|
Attempt to fix /dev/mapper/control transparently if it's wrong.
|
||||||
|
Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
|
||||||
|
Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
|
||||||
|
Add --noheadings columns option for colon-separated dmsetup output.
|
||||||
|
Support device referencing by uuid or major/minor.
|
||||||
|
Warn if kernel data didn't fit in buffer.
|
||||||
|
Fix a printf.
|
||||||
|
|
||||||
|
Version 1.00.19 - 3 July 2004
|
||||||
|
=============================
|
||||||
|
More autoconf fixes.
|
||||||
|
Fix a dmsetup newline.
|
||||||
|
Fix device number handling for 2.6 kernels.
|
||||||
|
|
||||||
|
Version 1.00.18 - 20 Jun 2004
|
||||||
|
=============================
|
||||||
|
Fix a uuid free in libdm-iface.
|
||||||
|
Fix a targets string size calc in driver.
|
||||||
|
Add -c to dmsetup for column-based output.
|
||||||
|
Add target message-passing ioctl.
|
||||||
|
|
||||||
|
Version 1.00.17 - 17 Apr 2004
|
||||||
|
=============================
|
||||||
|
configure --with-owner= --with-group= to avoid -o and -g args to 'install'
|
||||||
|
Fix library selinux linking.
|
||||||
|
|
||||||
|
Version 1.00.16 - 16 Apr 2004
|
||||||
|
=============================
|
||||||
|
Ignore error setting selinux file context if fs doesn't support it.
|
||||||
|
|
||||||
|
Version 1.00.15 - 7 Apr 2004
|
||||||
|
============================
|
||||||
|
Fix status overflow check in kernel patches.
|
||||||
|
|
||||||
|
Version 1.00.14 - 6 Apr 2004
|
||||||
|
============================
|
||||||
|
Fix static selinux build.
|
||||||
|
|
||||||
|
Version 1.00.13 - 6 Apr 2004
|
||||||
|
============================
|
||||||
|
Add some basic selinux support.
|
||||||
|
|
||||||
|
Version 1.00.12 - 6 Apr 2004
|
||||||
|
============================
|
||||||
|
Fix dmsetup.static install.
|
||||||
|
|
||||||
|
Version 1.00.11 - 5 Apr 2004
|
||||||
|
============================
|
||||||
|
configure --enable-static_link does static build in addition to dynamic.
|
||||||
|
Moved Makefile library targets definition into template.
|
||||||
|
|
||||||
|
Version 1.00.10 - 2 Apr 2004
|
||||||
|
============================
|
||||||
|
Fix DESTDIR handling.
|
||||||
|
Static build installs to dmsetup.static.
|
||||||
|
Basic support for internationalisation.
|
||||||
|
Minor Makefile tidy-ups/fixes.
|
||||||
|
|
||||||
|
Version 1.00.09 - 31 Mar 2004
|
||||||
|
=============================
|
||||||
|
Update copyright notices to Red Hat.
|
||||||
|
Move full mknodes functionality from dmsetup into libdevmapper.
|
||||||
|
Avoid sscanf %as for uClibc compatibility.
|
||||||
|
Cope if DM_LIST_VERSIONS is not defined.
|
||||||
|
Add DM_LIST_VERSIONS functionality to kernel patches.
|
||||||
|
Generate new kernel patches for 2.4.26-rc1.
|
||||||
|
|
||||||
|
Version 1.00.08 - 27 Feb 2004
|
||||||
|
=============================
|
||||||
|
Added 'dmsetup targets'.
|
||||||
|
Added event_nr support to 'dmsetup wait'.
|
||||||
|
Updated dmsetup man page.
|
||||||
|
Allow logging function to be reset to use internal one.
|
||||||
|
Bring log macros in line with LVM2 ones.
|
||||||
|
Added 'make install_static_lib' which installs libdevmapper.a.
|
||||||
|
Made configure/makefiles closer to LVM2 versions.
|
||||||
|
Fixed DESTDIR for make install/install_static_lib.
|
||||||
|
Updated README/INSTALL to reflect move to sources.redhat.com.
|
||||||
|
Updated autoconf files to 2003-06-17.
|
||||||
|
|
||||||
1082
autoconf/config.guess
vendored
1082
autoconf/config.guess
vendored
File diff suppressed because it is too large
Load Diff
560
autoconf/config.sub
vendored
560
autoconf/config.sub
vendored
@@ -1,6 +1,10 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Configuration validation subroutine script, version 1.1.
|
# Configuration validation subroutine script.
|
||||||
# Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc.
|
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||||
|
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
timestamp='2003-06-17'
|
||||||
|
|
||||||
# This file is (in principle) common to ALL GNU software.
|
# This file is (in principle) common to ALL GNU software.
|
||||||
# The presence of a machine in this file suggests that SOME GNU software
|
# The presence of a machine in this file suggests that SOME GNU software
|
||||||
# can handle that machine. It does not imply ALL GNU software can.
|
# can handle that machine. It does not imply ALL GNU software can.
|
||||||
@@ -25,6 +29,9 @@
|
|||||||
# configuration script generated by Autoconf, you may include it under
|
# configuration script generated by Autoconf, you may include it under
|
||||||
# the same distribution terms that you use for the rest of that program.
|
# the same distribution terms that you use for the rest of that program.
|
||||||
|
|
||||||
|
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||||
|
# diff and a properly formatted ChangeLog entry.
|
||||||
|
#
|
||||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||||
# Supply the specified configuration type as an argument.
|
# Supply the specified configuration type as an argument.
|
||||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||||
@@ -45,30 +52,73 @@
|
|||||||
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
||||||
# It is wrong to echo any other type of specification.
|
# It is wrong to echo any other type of specification.
|
||||||
|
|
||||||
if [ x$1 = x ]
|
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||||
then
|
|
||||||
echo Configuration name missing. 1>&2
|
|
||||||
echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
|
|
||||||
echo "or $0 ALIAS" 1>&2
|
|
||||||
echo where ALIAS is a recognized configuration type. 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# First pass through any local machine types.
|
usage="\
|
||||||
case $1 in
|
Usage: $0 [OPTION] CPU-MFR-OPSYS
|
||||||
*local*)
|
$0 [OPTION] ALIAS
|
||||||
echo $1
|
|
||||||
exit 0
|
Canonicalize a configuration name.
|
||||||
;;
|
|
||||||
*)
|
Operation modes:
|
||||||
;;
|
-h, --help print this help, then exit
|
||||||
|
-t, --time-stamp print date of last modification, then exit
|
||||||
|
-v, --version print version number, then exit
|
||||||
|
|
||||||
|
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
|
||||||
|
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."
|
||||||
|
|
||||||
|
help="
|
||||||
|
Try \`$me --help' for more information."
|
||||||
|
|
||||||
|
# Parse command line
|
||||||
|
while test $# -gt 0 ; do
|
||||||
|
case $1 in
|
||||||
|
--time-stamp | --time* | -t )
|
||||||
|
echo "$timestamp" ; exit 0 ;;
|
||||||
|
--version | -v )
|
||||||
|
echo "$version" ; exit 0 ;;
|
||||||
|
--help | --h* | -h )
|
||||||
|
echo "$usage"; exit 0 ;;
|
||||||
|
-- ) # Stop option processing
|
||||||
|
shift; break ;;
|
||||||
|
- ) # Use stdin as input.
|
||||||
|
break ;;
|
||||||
|
-* )
|
||||||
|
echo "$me: invalid option $1$help"
|
||||||
|
exit 1 ;;
|
||||||
|
|
||||||
|
*local*)
|
||||||
|
# First pass through any local machine types.
|
||||||
|
echo $1
|
||||||
|
exit 0;;
|
||||||
|
|
||||||
|
* )
|
||||||
|
break ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
case $# in
|
||||||
|
0) echo "$me: missing argument$help" >&2
|
||||||
|
exit 1;;
|
||||||
|
1) ;;
|
||||||
|
*) echo "$me: too many arguments$help" >&2
|
||||||
|
exit 1;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
|
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
|
||||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||||
case $maybe_os in
|
case $maybe_os in
|
||||||
linux-gnu*)
|
nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||||
os=-$maybe_os
|
os=-$maybe_os
|
||||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||||
;;
|
;;
|
||||||
@@ -94,7 +144,7 @@ case $os in
|
|||||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||||
-apple)
|
-apple | -axis)
|
||||||
os=
|
os=
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
;;
|
;;
|
||||||
@@ -105,9 +155,17 @@ case $os in
|
|||||||
-scout)
|
-scout)
|
||||||
;;
|
;;
|
||||||
-wrs)
|
-wrs)
|
||||||
os=vxworks
|
os=-vxworks
|
||||||
basic_machine=$1
|
basic_machine=$1
|
||||||
;;
|
;;
|
||||||
|
-chorusos*)
|
||||||
|
os=-chorusos
|
||||||
|
basic_machine=$1
|
||||||
|
;;
|
||||||
|
-chorusrdb)
|
||||||
|
os=-chorusrdb
|
||||||
|
basic_machine=$1
|
||||||
|
;;
|
||||||
-hiux*)
|
-hiux*)
|
||||||
os=-hiuxwe2
|
os=-hiuxwe2
|
||||||
;;
|
;;
|
||||||
@@ -156,33 +214,72 @@ case $os in
|
|||||||
-psos*)
|
-psos*)
|
||||||
os=-psos
|
os=-psos
|
||||||
;;
|
;;
|
||||||
|
-mint | -mint[0-9]*)
|
||||||
|
basic_machine=m68k-atari
|
||||||
|
os=-mint
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Decode aliases for certain CPU-COMPANY combinations.
|
# Decode aliases for certain CPU-COMPANY combinations.
|
||||||
case $basic_machine in
|
case $basic_machine in
|
||||||
# Recognize the basic CPU types without company name.
|
# Recognize the basic CPU types without company name.
|
||||||
# Some are omitted here because they have special meanings below.
|
# Some are omitted here because they have special meanings below.
|
||||||
tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
|
1750a | 580 \
|
||||||
| arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
|
| a29k \
|
||||||
| 580 | i960 | h8300 \
|
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||||
| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
|
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||||
| alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \
|
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||||
| we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
|
| c4x | clipper \
|
||||||
| 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
|
| d10v | d30v | dlx | dsp16xx \
|
||||||
| mips64orion | mips64orionel | mipstx39 | mipstx39el \
|
| fr30 | frv \
|
||||||
| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
|
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||||
| mips64vr5000 | miprs64vr5000el | mcore \
|
| i370 | i860 | i960 | ia64 \
|
||||||
| sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
|
| ip2k \
|
||||||
| thumb | d10v)
|
| m32r | m68000 | m68k | m88k | mcore \
|
||||||
|
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||||
|
| mips16 \
|
||||||
|
| mips64 | mips64el \
|
||||||
|
| mips64vr | mips64vrel \
|
||||||
|
| mips64orion | mips64orionel \
|
||||||
|
| mips64vr4100 | mips64vr4100el \
|
||||||
|
| mips64vr4300 | mips64vr4300el \
|
||||||
|
| mips64vr5000 | mips64vr5000el \
|
||||||
|
| mipsisa32 | mipsisa32el \
|
||||||
|
| mipsisa32r2 | mipsisa32r2el \
|
||||||
|
| mipsisa64 | mipsisa64el \
|
||||||
|
| mipsisa64sb1 | mipsisa64sb1el \
|
||||||
|
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||||
|
| mipstx39 | mipstx39el \
|
||||||
|
| mn10200 | mn10300 \
|
||||||
|
| msp430 \
|
||||||
|
| ns16k | ns32k \
|
||||||
|
| openrisc | or32 \
|
||||||
|
| pdp10 | pdp11 | pj | pjl \
|
||||||
|
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||||
|
| pyramid \
|
||||||
|
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||||
|
| sh64 | sh64le \
|
||||||
|
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
||||||
|
| strongarm \
|
||||||
|
| tahoe | thumb | tic4x | tic80 | tron \
|
||||||
|
| v850 | v850e \
|
||||||
|
| we32k \
|
||||||
|
| x86 | xscale | xstormy16 | xtensa \
|
||||||
|
| z8k)
|
||||||
basic_machine=$basic_machine-unknown
|
basic_machine=$basic_machine-unknown
|
||||||
;;
|
;;
|
||||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65)
|
m6811 | m68hc11 | m6812 | m68hc12)
|
||||||
|
# Motorola 68HC11/12.
|
||||||
|
basic_machine=$basic_machine-unknown
|
||||||
|
os=-none
|
||||||
|
;;
|
||||||
|
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
||||||
;;
|
;;
|
||||||
|
|
||||||
# We use `pc' rather than `unknown'
|
# We use `pc' rather than `unknown'
|
||||||
# because (1) that's what they normally are, and
|
# because (1) that's what they normally are, and
|
||||||
# (2) the word "unknown" tends to confuse beginning users.
|
# (2) the word "unknown" tends to confuse beginning users.
|
||||||
i[34567]86)
|
i*86 | x86_64)
|
||||||
basic_machine=$basic_machine-pc
|
basic_machine=$basic_machine-pc
|
||||||
;;
|
;;
|
||||||
# Object if more than one company name word.
|
# Object if more than one company name word.
|
||||||
@@ -191,24 +288,60 @@ case $basic_machine in
|
|||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
# Recognize the basic CPU types with company name.
|
# Recognize the basic CPU types with company name.
|
||||||
# FIXME: clean up the formatting here.
|
580-* \
|
||||||
vax-* | tahoe-* | i[34567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
|
| a29k-* \
|
||||||
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
|
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||||
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
|
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||||
| power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
|
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||||
| xmp-* | ymp-* \
|
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||||
| hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
|
| avr-* \
|
||||||
| alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \
|
| bs2000-* \
|
||||||
| we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
|
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||||
| clipper-* | orion-* \
|
| clipper-* | cydra-* \
|
||||||
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
|
| d10v-* | d30v-* | dlx-* \
|
||||||
| sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
|
| elxsi-* \
|
||||||
| mips64el-* | mips64orion-* | mips64orionel-* \
|
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||||
| mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
|
| h8300-* | h8500-* \
|
||||||
| mipstx39-* | mipstx39el-* | mcore-* \
|
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||||
| f301-* | armv*-* | t3e-* \
|
| i*86-* | i860-* | i960-* | ia64-* \
|
||||||
| m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
|
| ip2k-* \
|
||||||
| thumb-* | v850-* | d30v-* | tic30-* | c30-* )
|
| m32r-* \
|
||||||
|
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||||
|
| m88110-* | m88k-* | mcore-* \
|
||||||
|
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||||
|
| mips16-* \
|
||||||
|
| mips64-* | mips64el-* \
|
||||||
|
| mips64vr-* | mips64vrel-* \
|
||||||
|
| mips64orion-* | mips64orionel-* \
|
||||||
|
| mips64vr4100-* | mips64vr4100el-* \
|
||||||
|
| mips64vr4300-* | mips64vr4300el-* \
|
||||||
|
| mips64vr5000-* | mips64vr5000el-* \
|
||||||
|
| mipsisa32-* | mipsisa32el-* \
|
||||||
|
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||||
|
| mipsisa64-* | mipsisa64el-* \
|
||||||
|
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||||
|
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||||
|
| mipstx39-* | mipstx39el-* \
|
||||||
|
| msp430-* \
|
||||||
|
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
|
||||||
|
| orion-* \
|
||||||
|
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||||
|
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||||
|
| pyramid-* \
|
||||||
|
| romp-* | rs6000-* \
|
||||||
|
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||||
|
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||||
|
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
||||||
|
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||||
|
| tahoe-* | thumb-* \
|
||||||
|
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||||
|
| tron-* \
|
||||||
|
| v850-* | v850e-* | vax-* \
|
||||||
|
| we32k-* \
|
||||||
|
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
|
||||||
|
| xtensa-* \
|
||||||
|
| ymp-* \
|
||||||
|
| z8k-*)
|
||||||
;;
|
;;
|
||||||
# Recognize the various machine names and aliases which stand
|
# Recognize the various machine names and aliases which stand
|
||||||
# for a CPU type and a company and sometimes even an OS.
|
# for a CPU type and a company and sometimes even an OS.
|
||||||
@@ -240,19 +373,22 @@ case $basic_machine in
|
|||||||
basic_machine=a29k-none
|
basic_machine=a29k-none
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
|
amd64)
|
||||||
|
basic_machine=x86_64-pc
|
||||||
|
;;
|
||||||
amdahl)
|
amdahl)
|
||||||
basic_machine=580-amdahl
|
basic_machine=580-amdahl
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
amiga | amiga-*)
|
amiga | amiga-*)
|
||||||
basic_machine=m68k-cbm
|
basic_machine=m68k-unknown
|
||||||
;;
|
;;
|
||||||
amigaos | amigados)
|
amigaos | amigados)
|
||||||
basic_machine=m68k-cbm
|
basic_machine=m68k-unknown
|
||||||
os=-amigaos
|
os=-amigaos
|
||||||
;;
|
;;
|
||||||
amigaunix | amix)
|
amigaunix | amix)
|
||||||
basic_machine=m68k-cbm
|
basic_machine=m68k-unknown
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
;;
|
;;
|
||||||
apollo68)
|
apollo68)
|
||||||
@@ -271,6 +407,10 @@ case $basic_machine in
|
|||||||
basic_machine=ns32k-sequent
|
basic_machine=ns32k-sequent
|
||||||
os=-dynix
|
os=-dynix
|
||||||
;;
|
;;
|
||||||
|
c90)
|
||||||
|
basic_machine=c90-cray
|
||||||
|
os=-unicos
|
||||||
|
;;
|
||||||
convex-c1)
|
convex-c1)
|
||||||
basic_machine=c1-convex
|
basic_machine=c1-convex
|
||||||
os=-bsd
|
os=-bsd
|
||||||
@@ -291,27 +431,30 @@ case $basic_machine in
|
|||||||
basic_machine=c38-convex
|
basic_machine=c38-convex
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
cray | ymp)
|
cray | j90)
|
||||||
basic_machine=ymp-cray
|
basic_machine=j90-cray
|
||||||
os=-unicos
|
|
||||||
;;
|
|
||||||
cray2)
|
|
||||||
basic_machine=cray2-cray
|
|
||||||
os=-unicos
|
|
||||||
;;
|
|
||||||
[ctj]90-cray)
|
|
||||||
basic_machine=c90-cray
|
|
||||||
os=-unicos
|
os=-unicos
|
||||||
;;
|
;;
|
||||||
crds | unos)
|
crds | unos)
|
||||||
basic_machine=m68k-crds
|
basic_machine=m68k-crds
|
||||||
;;
|
;;
|
||||||
|
cris | cris-* | etrax*)
|
||||||
|
basic_machine=cris-axis
|
||||||
|
;;
|
||||||
da30 | da30-*)
|
da30 | da30-*)
|
||||||
basic_machine=m68k-da30
|
basic_machine=m68k-da30
|
||||||
;;
|
;;
|
||||||
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
|
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
|
||||||
basic_machine=mips-dec
|
basic_machine=mips-dec
|
||||||
;;
|
;;
|
||||||
|
decsystem10* | dec10*)
|
||||||
|
basic_machine=pdp10-dec
|
||||||
|
os=-tops10
|
||||||
|
;;
|
||||||
|
decsystem20* | dec20*)
|
||||||
|
basic_machine=pdp10-dec
|
||||||
|
os=-tops20
|
||||||
|
;;
|
||||||
delta | 3300 | motorola-3300 | motorola-delta \
|
delta | 3300 | motorola-3300 | motorola-delta \
|
||||||
| 3300-motorola | delta-motorola)
|
| 3300-motorola | delta-motorola)
|
||||||
basic_machine=m68k-motorola
|
basic_machine=m68k-motorola
|
||||||
@@ -353,6 +496,10 @@ case $basic_machine in
|
|||||||
basic_machine=tron-gmicro
|
basic_machine=tron-gmicro
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
|
go32)
|
||||||
|
basic_machine=i386-pc
|
||||||
|
os=-go32
|
||||||
|
;;
|
||||||
h3050r* | hiux*)
|
h3050r* | hiux*)
|
||||||
basic_machine=hppa1.1-hitachi
|
basic_machine=hppa1.1-hitachi
|
||||||
os=-hiuxwe2
|
os=-hiuxwe2
|
||||||
@@ -426,22 +573,21 @@ case $basic_machine in
|
|||||||
;;
|
;;
|
||||||
i370-ibm* | ibm*)
|
i370-ibm* | ibm*)
|
||||||
basic_machine=i370-ibm
|
basic_machine=i370-ibm
|
||||||
os=-mvs
|
|
||||||
;;
|
;;
|
||||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||||
i[34567]86v32)
|
i*86v32)
|
||||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||||
os=-sysv32
|
os=-sysv32
|
||||||
;;
|
;;
|
||||||
i[34567]86v4*)
|
i*86v4*)
|
||||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
;;
|
;;
|
||||||
i[34567]86v)
|
i*86v)
|
||||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
i[34567]86sol2)
|
i*86sol2)
|
||||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||||
os=-solaris2
|
os=-solaris2
|
||||||
;;
|
;;
|
||||||
@@ -453,14 +599,6 @@ case $basic_machine in
|
|||||||
basic_machine=i386-unknown
|
basic_machine=i386-unknown
|
||||||
os=-vsta
|
os=-vsta
|
||||||
;;
|
;;
|
||||||
i386-go32 | go32)
|
|
||||||
basic_machine=i386-unknown
|
|
||||||
os=-go32
|
|
||||||
;;
|
|
||||||
i386-mingw32 | mingw32)
|
|
||||||
basic_machine=i386-unknown
|
|
||||||
os=-mingw32
|
|
||||||
;;
|
|
||||||
iris | iris4d)
|
iris | iris4d)
|
||||||
basic_machine=mips-sgi
|
basic_machine=mips-sgi
|
||||||
case $os in
|
case $os in
|
||||||
@@ -486,35 +624,43 @@ case $basic_machine in
|
|||||||
basic_machine=ns32k-utek
|
basic_machine=ns32k-utek
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
|
mingw32)
|
||||||
|
basic_machine=i386-pc
|
||||||
|
os=-mingw32
|
||||||
|
;;
|
||||||
miniframe)
|
miniframe)
|
||||||
basic_machine=m68000-convergent
|
basic_machine=m68000-convergent
|
||||||
;;
|
;;
|
||||||
*mint | *MiNT)
|
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
|
||||||
basic_machine=m68k-atari
|
basic_machine=m68k-atari
|
||||||
os=-mint
|
os=-mint
|
||||||
;;
|
;;
|
||||||
mipsel*-linux*)
|
|
||||||
basic_machine=mipsel-unknown
|
|
||||||
os=-linux-gnu
|
|
||||||
;;
|
|
||||||
mips*-linux*)
|
|
||||||
basic_machine=mips-unknown
|
|
||||||
os=-linux-gnu
|
|
||||||
;;
|
|
||||||
mips3*-*)
|
mips3*-*)
|
||||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
|
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
|
||||||
;;
|
;;
|
||||||
mips3*)
|
mips3*)
|
||||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||||
;;
|
;;
|
||||||
|
mmix*)
|
||||||
|
basic_machine=mmix-knuth
|
||||||
|
os=-mmixware
|
||||||
|
;;
|
||||||
monitor)
|
monitor)
|
||||||
basic_machine=m68k-rom68k
|
basic_machine=m68k-rom68k
|
||||||
os=-coff
|
os=-coff
|
||||||
;;
|
;;
|
||||||
|
morphos)
|
||||||
|
basic_machine=powerpc-unknown
|
||||||
|
os=-morphos
|
||||||
|
;;
|
||||||
msdos)
|
msdos)
|
||||||
basic_machine=i386-unknown
|
basic_machine=i386-pc
|
||||||
os=-msdos
|
os=-msdos
|
||||||
;;
|
;;
|
||||||
|
mvs)
|
||||||
|
basic_machine=i370-ibm
|
||||||
|
os=-mvs
|
||||||
|
;;
|
||||||
ncr3000)
|
ncr3000)
|
||||||
basic_machine=i486-ncr
|
basic_machine=i486-ncr
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
@@ -524,7 +670,7 @@ case $basic_machine in
|
|||||||
os=-netbsd
|
os=-netbsd
|
||||||
;;
|
;;
|
||||||
netwinder)
|
netwinder)
|
||||||
basic_machine=armv4l-corel
|
basic_machine=armv4l-rebel
|
||||||
os=-linux
|
os=-linux
|
||||||
;;
|
;;
|
||||||
news | news700 | news800 | news900)
|
news | news700 | news800 | news900)
|
||||||
@@ -572,13 +718,28 @@ case $basic_machine in
|
|||||||
basic_machine=i960-intel
|
basic_machine=i960-intel
|
||||||
os=-mon960
|
os=-mon960
|
||||||
;;
|
;;
|
||||||
|
nonstopux)
|
||||||
|
basic_machine=mips-compaq
|
||||||
|
os=-nonstopux
|
||||||
|
;;
|
||||||
np1)
|
np1)
|
||||||
basic_machine=np1-gould
|
basic_machine=np1-gould
|
||||||
;;
|
;;
|
||||||
|
nv1)
|
||||||
|
basic_machine=nv1-cray
|
||||||
|
os=-unicosmp
|
||||||
|
;;
|
||||||
|
nsr-tandem)
|
||||||
|
basic_machine=nsr-tandem
|
||||||
|
;;
|
||||||
op50n-* | op60c-*)
|
op50n-* | op60c-*)
|
||||||
basic_machine=hppa1.1-oki
|
basic_machine=hppa1.1-oki
|
||||||
os=-proelf
|
os=-proelf
|
||||||
;;
|
;;
|
||||||
|
or32 | or32-*)
|
||||||
|
basic_machine=or32-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
OSE68000 | ose68000)
|
OSE68000 | ose68000)
|
||||||
basic_machine=m68000-ericsson
|
basic_machine=m68000-ericsson
|
||||||
os=-ose
|
os=-ose
|
||||||
@@ -601,45 +762,65 @@ case $basic_machine in
|
|||||||
pbb)
|
pbb)
|
||||||
basic_machine=m68k-tti
|
basic_machine=m68k-tti
|
||||||
;;
|
;;
|
||||||
pc532 | pc532-*)
|
pc532 | pc532-*)
|
||||||
basic_machine=ns32k-pc532
|
basic_machine=ns32k-pc532
|
||||||
;;
|
;;
|
||||||
pentium | p5 | k5 | k6 | nexen)
|
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||||
basic_machine=i586-pc
|
basic_machine=i586-pc
|
||||||
;;
|
;;
|
||||||
pentiumpro | p6 | 6x86)
|
pentiumpro | p6 | 6x86 | athlon | athlon_*)
|
||||||
basic_machine=i686-pc
|
basic_machine=i686-pc
|
||||||
;;
|
;;
|
||||||
pentiumii | pentium2)
|
pentiumii | pentium2 | pentiumiii | pentium3)
|
||||||
|
basic_machine=i686-pc
|
||||||
|
;;
|
||||||
|
pentium4)
|
||||||
basic_machine=i786-pc
|
basic_machine=i786-pc
|
||||||
;;
|
;;
|
||||||
pentium-* | p5-* | k5-* | k6-* | nexen-*)
|
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
|
||||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
pentiumpro-* | p6-* | 6x86-*)
|
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
||||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
pentiumii-* | pentium2-*)
|
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
|
||||||
|
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
;;
|
||||||
|
pentium4-*)
|
||||||
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
pn)
|
pn)
|
||||||
basic_machine=pn-gould
|
basic_machine=pn-gould
|
||||||
;;
|
;;
|
||||||
power) basic_machine=rs6000-ibm
|
power) basic_machine=power-ibm
|
||||||
;;
|
;;
|
||||||
ppc) basic_machine=powerpc-unknown
|
ppc) basic_machine=powerpc-unknown
|
||||||
;;
|
;;
|
||||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||||
basic_machine=powerpcle-unknown
|
basic_machine=powerpcle-unknown
|
||||||
;;
|
;;
|
||||||
ppcle-* | powerpclittle-*)
|
ppcle-* | powerpclittle-*)
|
||||||
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
|
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
|
ppc64) basic_machine=powerpc64-unknown
|
||||||
|
;;
|
||||||
|
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
;;
|
||||||
|
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
|
||||||
|
basic_machine=powerpc64le-unknown
|
||||||
|
;;
|
||||||
|
ppc64le-* | powerpc64little-*)
|
||||||
|
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
|
;;
|
||||||
ps2)
|
ps2)
|
||||||
basic_machine=i386-ibm
|
basic_machine=i386-ibm
|
||||||
;;
|
;;
|
||||||
|
pw32)
|
||||||
|
basic_machine=i586-unknown
|
||||||
|
os=-pw32
|
||||||
|
;;
|
||||||
rom68k)
|
rom68k)
|
||||||
basic_machine=m68k-rom68k
|
basic_machine=m68k-rom68k
|
||||||
os=-coff
|
os=-coff
|
||||||
@@ -650,10 +831,26 @@ case $basic_machine in
|
|||||||
rtpc | rtpc-*)
|
rtpc | rtpc-*)
|
||||||
basic_machine=romp-ibm
|
basic_machine=romp-ibm
|
||||||
;;
|
;;
|
||||||
|
s390 | s390-*)
|
||||||
|
basic_machine=s390-ibm
|
||||||
|
;;
|
||||||
|
s390x | s390x-*)
|
||||||
|
basic_machine=s390x-ibm
|
||||||
|
;;
|
||||||
sa29200)
|
sa29200)
|
||||||
basic_machine=a29k-amd
|
basic_machine=a29k-amd
|
||||||
os=-udi
|
os=-udi
|
||||||
;;
|
;;
|
||||||
|
sb1)
|
||||||
|
basic_machine=mipsisa64sb1-unknown
|
||||||
|
;;
|
||||||
|
sb1el)
|
||||||
|
basic_machine=mipsisa64sb1el-unknown
|
||||||
|
;;
|
||||||
|
sei)
|
||||||
|
basic_machine=mips-sei
|
||||||
|
os=-seiux
|
||||||
|
;;
|
||||||
sequent)
|
sequent)
|
||||||
basic_machine=i386-sequent
|
basic_machine=i386-sequent
|
||||||
;;
|
;;
|
||||||
@@ -661,7 +858,10 @@ case $basic_machine in
|
|||||||
basic_machine=sh-hitachi
|
basic_machine=sh-hitachi
|
||||||
os=-hms
|
os=-hms
|
||||||
;;
|
;;
|
||||||
sparclite-wrs)
|
sh64)
|
||||||
|
basic_machine=sh64-unknown
|
||||||
|
;;
|
||||||
|
sparclite-wrs | simso-wrs)
|
||||||
basic_machine=sparclite-wrs
|
basic_machine=sparclite-wrs
|
||||||
os=-vxworks
|
os=-vxworks
|
||||||
;;
|
;;
|
||||||
@@ -719,20 +919,44 @@ case $basic_machine in
|
|||||||
sun386 | sun386i | roadrunner)
|
sun386 | sun386i | roadrunner)
|
||||||
basic_machine=i386-sun
|
basic_machine=i386-sun
|
||||||
;;
|
;;
|
||||||
|
sv1)
|
||||||
|
basic_machine=sv1-cray
|
||||||
|
os=-unicos
|
||||||
|
;;
|
||||||
symmetry)
|
symmetry)
|
||||||
basic_machine=i386-sequent
|
basic_machine=i386-sequent
|
||||||
os=-dynix
|
os=-dynix
|
||||||
;;
|
;;
|
||||||
t3e)
|
t3e)
|
||||||
basic_machine=t3e-cray
|
basic_machine=alphaev5-cray
|
||||||
os=-unicos
|
os=-unicos
|
||||||
;;
|
;;
|
||||||
|
t90)
|
||||||
|
basic_machine=t90-cray
|
||||||
|
os=-unicos
|
||||||
|
;;
|
||||||
|
tic54x | c54x*)
|
||||||
|
basic_machine=tic54x-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
|
tic55x | c55x*)
|
||||||
|
basic_machine=tic55x-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
|
tic6x | c6x*)
|
||||||
|
basic_machine=tic6x-unknown
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
tx39)
|
tx39)
|
||||||
basic_machine=mipstx39-unknown
|
basic_machine=mipstx39-unknown
|
||||||
;;
|
;;
|
||||||
tx39el)
|
tx39el)
|
||||||
basic_machine=mipstx39el-unknown
|
basic_machine=mipstx39el-unknown
|
||||||
;;
|
;;
|
||||||
|
toad1)
|
||||||
|
basic_machine=pdp10-xkl
|
||||||
|
os=-tops20
|
||||||
|
;;
|
||||||
tower | tower-32)
|
tower | tower-32)
|
||||||
basic_machine=m68k-ncr
|
basic_machine=m68k-ncr
|
||||||
;;
|
;;
|
||||||
@@ -757,8 +981,8 @@ case $basic_machine in
|
|||||||
os=-vms
|
os=-vms
|
||||||
;;
|
;;
|
||||||
vpp*|vx|vx-*)
|
vpp*|vx|vx-*)
|
||||||
basic_machine=f301-fujitsu
|
basic_machine=f301-fujitsu
|
||||||
;;
|
;;
|
||||||
vxworks960)
|
vxworks960)
|
||||||
basic_machine=i960-wrs
|
basic_machine=i960-wrs
|
||||||
os=-vxworks
|
os=-vxworks
|
||||||
@@ -779,13 +1003,13 @@ case $basic_machine in
|
|||||||
basic_machine=hppa1.1-winbond
|
basic_machine=hppa1.1-winbond
|
||||||
os=-proelf
|
os=-proelf
|
||||||
;;
|
;;
|
||||||
xmp)
|
xps | xps100)
|
||||||
basic_machine=xmp-cray
|
|
||||||
os=-unicos
|
|
||||||
;;
|
|
||||||
xps | xps100)
|
|
||||||
basic_machine=xps100-honeywell
|
basic_machine=xps100-honeywell
|
||||||
;;
|
;;
|
||||||
|
ymp)
|
||||||
|
basic_machine=ymp-cray
|
||||||
|
os=-unicos
|
||||||
|
;;
|
||||||
z8k-*-coff)
|
z8k-*-coff)
|
||||||
basic_machine=z8k-unknown
|
basic_machine=z8k-unknown
|
||||||
os=-sim
|
os=-sim
|
||||||
@@ -806,13 +1030,6 @@ case $basic_machine in
|
|||||||
op60c)
|
op60c)
|
||||||
basic_machine=hppa1.1-oki
|
basic_machine=hppa1.1-oki
|
||||||
;;
|
;;
|
||||||
mips)
|
|
||||||
if [ x$os = x-linux-gnu ]; then
|
|
||||||
basic_machine=mips-unknown
|
|
||||||
else
|
|
||||||
basic_machine=mips-mips
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
romp)
|
romp)
|
||||||
basic_machine=romp-ibm
|
basic_machine=romp-ibm
|
||||||
;;
|
;;
|
||||||
@@ -822,16 +1039,26 @@ case $basic_machine in
|
|||||||
vax)
|
vax)
|
||||||
basic_machine=vax-dec
|
basic_machine=vax-dec
|
||||||
;;
|
;;
|
||||||
|
pdp10)
|
||||||
|
# there are many clones, so DEC is not a safe bet
|
||||||
|
basic_machine=pdp10-unknown
|
||||||
|
;;
|
||||||
pdp11)
|
pdp11)
|
||||||
basic_machine=pdp11-dec
|
basic_machine=pdp11-dec
|
||||||
;;
|
;;
|
||||||
we32k)
|
we32k)
|
||||||
basic_machine=we32k-att
|
basic_machine=we32k-att
|
||||||
;;
|
;;
|
||||||
sparc | sparcv9)
|
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||||
|
basic_machine=sh-unknown
|
||||||
|
;;
|
||||||
|
sh64)
|
||||||
|
basic_machine=sh64-unknown
|
||||||
|
;;
|
||||||
|
sparc | sparcv9 | sparcv9b)
|
||||||
basic_machine=sparc-sun
|
basic_machine=sparc-sun
|
||||||
;;
|
;;
|
||||||
cydra)
|
cydra)
|
||||||
basic_machine=cydra-cydrome
|
basic_machine=cydra-cydrome
|
||||||
;;
|
;;
|
||||||
orion)
|
orion)
|
||||||
@@ -846,9 +1073,8 @@ case $basic_machine in
|
|||||||
pmac | pmac-mpw)
|
pmac | pmac-mpw)
|
||||||
basic_machine=powerpc-apple
|
basic_machine=powerpc-apple
|
||||||
;;
|
;;
|
||||||
c4x*)
|
*-unknown)
|
||||||
basic_machine=c4x-none
|
# Make sure to match an already-canonicalized machine name.
|
||||||
os=-coff
|
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||||
@@ -906,14 +1132,34 @@ case $os in
|
|||||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||||
|
| -chorusos* | -chorusrdb* \
|
||||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||||
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
|
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||||
| -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*)
|
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||||
|
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||||
|
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||||
|
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||||
|
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||||
|
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
|
||||||
# Remember, each alternative MUST END IN *, to match a version number.
|
# Remember, each alternative MUST END IN *, to match a version number.
|
||||||
;;
|
;;
|
||||||
|
-qnx*)
|
||||||
|
case $basic_machine in
|
||||||
|
x86-* | i*86-*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
os=-nto$os
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
-nto-qnx*)
|
||||||
|
;;
|
||||||
|
-nto*)
|
||||||
|
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||||
|
;;
|
||||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||||
| -macos* | -mpw* | -magic* | -mon960* | -lnews*)
|
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||||
;;
|
;;
|
||||||
-mac*)
|
-mac*)
|
||||||
os=`echo $os | sed -e 's|mac|macos|'`
|
os=`echo $os | sed -e 's|mac|macos|'`
|
||||||
@@ -927,6 +1173,12 @@ case $os in
|
|||||||
-sunos6*)
|
-sunos6*)
|
||||||
os=`echo $os | sed -e 's|sunos6|solaris3|'`
|
os=`echo $os | sed -e 's|sunos6|solaris3|'`
|
||||||
;;
|
;;
|
||||||
|
-opened*)
|
||||||
|
os=-openedition
|
||||||
|
;;
|
||||||
|
-wince*)
|
||||||
|
os=-wince
|
||||||
|
;;
|
||||||
-osfrose*)
|
-osfrose*)
|
||||||
os=-osfrose
|
os=-osfrose
|
||||||
;;
|
;;
|
||||||
@@ -942,14 +1194,23 @@ case $os in
|
|||||||
-acis*)
|
-acis*)
|
||||||
os=-aos
|
os=-aos
|
||||||
;;
|
;;
|
||||||
|
-atheos*)
|
||||||
|
os=-atheos
|
||||||
|
;;
|
||||||
-386bsd)
|
-386bsd)
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
-ctix* | -uts*)
|
-ctix* | -uts*)
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
|
-nova*)
|
||||||
|
os=-rtmk-nova
|
||||||
|
;;
|
||||||
-ns2 )
|
-ns2 )
|
||||||
os=-nextstep2
|
os=-nextstep2
|
||||||
|
;;
|
||||||
|
-nsk*)
|
||||||
|
os=-nsk
|
||||||
;;
|
;;
|
||||||
# Preserve the version number of sinix5.
|
# Preserve the version number of sinix5.
|
||||||
-sinix5.*)
|
-sinix5.*)
|
||||||
@@ -985,8 +1246,14 @@ case $os in
|
|||||||
-xenix)
|
-xenix)
|
||||||
os=-xenix
|
os=-xenix
|
||||||
;;
|
;;
|
||||||
-*mint | -*MiNT)
|
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||||
os=-mint
|
os=-mint
|
||||||
|
;;
|
||||||
|
-aros*)
|
||||||
|
os=-aros
|
||||||
|
;;
|
||||||
|
-kaos*)
|
||||||
|
os=-kaos
|
||||||
;;
|
;;
|
||||||
-none)
|
-none)
|
||||||
;;
|
;;
|
||||||
@@ -1013,13 +1280,20 @@ case $basic_machine in
|
|||||||
*-acorn)
|
*-acorn)
|
||||||
os=-riscix1.2
|
os=-riscix1.2
|
||||||
;;
|
;;
|
||||||
arm*-corel)
|
arm*-rebel)
|
||||||
os=-linux
|
os=-linux
|
||||||
;;
|
;;
|
||||||
arm*-semi)
|
arm*-semi)
|
||||||
os=-aout
|
os=-aout
|
||||||
;;
|
;;
|
||||||
pdp11-*)
|
c4x-* | tic4x-*)
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
|
# This must come before the *-dec entry.
|
||||||
|
pdp10-*)
|
||||||
|
os=-tops20
|
||||||
|
;;
|
||||||
|
pdp11-*)
|
||||||
os=-none
|
os=-none
|
||||||
;;
|
;;
|
||||||
*-dec | vax-*)
|
*-dec | vax-*)
|
||||||
@@ -1046,6 +1320,9 @@ case $basic_machine in
|
|||||||
mips*-*)
|
mips*-*)
|
||||||
os=-elf
|
os=-elf
|
||||||
;;
|
;;
|
||||||
|
or32-*)
|
||||||
|
os=-coff
|
||||||
|
;;
|
||||||
*-tti) # must be before sparc entry or we get the wrong os.
|
*-tti) # must be before sparc entry or we get the wrong os.
|
||||||
os=-sysv3
|
os=-sysv3
|
||||||
;;
|
;;
|
||||||
@@ -1109,25 +1386,25 @@ case $basic_machine in
|
|||||||
*-next)
|
*-next)
|
||||||
os=-nextstep3
|
os=-nextstep3
|
||||||
;;
|
;;
|
||||||
*-gould)
|
*-gould)
|
||||||
os=-sysv
|
os=-sysv
|
||||||
;;
|
;;
|
||||||
*-highlevel)
|
*-highlevel)
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
*-encore)
|
*-encore)
|
||||||
os=-bsd
|
os=-bsd
|
||||||
;;
|
;;
|
||||||
*-sgi)
|
*-sgi)
|
||||||
os=-irix
|
os=-irix
|
||||||
;;
|
;;
|
||||||
*-siemens)
|
*-siemens)
|
||||||
os=-sysv4
|
os=-sysv4
|
||||||
;;
|
;;
|
||||||
*-masscomp)
|
*-masscomp)
|
||||||
os=-rtu
|
os=-rtu
|
||||||
;;
|
;;
|
||||||
f301-fujitsu)
|
f30[01]-fujitsu | f700-fujitsu)
|
||||||
os=-uxpv
|
os=-uxpv
|
||||||
;;
|
;;
|
||||||
*-rom68k)
|
*-rom68k)
|
||||||
@@ -1187,13 +1464,13 @@ case $basic_machine in
|
|||||||
-genix*)
|
-genix*)
|
||||||
vendor=ns
|
vendor=ns
|
||||||
;;
|
;;
|
||||||
-mvs*)
|
-mvs* | -opened*)
|
||||||
vendor=ibm
|
vendor=ibm
|
||||||
;;
|
;;
|
||||||
-ptx*)
|
-ptx*)
|
||||||
vendor=sequent
|
vendor=sequent
|
||||||
;;
|
;;
|
||||||
-vxsim* | -vxworks*)
|
-vxsim* | -vxworks* | -windiss*)
|
||||||
vendor=wrs
|
vendor=wrs
|
||||||
;;
|
;;
|
||||||
-aux*)
|
-aux*)
|
||||||
@@ -1205,12 +1482,23 @@ case $basic_machine in
|
|||||||
-mpw* | -macos*)
|
-mpw* | -macos*)
|
||||||
vendor=apple
|
vendor=apple
|
||||||
;;
|
;;
|
||||||
-*mint | -*MiNT)
|
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||||
vendor=atari
|
vendor=atari
|
||||||
;;
|
;;
|
||||||
|
-vos*)
|
||||||
|
vendor=stratus
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
|
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo $basic_machine$os
|
echo $basic_machine$os
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "timestamp='"
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d"
|
||||||
|
# time-stamp-end: "'"
|
||||||
|
# End:
|
||||||
|
|||||||
@@ -1,19 +1,38 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
|
||||||
# install - install a program, script, or datafile
|
# install - install a program, script, or datafile
|
||||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
|
||||||
|
scriptversion=2003-06-13.21
|
||||||
|
|
||||||
|
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||||
|
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||||
|
# following copyright and license.
|
||||||
#
|
#
|
||||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
# Copyright (C) 1994 X Consortium
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# documentation for any purpose is hereby granted without fee, provided that
|
# of this software and associated documentation files (the "Software"), to
|
||||||
# the above copyright notice appear in all copies and that both that
|
# deal in the Software without restriction, including without limitation the
|
||||||
# copyright notice and this permission notice appear in supporting
|
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
# sell copies of the Software, and to permit persons to whom the Software is
|
||||||
# publicity pertaining to distribution of the software without specific,
|
# furnished to do so, subject to the following conditions:
|
||||||
# written prior permission. M.I.T. makes no representations about the
|
#
|
||||||
# suitability of this software for any purpose. It is provided "as is"
|
# The above copyright notice and this permission notice shall be included in
|
||||||
# without express or implied warranty.
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||||
|
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
# Except as contained in this notice, the name of the X Consortium shall not
|
||||||
|
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||||
|
# ings in this Software without prior written authorization from the X Consor-
|
||||||
|
# tium.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# FSF changes to this file are in the public domain.
|
||||||
#
|
#
|
||||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||||
# `make' implicit rules from creating a file called install from it
|
# `make' implicit rules from creating a file called install from it
|
||||||
@@ -23,13 +42,11 @@
|
|||||||
# from scratch. It can only install one file at a time, a restriction
|
# from scratch. It can only install one file at a time, a restriction
|
||||||
# shared with many OS's install programs.
|
# shared with many OS's install programs.
|
||||||
|
|
||||||
|
|
||||||
# set DOITPROG to echo to test this script
|
# set DOITPROG to echo to test this script
|
||||||
|
|
||||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||||
doit="${DOITPROG-}"
|
doit="${DOITPROG-}"
|
||||||
|
|
||||||
|
|
||||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||||
|
|
||||||
mvprog="${MVPROG-mv}"
|
mvprog="${MVPROG-mv}"
|
||||||
@@ -41,211 +58,229 @@ stripprog="${STRIPPROG-strip}"
|
|||||||
rmprog="${RMPROG-rm}"
|
rmprog="${RMPROG-rm}"
|
||||||
mkdirprog="${MKDIRPROG-mkdir}"
|
mkdirprog="${MKDIRPROG-mkdir}"
|
||||||
|
|
||||||
transformbasename=""
|
transformbasename=
|
||||||
transform_arg=""
|
transform_arg=
|
||||||
instcmd="$mvprog"
|
instcmd="$mvprog"
|
||||||
chmodcmd="$chmodprog 0755"
|
chmodcmd="$chmodprog 0755"
|
||||||
chowncmd=""
|
chowncmd=
|
||||||
chgrpcmd=""
|
chgrpcmd=
|
||||||
stripcmd=""
|
stripcmd=
|
||||||
rmcmd="$rmprog -f"
|
rmcmd="$rmprog -f"
|
||||||
mvcmd="$mvprog"
|
mvcmd="$mvprog"
|
||||||
src=""
|
src=
|
||||||
dst=""
|
dst=
|
||||||
dir_arg=""
|
dir_arg=
|
||||||
|
|
||||||
while [ x"$1" != x ]; do
|
usage="Usage: $0 [OPTION]... SRCFILE DSTFILE
|
||||||
case $1 in
|
or: $0 -d DIR1 DIR2...
|
||||||
-c) instcmd="$cpprog"
|
|
||||||
shift
|
|
||||||
continue;;
|
|
||||||
|
|
||||||
-d) dir_arg=true
|
In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default.
|
||||||
shift
|
In the second, create the directory path DIR.
|
||||||
continue;;
|
|
||||||
|
|
||||||
-m) chmodcmd="$chmodprog $2"
|
Options:
|
||||||
shift
|
-b=TRANSFORMBASENAME
|
||||||
shift
|
-c copy source (using $cpprog) instead of moving (using $mvprog).
|
||||||
continue;;
|
-d create directories instead of installing files.
|
||||||
|
-g GROUP $chgrp installed files to GROUP.
|
||||||
|
-m MODE $chmod installed files to MODE.
|
||||||
|
-o USER $chown installed files to USER.
|
||||||
|
-s strip installed files (using $stripprog).
|
||||||
|
-t=TRANSFORM
|
||||||
|
--help display this help and exit.
|
||||||
|
--version display version info and exit.
|
||||||
|
|
||||||
-o) chowncmd="$chownprog $2"
|
Environment variables override the default commands:
|
||||||
shift
|
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||||
shift
|
"
|
||||||
continue;;
|
|
||||||
|
|
||||||
-g) chgrpcmd="$chgrpprog $2"
|
while test -n "$1"; do
|
||||||
shift
|
case $1 in
|
||||||
shift
|
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||||
continue;;
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
-s) stripcmd="$stripprog"
|
-c) instcmd=$cpprog
|
||||||
shift
|
shift
|
||||||
continue;;
|
continue;;
|
||||||
|
|
||||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
-d) dir_arg=true
|
||||||
shift
|
shift
|
||||||
continue;;
|
continue;;
|
||||||
|
|
||||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
-g) chgrpcmd="$chgrpprog $2"
|
||||||
shift
|
shift
|
||||||
continue;;
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
*) if [ x"$src" = x ]
|
--help) echo "$usage"; exit 0;;
|
||||||
then
|
|
||||||
src=$1
|
-m) chmodcmd="$chmodprog $2"
|
||||||
else
|
shift
|
||||||
# this colon is to work around a 386BSD /bin/sh bug
|
shift
|
||||||
:
|
continue;;
|
||||||
dst=$1
|
|
||||||
fi
|
-o) chowncmd="$chownprog $2"
|
||||||
shift
|
shift
|
||||||
continue;;
|
shift
|
||||||
esac
|
continue;;
|
||||||
|
|
||||||
|
-s) stripcmd=$stripprog
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
|
||||||
|
--version) echo "$0 $scriptversion"; exit 0;;
|
||||||
|
|
||||||
|
*) if test -z "$src"; then
|
||||||
|
src=$1
|
||||||
|
else
|
||||||
|
# this colon is to work around a 386BSD /bin/sh bug
|
||||||
|
:
|
||||||
|
dst=$1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
continue;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ x"$src" = x ]
|
if test -z "$src"; then
|
||||||
then
|
echo "$0: no input file specified." >&2
|
||||||
echo "install: no input file specified"
|
exit 1
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
true
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ x"$dir_arg" != x ]; then
|
if test -n "$dir_arg"; then
|
||||||
dst=$src
|
dst=$src
|
||||||
src=""
|
src=
|
||||||
|
|
||||||
if [ -d $dst ]; then
|
if test -d "$dst"; then
|
||||||
instcmd=:
|
instcmd=:
|
||||||
chmodcmd=""
|
chmodcmd=
|
||||||
else
|
else
|
||||||
instcmd=mkdir
|
instcmd=$mkdirprog
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||||
|
# might cause directories to be created, which would be especially bad
|
||||||
|
# if $src (and thus $dsttmp) contains '*'.
|
||||||
|
if test ! -f "$src" && test ! -d "$src"; then
|
||||||
|
echo "$0: $src does not exist." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
if test -z "$dst"; then
|
||||||
# might cause directories to be created, which would be especially bad
|
echo "$0: no destination specified." >&2
|
||||||
# if $src (and thus $dsttmp) contains '*'.
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -f $src -o -d $src ]
|
# If destination is a directory, append the input filename; won't work
|
||||||
then
|
# if double slashes aren't ignored.
|
||||||
true
|
if test -d "$dst"; then
|
||||||
else
|
dst=$dst/`basename "$src"`
|
||||||
echo "install: $src does not exist"
|
fi
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ x"$dst" = x ]
|
|
||||||
then
|
|
||||||
echo "install: no destination specified"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If destination is a directory, append the input filename; if your system
|
|
||||||
# does not like double slashes in filenames, you may need to add some logic
|
|
||||||
|
|
||||||
if [ -d $dst ]
|
|
||||||
then
|
|
||||||
dst="$dst"/`basename $src`
|
|
||||||
else
|
|
||||||
true
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
## this sed command emulates the dirname command
|
## this sed command emulates the dirname command
|
||||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||||
|
|
||||||
# Make sure that the destination directory exists.
|
# Make sure that the destination directory exists.
|
||||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
# (this part is taken from Noah Friedman's mkinstalldirs script.)
|
||||||
|
|
||||||
# Skip lots of stat calls in the usual case.
|
# Skip lots of stat calls in the usual case.
|
||||||
if [ ! -d "$dstdir" ]; then
|
if test ! -d "$dstdir"; then
|
||||||
defaultIFS='
|
defaultIFS='
|
||||||
'
|
'
|
||||||
IFS="${IFS-${defaultIFS}}"
|
IFS="${IFS-$defaultIFS}"
|
||||||
|
|
||||||
oIFS="${IFS}"
|
oIFS=$IFS
|
||||||
# Some sh's can't handle IFS=/ for some reason.
|
# Some sh's can't handle IFS=/ for some reason.
|
||||||
IFS='%'
|
IFS='%'
|
||||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||||
IFS="${oIFS}"
|
IFS=$oIFS
|
||||||
|
|
||||||
pathcomp=''
|
pathcomp=
|
||||||
|
|
||||||
while [ $# -ne 0 ] ; do
|
while test $# -ne 0 ; do
|
||||||
pathcomp="${pathcomp}${1}"
|
pathcomp=$pathcomp$1
|
||||||
shift
|
shift
|
||||||
|
test -d "$pathcomp" || $mkdirprog "$pathcomp"
|
||||||
if [ ! -d "${pathcomp}" ] ;
|
pathcomp=$pathcomp/
|
||||||
then
|
done
|
||||||
$mkdirprog "${pathcomp}"
|
|
||||||
else
|
|
||||||
true
|
|
||||||
fi
|
|
||||||
|
|
||||||
pathcomp="${pathcomp}/"
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ x"$dir_arg" != x ]
|
if test -n "$dir_arg"; then
|
||||||
then
|
$doit $instcmd "$dst" \
|
||||||
$doit $instcmd $dst &&
|
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
|
||||||
|
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
|
||||||
|
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
|
||||||
|
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
|
||||||
|
|
||||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
|
||||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
|
||||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
|
||||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
|
||||||
else
|
else
|
||||||
|
# If we're going to rename the final executable, determine the name now.
|
||||||
|
if test -z "$transformarg"; then
|
||||||
|
dstfile=`basename "$dst"`
|
||||||
|
else
|
||||||
|
dstfile=`basename "$dst" $transformbasename \
|
||||||
|
| sed $transformarg`$transformbasename
|
||||||
|
fi
|
||||||
|
|
||||||
# If we're going to rename the final executable, determine the name now.
|
# don't allow the sed command to completely eliminate the filename.
|
||||||
|
test -z "$dstfile" && dstfile=`basename "$dst"`
|
||||||
|
|
||||||
if [ x"$transformarg" = x ]
|
# Make a couple of temp file names in the proper directory.
|
||||||
then
|
dsttmp=$dstdir/_inst.$$_
|
||||||
dstfile=`basename $dst`
|
rmtmp=$dstdir/_rm.$$_
|
||||||
else
|
|
||||||
dstfile=`basename $dst $transformbasename |
|
|
||||||
sed $transformarg`$transformbasename
|
|
||||||
fi
|
|
||||||
|
|
||||||
# don't allow the sed command to completely eliminate the filename
|
# Trap to clean up those temp files at exit.
|
||||||
|
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
|
||||||
|
trap '(exit $?); exit' 1 2 13 15
|
||||||
|
|
||||||
if [ x"$dstfile" = x ]
|
# Move or copy the file name to the temp name
|
||||||
then
|
$doit $instcmd "$src" "$dsttmp" &&
|
||||||
dstfile=`basename $dst`
|
|
||||||
else
|
|
||||||
true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make a temp file name in the proper directory.
|
# and set any options; do chmod last to preserve setuid bits.
|
||||||
|
#
|
||||||
|
# If any of these fail, we abort the whole thing. If we want to
|
||||||
|
# ignore errors from any of these, just make sure not to ignore
|
||||||
|
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||||
|
#
|
||||||
|
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||||
|
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||||
|
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||||
|
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
|
||||||
|
|
||||||
dsttmp=$dstdir/#inst.$$#
|
# Now remove or move aside any old file at destination location. We
|
||||||
|
# try this two ways since rm can't unlink itself on some systems and
|
||||||
# Move or copy the file name to the temp name
|
# the destination file might be busy for other reasons. In this case,
|
||||||
|
# the final cleanup might fail but the new file should still install
|
||||||
$doit $instcmd $src $dsttmp &&
|
# successfully.
|
||||||
|
{
|
||||||
trap "rm -f ${dsttmp}" 0 &&
|
if test -f "$dstdir/$dstfile"; then
|
||||||
|
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|
||||||
# and set any options; do chmod last to preserve setuid bits
|
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|
||||||
|
|| {
|
||||||
# If any of these fail, we abort the whole thing. If we want to
|
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||||
# ignore errors from any of these, just make sure not to ignore
|
(exit 1); exit
|
||||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
}
|
||||||
|
else
|
||||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
:
|
||||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
fi
|
||||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
} &&
|
||||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
|
||||||
|
|
||||||
# Now rename the file to the real destination.
|
|
||||||
|
|
||||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
|
||||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
|
||||||
|
|
||||||
|
# Now rename the file to the real destination.
|
||||||
|
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||||
fi &&
|
fi &&
|
||||||
|
|
||||||
|
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||||
|
{
|
||||||
|
(exit 0); exit
|
||||||
|
}
|
||||||
|
|
||||||
exit 0
|
# Local variables:
|
||||||
|
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||||
|
# time-stamp-start: "scriptversion="
|
||||||
|
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||||
|
# time-stamp-end: "$"
|
||||||
|
# End:
|
||||||
|
|||||||
661
configure.in
Normal file
661
configure.in
Normal file
@@ -0,0 +1,661 @@
|
|||||||
|
##
|
||||||
|
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
## Copyright (C) 2004 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
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
AC_PREREQ(2.53)
|
||||||
|
################################################################################
|
||||||
|
dnl -- Process this file with autoconf to produce a configure script.
|
||||||
|
AC_INIT(lib/device/dev-cache.h)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
AC_CONFIG_HEADERS(lib/misc/configure.h)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Setup the directory where autoconf has auxilary files
|
||||||
|
AC_CONFIG_AUX_DIR(autoconf)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Get system type
|
||||||
|
AC_CANONICAL_SYSTEM
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
linux*)
|
||||||
|
CFLAGS="$CFLAGS"
|
||||||
|
COPTIMISE_FLAG="-O2"
|
||||||
|
CLDFLAGS="$CLDFLAGS -Wl,--version-script,.export.sym"
|
||||||
|
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
||||||
|
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
||||||
|
LDDEPS="$LDDEPS .export.sym"
|
||||||
|
LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
|
||||||
|
LIB_SUFFIX="so"
|
||||||
|
DEVMAPPER=yes
|
||||||
|
ODIRECT=yes
|
||||||
|
SELINUX=yes
|
||||||
|
REALTIME=yes
|
||||||
|
CLUSTER=internal
|
||||||
|
FSADM=no ;;
|
||||||
|
darwin*)
|
||||||
|
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
||||||
|
COPTIMISE_FLAG="-O2"
|
||||||
|
CLDFLAGS="$CLDFLAGS"
|
||||||
|
CLDWHOLEARCHIVE="-all_load"
|
||||||
|
CLDNOWHOLEARCHIVE=
|
||||||
|
LDDEPS="$LDDEPS"
|
||||||
|
LDFLAGS="$LDFLAGS"
|
||||||
|
LIB_SUFFIX="dylib"
|
||||||
|
DEVMAPPER=yes
|
||||||
|
ODIRECT=no
|
||||||
|
SELINUX=no
|
||||||
|
REALTIME=no
|
||||||
|
CLUSTER=none
|
||||||
|
FSADM=no ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Checks for programs.
|
||||||
|
AC_PROG_AWK
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_LN_S
|
||||||
|
AC_PROG_MAKE_SET
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
AC_PATH_PROG(CFLOW_CMD, cflow)
|
||||||
|
AC_PATH_PROG(CSCOPE_CMD, cscope)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Checks for header files.
|
||||||
|
AC_HEADER_DIRENT
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_HEADER_SYS_WAIT
|
||||||
|
AC_HEADER_TIME
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS(fcntl.h limits.h locale.h stddef.h syslog.h sys/file.h sys/ioctl.h sys/param.h sys/time.h,,AC_MSG_ERROR(bailing out))
|
||||||
|
AC_CHECK_HEADERS(assert.h ctype.h libgen.h signal.h stdio.h sys/mman.h sys/resource.h sys/stat.h sys/types.h sys/utsname.h sys/wait.h time.h,,AC_MSG_ERROR(bailing out))
|
||||||
|
|
||||||
|
case "$host_os" in
|
||||||
|
linux*)
|
||||||
|
AC_CHECK_HEADERS(asm/byteorder.h linux/fs.h malloc.h,,AC_MSG_ERROR(bailing out)) ;;
|
||||||
|
darwin*)
|
||||||
|
AC_CHECK_HEADERS(machine/endian.h sys/disk.h,,AC_MSG_ERROR(bailing out)) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_C_CONST
|
||||||
|
AC_C_INLINE
|
||||||
|
AC_TYPE_OFF_T
|
||||||
|
AC_TYPE_PID_T
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_TYPE_MODE_T
|
||||||
|
AC_STRUCT_ST_RDEV
|
||||||
|
AC_STRUCT_TM
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for functions
|
||||||
|
AC_CHECK_FUNCS(gethostname getpagesize memset munmap setlocale strcasecmp strchr strdup strncasecmp strerror strrchr strstr strtol strtoul,,AC_MSG_ERROR(bailing out))
|
||||||
|
AC_FUNC_ALLOCA
|
||||||
|
AC_FUNC_CLOSEDIR_VOID
|
||||||
|
AC_FUNC_FORK
|
||||||
|
AC_FUNC_LSTAT
|
||||||
|
AC_FUNC_MALLOC
|
||||||
|
AC_FUNC_MEMCMP
|
||||||
|
AC_FUNC_MMAP
|
||||||
|
AC_FUNC_STAT
|
||||||
|
AC_FUNC_STRTOD
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Prefix is /usr by default, the exec_prefix default is setup later
|
||||||
|
AC_PREFIX_DEFAULT(/usr)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Parallel make jobs?
|
||||||
|
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Setup the ownership of the files
|
||||||
|
AC_MSG_CHECKING(file owner)
|
||||||
|
OWNER="root"
|
||||||
|
|
||||||
|
AC_ARG_WITH(user,
|
||||||
|
[ --with-user=USER Set the owner of installed files ],
|
||||||
|
[ OWNER="$withval" ])
|
||||||
|
AC_MSG_RESULT($OWNER)
|
||||||
|
|
||||||
|
if test x$OWNER != x; then
|
||||||
|
OWNER="-o $OWNER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Setup the group ownership of the files
|
||||||
|
AC_MSG_CHECKING(group owner)
|
||||||
|
GROUP="root"
|
||||||
|
AC_ARG_WITH(group,
|
||||||
|
[ --with-group=GROUP Set the group owner of installed files ],
|
||||||
|
[ GROUP="$withval" ])
|
||||||
|
AC_MSG_RESULT($GROUP)
|
||||||
|
|
||||||
|
if test x$GROUP != x; then
|
||||||
|
GROUP="-g $GROUP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- LVM1 tool fallback option
|
||||||
|
AC_MSG_CHECKING(whether to enable lvm1 fallback)
|
||||||
|
AC_ARG_ENABLE(lvm1_fallback, [ --enable-lvm1_fallback Use this to fall back and use LVM1 binaries if
|
||||||
|
device-mapper is missing from the kernel], LVM1_FALLBACK=$enableval, LVM1_FALLBACK=no)
|
||||||
|
AC_MSG_RESULT($LVM1_FALLBACK)
|
||||||
|
|
||||||
|
if test x$LVM1_FALLBACK = xyes; then
|
||||||
|
AC_DEFINE([LVM1_FALLBACK], 1, [Define to 1 if 'lvm' should fall back to using LVM1 binaries if device-mapper is missing from the kernel])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- format1 inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include support for lvm1 metadata)
|
||||||
|
AC_ARG_WITH(lvm1,
|
||||||
|
[ --with-lvm1=TYPE LVM1 metadata support: internal/shared/none
|
||||||
|
[TYPE=internal] ],
|
||||||
|
[ LVM1="$withval" ],
|
||||||
|
[ LVM1="internal" ])
|
||||||
|
AC_MSG_RESULT($LVM1)
|
||||||
|
|
||||||
|
if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
|
||||||
|
then AC_MSG_ERROR(
|
||||||
|
--with-lvm1 parameter invalid
|
||||||
|
)
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if test x$LVM1 = xinternal; then
|
||||||
|
AC_DEFINE([LVM1_INTERNAL], 1, [Define to 1 to include built-in support for LVM1 metadata.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- format_pool inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include support for GFS pool metadata)
|
||||||
|
AC_ARG_WITH(pool,
|
||||||
|
[ --with-pool=TYPE GFS pool read-only support: internal/shared/none
|
||||||
|
[TYPE=internal] ],
|
||||||
|
[ POOL="$withval" ],
|
||||||
|
[ POOL="internal" ])
|
||||||
|
AC_MSG_RESULT($POOL)
|
||||||
|
|
||||||
|
if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
|
||||||
|
then AC_MSG_ERROR(
|
||||||
|
--with-pool parameter invalid
|
||||||
|
)
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if test x$POOL = xinternal; then
|
||||||
|
AC_DEFINE([POOL_INTERNAL], 1, [Define to 1 to include built-in support for GFS pool metadata.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- cluster_locking inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include support for cluster locking)
|
||||||
|
AC_ARG_WITH(cluster,
|
||||||
|
[ --with-cluster=TYPE Cluster LVM locking support: internal/shared/none
|
||||||
|
[TYPE=internal] ],
|
||||||
|
[ CLUSTER="$withval" ])
|
||||||
|
AC_MSG_RESULT($CLUSTER)
|
||||||
|
|
||||||
|
if [[ "x$CLUSTER" != xnone -a "x$CLUSTER" != xinternal -a "x$CLUSTER" != xshared ]];
|
||||||
|
then AC_MSG_ERROR(
|
||||||
|
--with-cluster parameter invalid
|
||||||
|
)
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if test x$CLUSTER = xinternal; then
|
||||||
|
AC_DEFINE([CLUSTER_LOCKING_INTERNAL], 1, [Define to 1 to include built-in support for clustered LVM locking.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- snapshots inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include snapshots)
|
||||||
|
AC_ARG_WITH(snapshots,
|
||||||
|
[ --with-snapshots=TYPE Snapshot support: internal/shared/none
|
||||||
|
[TYPE=internal] ],
|
||||||
|
[ SNAPSHOTS="$withval" ],
|
||||||
|
[ SNAPSHOTS="internal" ])
|
||||||
|
AC_MSG_RESULT($SNAPSHOTS)
|
||||||
|
|
||||||
|
if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
|
||||||
|
then AC_MSG_ERROR(
|
||||||
|
--with-snapshots parameter invalid
|
||||||
|
)
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if test x$SNAPSHOTS = xinternal; then
|
||||||
|
AC_DEFINE([SNAPSHOT_INTERNAL], 1, [Define to 1 to include built-in support for snapshots.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- mirrors inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include mirrors)
|
||||||
|
AC_ARG_WITH(mirrors,
|
||||||
|
[ --with-mirrors=TYPE Mirror support: internal/shared/none
|
||||||
|
[TYPE=internal] ],
|
||||||
|
[ MIRRORS="$withval" ],
|
||||||
|
[ MIRRORS="internal" ])
|
||||||
|
AC_MSG_RESULT($MIRRORS)
|
||||||
|
|
||||||
|
if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
|
||||||
|
then AC_MSG_ERROR(
|
||||||
|
--with-mirrors parameter invalid
|
||||||
|
)
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if test x$MIRRORS = xinternal; then
|
||||||
|
AC_DEFINE([MIRRORED_INTERNAL], 1, [Define to 1 to include built-in support for mirrors.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Enables staticly-linked tools
|
||||||
|
AC_MSG_CHECKING(whether to use static linking)
|
||||||
|
AC_ARG_ENABLE(static_link, [ --enable-static_link Use this to link the tools to their libraries
|
||||||
|
statically. Default is dynamic linking], STATIC_LINK=$enableval, STATIC_LINK=no)
|
||||||
|
AC_MSG_RESULT($STATIC_LINK)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Enable readline
|
||||||
|
AC_MSG_CHECKING(whether to enable readline)
|
||||||
|
AC_ARG_ENABLE(readline, [ --enable-readline Enable readline support],
|
||||||
|
READLINE=$enableval, READLINE=no)
|
||||||
|
AC_MSG_RESULT($READLINE)
|
||||||
|
|
||||||
|
if test x$READLINE = xyes; then
|
||||||
|
AC_DEFINE([READLINE_SUPPORT], 1, [Define to 1 to include the LVM readline shell.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Disable selinux
|
||||||
|
AC_MSG_CHECKING(whether to enable selinux support)
|
||||||
|
AC_ARG_ENABLE(selinux, [ --disable-selinux Disable selinux support],
|
||||||
|
SELINUX=$enableval)
|
||||||
|
AC_MSG_RESULT($SELINUX)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Disable realtime clock support
|
||||||
|
AC_MSG_CHECKING(whether to enable realtime support)
|
||||||
|
AC_ARG_ENABLE(realtime, [ --disable-realtime Disable realtime clock support],
|
||||||
|
REALTIME=$enableval)
|
||||||
|
AC_MSG_RESULT($REALTIME)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Build cluster LVM daemon
|
||||||
|
AC_MSG_CHECKING(whether to build cluster LVM daemon)
|
||||||
|
AC_ARG_WITH(clvmd,
|
||||||
|
[ --with-clvmd=TYPE Build cluster LVM Daemon: cman/gulm/none/all
|
||||||
|
[TYPE=none] ],
|
||||||
|
[ CLVMD="$withval" ],
|
||||||
|
[ CLVMD="none" ])
|
||||||
|
if test x$CLVMD = xyes; then
|
||||||
|
CLVMD=all
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT($CLVMD)
|
||||||
|
|
||||||
|
dnl -- If clvmd enabled without cluster locking, automagically include it
|
||||||
|
if test x$CLVMD != xnone && test x$CLUSTER = xnone; then
|
||||||
|
CLUSTER=internal
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Enable debugging
|
||||||
|
AC_MSG_CHECKING(whether to enable debugging)
|
||||||
|
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging],
|
||||||
|
DEBUG=$enableval, DEBUG=no)
|
||||||
|
AC_MSG_RESULT($DEBUG)
|
||||||
|
|
||||||
|
dnl -- Normally turn off optimisation for debug builds
|
||||||
|
if test x$DEBUG = xyes; then
|
||||||
|
COPTIMISE_FLAG=
|
||||||
|
else
|
||||||
|
CSCOPE_CMD=
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Override optimisation
|
||||||
|
AC_MSG_CHECKING(for C optimisation flag)
|
||||||
|
AC_ARG_WITH(optimisation,
|
||||||
|
[ --with-optimisation=OPT C optimisation flag [OPT=-O2] ],
|
||||||
|
[ COPTIMISE_FLAG="$withval" ])
|
||||||
|
AC_MSG_RESULT($COPTIMISE_FLAG)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Disable devmapper
|
||||||
|
AC_MSG_CHECKING(whether to use device-mapper)
|
||||||
|
AC_ARG_ENABLE(devmapper, [ --disable-devmapper Disable 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.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Disable O_DIRECT
|
||||||
|
AC_MSG_CHECKING(whether to enable O_DIRECT)
|
||||||
|
AC_ARG_ENABLE(o_direct, [ --disable-o_direct Disable O_DIRECT],
|
||||||
|
ODIRECT=$enableval)
|
||||||
|
AC_MSG_RESULT($ODIRECT)
|
||||||
|
|
||||||
|
if test x$ODIRECT = xyes; then
|
||||||
|
AC_DEFINE([O_DIRECT_SUPPORT], 1, [Define to 1 to enable O_DIRECT support.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Enable cmdlib
|
||||||
|
AC_MSG_CHECKING(whether to compile liblvm2cmd.so)
|
||||||
|
AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library],
|
||||||
|
CMDLIB=$enableval, CMDLIB=no)
|
||||||
|
AC_MSG_RESULT($CMDLIB)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Enable fsadm
|
||||||
|
AC_MSG_CHECKING(whether to build fsadm)
|
||||||
|
AC_ARG_ENABLE(fsadm, [ --enable-fsadm Enable fsadm],
|
||||||
|
FSADM=$enableval)
|
||||||
|
AC_MSG_RESULT($FSADM)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- enable dmeventd handling
|
||||||
|
AC_MSG_CHECKING(whether to use dmeventd)
|
||||||
|
AC_ARG_ENABLE(dmeventd, [ --enable-dmeventd Enable the device-mapper event daemon],
|
||||||
|
DMEVENTD=$enableval)
|
||||||
|
AC_MSG_RESULT($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
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$DMEVENTD = xyes; then
|
||||||
|
AC_DEFINE([DMEVENTD], 1, [Define to 1 to enable the device-mapper event daemon.])
|
||||||
|
fi
|
||||||
|
################################################################################
|
||||||
|
dnl -- Mess with default exec_prefix
|
||||||
|
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
||||||
|
then exec_prefix="";
|
||||||
|
fi;
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Checks for library functions.
|
||||||
|
AC_PROG_GCC_TRADITIONAL
|
||||||
|
AC_TYPE_SIGNAL
|
||||||
|
AC_FUNC_VPRINTF
|
||||||
|
AC_CHECK_FUNCS(mkdir rmdir uname,,AC_MSG_ERROR(bailing out))
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for termcap (Shamelessly copied from parted 1.4.17)
|
||||||
|
if test x$READLINE = xyes; then
|
||||||
|
AC_SEARCH_LIBS(tgetent, ncurses curses termcap termlib, ,
|
||||||
|
AC_MSG_ERROR(
|
||||||
|
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:
|
||||||
|
ftp.gnu.org/gnu/termcap
|
||||||
|
Note: if you are using precompiled packages you will also need the development
|
||||||
|
package as well (which may be called termcap-devel or something similar).
|
||||||
|
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
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for dlopen
|
||||||
|
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
|
||||||
|
|
||||||
|
if [[ "x$HAVE_LIBDL" = xyes ]]; then
|
||||||
|
AC_DEFINE([HAVE_LIBDL], 1, [Define to 1 if dynamic libraries are available.])
|
||||||
|
LIBS="-ldl $LIBS"
|
||||||
|
else
|
||||||
|
HAVE_LIBDL=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for shared/static conflicts
|
||||||
|
if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o "x$CLUSTER" = xshared \
|
||||||
|
-o "x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
|
||||||
|
\) -a "x$STATIC_LINK" = xyes ]];
|
||||||
|
then AC_MSG_ERROR(
|
||||||
|
Features cannot be 'shared' when building statically
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for selinux
|
||||||
|
if test x$SELINUX = xyes; then
|
||||||
|
AC_CHECK_LIB(sepol, sepol_check_context, HAVE_SEPOL=yes, HAVE_SEPOL=no)
|
||||||
|
|
||||||
|
if test x$HAVE_SEPOL = xyes; then
|
||||||
|
LIBS="-lsepol $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"
|
||||||
|
else
|
||||||
|
AC_MSG_WARN(Disabling selinux)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for realtime clock support
|
||||||
|
if test x$REALTIME = xyes; then
|
||||||
|
AC_CHECK_LIB(rt, clock_gettime, HAVE_REALTIME=yes, HAVE_REALTIME=no)
|
||||||
|
|
||||||
|
if test x$HAVE_REALTIME = xyes; then
|
||||||
|
AC_DEFINE([HAVE_REALTIME], 1, [Define to 1 to include support for realtime clock.])
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
else
|
||||||
|
AC_MSG_WARN(Disabling realtime clock)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for getopt
|
||||||
|
AC_CHECK_HEADERS(getopt.h, AC_DEFINE([HAVE_GETOPTLONG], 1, [Define to 1 to if getopt_long is available.]))
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
|
||||||
|
if test x$READLINE = xyes; then
|
||||||
|
AC_CHECK_LIB(readline, readline, ,
|
||||||
|
AC_MSG_ERROR(
|
||||||
|
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:
|
||||||
|
ftp.gnu.org/gnu/readline
|
||||||
|
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.]))
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Internationalisation stuff
|
||||||
|
AC_MSG_CHECKING(whether to enable internationalisation)
|
||||||
|
AC_ARG_ENABLE(nls, [ --enable-nls Enable Native Language Support],
|
||||||
|
INTL=$enableval, INTL=no)
|
||||||
|
AC_MSG_RESULT($INTL)
|
||||||
|
|
||||||
|
if test x$INTL = xyes; then
|
||||||
|
INTL_PACKAGE="lvm2"
|
||||||
|
AC_PATH_PROG(MSGFMT, msgfmt)
|
||||||
|
if [[ "x$MSGFMT" == x ]];
|
||||||
|
then AC_MSG_ERROR(
|
||||||
|
msgfmt not found in path $PATH
|
||||||
|
)
|
||||||
|
fi;
|
||||||
|
|
||||||
|
AC_ARG_WITH(localedir,
|
||||||
|
[ --with-localedir=DIR Translation files in DIR [PREFIX/share/locale]],
|
||||||
|
[ LOCALEDIR="$withval" ],
|
||||||
|
[ LOCALEDIR='${prefix}/share/locale' ])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
AC_ARG_WITH(confdir,
|
||||||
|
[ --with-confdir=DIR Configuration files in DIR [/etc]],
|
||||||
|
[ CONFDIR="$withval" ],
|
||||||
|
[ CONFDIR='/etc' ])
|
||||||
|
|
||||||
|
AC_ARG_WITH(staticdir,
|
||||||
|
[ --with-staticdir=DIR Static binary in DIR [EXEC_PREFIX/sbin]],
|
||||||
|
[ STATICDIR="$withval" ],
|
||||||
|
[ STATICDIR='${exec_prefix}/sbin' ])
|
||||||
|
|
||||||
|
AC_ARG_WITH(dmdir,
|
||||||
|
[ --with-dmdir=DIR Build against device-mapper source tree in DIR],
|
||||||
|
[ DMDIR="$withval" ],
|
||||||
|
[ DMDIR= ])
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Ensure additional headers required
|
||||||
|
if test x$READLINE = xyes; then
|
||||||
|
AC_CHECK_HEADERS(readline/readline.h readline/history.h,,AC_MSG_ERROR(bailing out))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$CLVMD != xnone; then
|
||||||
|
AC_CHECK_HEADERS(mntent.h netdb.h netinet/in.h pthread.h search.h sys/mount.h sys/socket.h sys/uio.h sys/un.h utmpx.h,,AC_MSG_ERROR(bailing out))
|
||||||
|
AC_CHECK_FUNCS(dup2 getmntent memmove select socket,,AC_MSG_ERROR(bailing out))
|
||||||
|
AC_FUNC_GETMNTENT
|
||||||
|
# AC_FUNC_REALLOC
|
||||||
|
AC_FUNC_SELECT_ARGTYPES
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$FSADM = xyes; then
|
||||||
|
AC_CHECK_HEADERS(fstab.h sys/mount.h sys/vfs.h,,AC_MSG_ERROR(bailing out))
|
||||||
|
AC_CHECK_FUNCS(memmove,,AC_MSG_ERROR(bailing out))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$CLUSTER != xnone; then
|
||||||
|
AC_CHECK_HEADERS(sys/socket.h sys/un.h,,AC_MSG_ERROR(bailing out))
|
||||||
|
AC_CHECK_FUNCS(socket,,AC_MSG_ERROR(bailing out))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x$HAVE_LIBDL = xyes; then
|
||||||
|
AC_CHECK_HEADERS(dlfcn.h,,AC_MSG_ERROR(bailing out))
|
||||||
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
AC_PATH_PROG(MODPROBE_CMD, modprobe)
|
||||||
|
|
||||||
|
if test x$MODPROBE_CMD != x; then
|
||||||
|
AC_DEFINE_UNQUOTED([MODPROBE_CMD], ["$MODPROBE_CMD"], [The path to 'modprobe', if available.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
if test "-f VERSION"; then
|
||||||
|
LVM_VERSION="\"`cat VERSION`\""
|
||||||
|
else
|
||||||
|
LVM_VERSION="Unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
AC_SUBST(JOBS)
|
||||||
|
AC_SUBST(STATIC_LINK)
|
||||||
|
AC_SUBST(LVM1)
|
||||||
|
AC_SUBST(POOL)
|
||||||
|
AC_SUBST(SNAPSHOTS)
|
||||||
|
AC_SUBST(MIRRORS)
|
||||||
|
AC_SUBST(OWNER)
|
||||||
|
AC_SUBST(GROUP)
|
||||||
|
AC_SUBST(CFLAGS)
|
||||||
|
AC_SUBST(COPTIMISE_FLAG)
|
||||||
|
AC_SUBST(CLDFLAGS)
|
||||||
|
AC_SUBST(CLDWHOLEARCHIVE)
|
||||||
|
AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||||
|
AC_SUBST(LDDEPS)
|
||||||
|
AC_SUBST(LDFLAGS)
|
||||||
|
AC_SUBST(LIB_SUFFIX)
|
||||||
|
AC_SUBST(LIBS)
|
||||||
|
AC_SUBST(LVM_VERSION)
|
||||||
|
AC_SUBST(LVM1_FALLBACK)
|
||||||
|
AC_SUBST(DEBUG)
|
||||||
|
AC_SUBST(DEVMAPPER)
|
||||||
|
AC_SUBST(HAVE_LIBDL)
|
||||||
|
AC_SUBST(HAVE_SELINUX)
|
||||||
|
AC_SUBST(HAVE_REALTIME)
|
||||||
|
AC_SUBST(CMDLIB)
|
||||||
|
AC_SUBST(MSGFMT)
|
||||||
|
AC_SUBST(LOCALEDIR)
|
||||||
|
AC_SUBST(CONFDIR)
|
||||||
|
AC_SUBST(STATICDIR)
|
||||||
|
AC_SUBST(DMDIR)
|
||||||
|
AC_SUBST(INTL_PACKAGE)
|
||||||
|
AC_SUBST(INTL)
|
||||||
|
AC_SUBST(CLVMD)
|
||||||
|
AC_SUBST(CLUSTER)
|
||||||
|
AC_SUBST(FSADM)
|
||||||
|
AC_SUBST(DMEVENTD)
|
||||||
|
AC_SUBST(CFLOW_CMD)
|
||||||
|
AC_SUBST(CSCOPE_CMD)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- First and last lines should not contain files to generate in order to
|
||||||
|
dnl -- keep utility scripts running properly
|
||||||
|
AC_OUTPUT( \
|
||||||
|
Makefile \
|
||||||
|
make.tmpl \
|
||||||
|
daemons/Makefile \
|
||||||
|
daemons/clvmd/Makefile \
|
||||||
|
dmeventd/Makefile \
|
||||||
|
dmeventd/mirror/Makefile \
|
||||||
|
doc/Makefile \
|
||||||
|
include/Makefile \
|
||||||
|
lib/Makefile \
|
||||||
|
lib/format1/Makefile \
|
||||||
|
lib/format_pool/Makefile \
|
||||||
|
lib/locking/Makefile \
|
||||||
|
lib/mirror/Makefile \
|
||||||
|
lib/snapshot/Makefile \
|
||||||
|
man/Makefile \
|
||||||
|
po/Makefile \
|
||||||
|
scripts/Makefile \
|
||||||
|
tools/Makefile \
|
||||||
|
tools/version.h \
|
||||||
|
tools/fsadm/Makefile \
|
||||||
|
test/mm/Makefile \
|
||||||
|
test/device/Makefile \
|
||||||
|
test/format1/Makefile \
|
||||||
|
test/regex/Makefile \
|
||||||
|
test/filters/Makefile \
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
23
daemons/Makefile.in
Normal file
23
daemons/Makefile.in
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2004 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@
|
||||||
|
|
||||||
|
ifneq ("@CLVMD@", "none")
|
||||||
|
SUBDIRS = clvmd
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
86
daemons/clvmd/Makefile.in
Normal file
86
daemons/clvmd/Makefile.in
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2004 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@
|
||||||
|
|
||||||
|
SOURCES = \
|
||||||
|
clvmd-command.c \
|
||||||
|
clvmd.c \
|
||||||
|
lvm-functions.c \
|
||||||
|
refresh_clvmd.c \
|
||||||
|
system-lv.c
|
||||||
|
|
||||||
|
ifeq ("@CLVMD@", "gulm")
|
||||||
|
GULM = yes
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@CLVMD@", "cman")
|
||||||
|
CMAN = yes
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@CLVMD@", "all")
|
||||||
|
GULM = yes
|
||||||
|
CMAN = yes
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@DEBUG@", "yes")
|
||||||
|
DEFS += -DDEBUG
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("$(GULM)", "yes")
|
||||||
|
SOURCES += clvmd-gulm.c tcp-comms.c
|
||||||
|
LMLIBS += -lccs -lgulm
|
||||||
|
DEFS += -DUSE_GULM
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("$(CMAN)", "yes")
|
||||||
|
SOURCES += clvmd-cman.c
|
||||||
|
LMLIBS += -ldlm -lcman
|
||||||
|
DEFS += -DUSE_CMAN
|
||||||
|
endif
|
||||||
|
|
||||||
|
TARGETS = \
|
||||||
|
clvmd
|
||||||
|
|
||||||
|
LVMLIBS = -llvm -lpthread
|
||||||
|
|
||||||
|
ifeq ("@DMEVENTD@", "yes")
|
||||||
|
LVMLIBS += -ldevmapper-event
|
||||||
|
endif
|
||||||
|
|
||||||
|
LVMLIBS += -ldevmapper
|
||||||
|
|
||||||
|
DEFS += -D_REENTRANT
|
||||||
|
CFLAGS += -fno-strict-aliasing
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
INSTALL_TARGETS = \
|
||||||
|
install_clvmd
|
||||||
|
|
||||||
|
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
|
||||||
|
$(CC) -o clvmd $(OBJECTS) $(CFLAGS) $(LDFLAGS) \
|
||||||
|
$(LVMLIBS) $(LMLIBS) $(LIBS)
|
||||||
|
|
||||||
|
.PHONY: install_clvmd
|
||||||
|
|
||||||
|
install_clvmd: $(TARGETS)
|
||||||
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) clvmd \
|
||||||
|
$(sbindir)/clvmd
|
||||||
|
|
||||||
|
install: $(INSTALL_TARGETS)
|
||||||
|
|
||||||
|
install_cluster: $(INSTALL_TARGETS)
|
||||||
|
|
||||||
70
daemons/clvmd/clvm.h
Normal file
70
daemons/clvmd/clvm.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Definitions for CLVMD server and clients */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The protocol spoken over the cluster and across the local socket.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CLVM_H
|
||||||
|
#define _CLVM_H
|
||||||
|
|
||||||
|
struct clvm_header {
|
||||||
|
uint8_t cmd; /* See below */
|
||||||
|
uint8_t flags; /* See below */
|
||||||
|
uint16_t xid; /* Transaction ID */
|
||||||
|
uint32_t clientid; /* Only used in Daemon->Daemon comms */
|
||||||
|
int32_t status; /* For replies, whether request succeeded */
|
||||||
|
uint32_t arglen; /* Length of argument below.
|
||||||
|
If >1500 then it will be passed
|
||||||
|
around the cluster in the system LV */
|
||||||
|
char node[1]; /* Actually a NUL-terminated string, node name.
|
||||||
|
If this is empty then the command is
|
||||||
|
forwarded to all cluster nodes unless
|
||||||
|
FLAG_LOCAL is also set. */
|
||||||
|
char args[1]; /* Arguments for the command follow the
|
||||||
|
node name, This member is only
|
||||||
|
valid if the node name is empty */
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
/* Flags */
|
||||||
|
#define CLVMD_FLAG_LOCAL 1 /* Only do this on the local node */
|
||||||
|
#define CLVMD_FLAG_SYSTEMLV 2 /* Data in system LV under my node name */
|
||||||
|
#define CLVMD_FLAG_NODEERRS 4 /* Reply has errors in node-specific portion */
|
||||||
|
|
||||||
|
/* Name of the local socket to communicate between libclvm and clvmd */
|
||||||
|
//static const char CLVMD_SOCKNAME[]="/var/run/clvmd";
|
||||||
|
static const char CLVMD_SOCKNAME[] = "\0clvmd";
|
||||||
|
|
||||||
|
/* Internal commands & replies */
|
||||||
|
#define CLVMD_CMD_REPLY 1
|
||||||
|
#define CLVMD_CMD_VERSION 2 /* Send version around cluster when we start */
|
||||||
|
#define CLVMD_CMD_GOAWAY 3 /* Die if received this - we are running
|
||||||
|
an incompatible version */
|
||||||
|
#define CLVMD_CMD_TEST 4 /* Just for mucking about */
|
||||||
|
|
||||||
|
#define CLVMD_CMD_LOCK 30
|
||||||
|
#define CLVMD_CMD_UNLOCK 31
|
||||||
|
|
||||||
|
/* Lock/Unlock commands */
|
||||||
|
#define CLVMD_CMD_LOCK_LV 50
|
||||||
|
#define CLVMD_CMD_LOCK_VG 51
|
||||||
|
|
||||||
|
/* Misc functions */
|
||||||
|
#define CLVMD_CMD_REFRESH 40
|
||||||
|
#define CLVMD_CMD_GET_CLUSTERNAME 41
|
||||||
|
|
||||||
|
#endif
|
||||||
510
daemons/clvmd/clvmd-cman.c
Normal file
510
daemons/clvmd/clvmd-cman.c
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CMAN communication layer for clvmd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "clvmd-comms.h"
|
||||||
|
#include "clvm.h"
|
||||||
|
#include "libdlm.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "clvmd.h"
|
||||||
|
#include "lvm-functions.h"
|
||||||
|
|
||||||
|
#define LOCKSPACE_NAME "clvmd"
|
||||||
|
|
||||||
|
static int num_nodes;
|
||||||
|
static struct cman_node *nodes = NULL;
|
||||||
|
static struct cman_node this_node;
|
||||||
|
static int count_nodes; /* size of allocated nodes array */
|
||||||
|
static int max_updown_nodes = 50; /* Current size of the allocated array */
|
||||||
|
/* Node up/down status, indexed by nodeid */
|
||||||
|
static int *node_updown = NULL;
|
||||||
|
static dlm_lshandle_t *lockspace;
|
||||||
|
static cman_handle_t c_handle;
|
||||||
|
|
||||||
|
static void count_clvmds_running(void);
|
||||||
|
static void get_members(void);
|
||||||
|
static int nodeid_from_csid(char *csid);
|
||||||
|
static int name_from_nodeid(int nodeid, char *name);
|
||||||
|
static void event_callback(cman_handle_t handle, void *private, int reason, int arg);
|
||||||
|
static void data_callback(cman_handle_t handle, void *private,
|
||||||
|
char *buf, int len, uint8_t port, int nodeid);
|
||||||
|
|
||||||
|
struct lock_wait {
|
||||||
|
pthread_cond_t cond;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
struct dlm_lksb lksb;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int _init_cluster(void)
|
||||||
|
{
|
||||||
|
/* Open the cluster communication socket */
|
||||||
|
c_handle = cman_init(NULL);
|
||||||
|
if (!c_handle) {
|
||||||
|
syslog(LOG_ERR, "Can't open cluster manager socket: %m");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cman_start_recv_data(c_handle, data_callback, CLUSTER_PORT_CLVMD)) {
|
||||||
|
syslog(LOG_ERR, "Can't bind cluster socket: %m");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cman_start_notification(c_handle, event_callback)) {
|
||||||
|
syslog(LOG_ERR, "Can't start cluster event listening");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the cluster members list */
|
||||||
|
get_members();
|
||||||
|
count_clvmds_running();
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
dlm_ls_pthread_init(lockspace);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _cluster_init_completed(void)
|
||||||
|
{
|
||||||
|
clvmd_cluster_init_completed();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _get_main_cluster_fd()
|
||||||
|
{
|
||||||
|
return cman_get_fd(c_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _get_num_nodes()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int nnodes = 0;
|
||||||
|
|
||||||
|
/* return number of ACTIVE nodes */
|
||||||
|
for (i=0; i<num_nodes; i++) {
|
||||||
|
if (nodes[i].cn_member)
|
||||||
|
nnodes++;
|
||||||
|
}
|
||||||
|
return nnodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send_message with the fd check removed */
|
||||||
|
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||||
|
{
|
||||||
|
int nodeid = 0;
|
||||||
|
|
||||||
|
if (csid)
|
||||||
|
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||||
|
|
||||||
|
if (cman_send_data(c_handle, buf, msglen, 0, CLUSTER_PORT_CLVMD, nodeid) <= 0)
|
||||||
|
{
|
||||||
|
log_error(errtext);
|
||||||
|
}
|
||||||
|
return msglen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _get_our_csid(char *csid)
|
||||||
|
{
|
||||||
|
if (this_node.cn_nodeid == 0) {
|
||||||
|
cman_get_node(c_handle, 0, &this_node);
|
||||||
|
}
|
||||||
|
memcpy(csid, &this_node.cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call a callback routine for each node is that known (down means not running a clvmd) */
|
||||||
|
static int _cluster_do_node_callback(struct local_client *client,
|
||||||
|
void (*callback) (struct local_client *, char *,
|
||||||
|
int))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int somedown = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < _get_num_nodes(); i++) {
|
||||||
|
if (nodes[i].cn_member) {
|
||||||
|
callback(client, (char *)&nodes[i].cn_nodeid, node_updown[nodes[i].cn_nodeid]);
|
||||||
|
if (!node_updown[nodes[i].cn_nodeid])
|
||||||
|
somedown = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return somedown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process OOB message from the cluster socket,
|
||||||
|
this currently just means that a node has stopped listening on our port */
|
||||||
|
static void event_callback(cman_handle_t handle, void *private, int reason, int arg)
|
||||||
|
{
|
||||||
|
char namebuf[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||||
|
|
||||||
|
switch (reason) {
|
||||||
|
case CMAN_REASON_PORTCLOSED:
|
||||||
|
name_from_nodeid(arg, namebuf);
|
||||||
|
log_notice("clvmd on node %s has died\n", namebuf);
|
||||||
|
DEBUGLOG("Got port closed message, removing node %s\n", namebuf);
|
||||||
|
|
||||||
|
node_updown[arg] = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMAN_REASON_STATECHANGE:
|
||||||
|
DEBUGLOG("Got state change message, re-reading members list\n");
|
||||||
|
get_members();
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if defined(LIBCMAN_VERSION) && LIBCMAN_VERSION >= 2
|
||||||
|
case CMAN_REASON_PORTOPENED:
|
||||||
|
/* Ignore this, wait for startup message from clvmd itself */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMAN_REASON_TRY_SHUTDOWN:
|
||||||
|
DEBUGLOG("Got try shutdown, sending OK\n");
|
||||||
|
cman_replyto_shutdown(c_handle, 1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
/* ERROR */
|
||||||
|
DEBUGLOG("Got unknown event callback message: %d\n", reason);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct local_client *cman_client;
|
||||||
|
static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||||
|
struct local_client **new_client)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Save this for data_callback */
|
||||||
|
cman_client = fd;
|
||||||
|
|
||||||
|
/* We never return a new client */
|
||||||
|
*new_client = NULL;
|
||||||
|
|
||||||
|
return cman_dispatch(c_handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void data_callback(cman_handle_t handle, void *private,
|
||||||
|
char *buf, int len, uint8_t port, int nodeid)
|
||||||
|
{
|
||||||
|
/* Ignore looped back messages */
|
||||||
|
if (nodeid == this_node.cn_nodeid)
|
||||||
|
return;
|
||||||
|
process_message(cman_client, buf, len, (char *)&nodeid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _add_up_node(char *csid)
|
||||||
|
{
|
||||||
|
/* It's up ! */
|
||||||
|
int nodeid = nodeid_from_csid(csid);
|
||||||
|
|
||||||
|
if (nodeid >= max_updown_nodes) {
|
||||||
|
int new_size = nodeid + 10;
|
||||||
|
int *new_updown = realloc(node_updown, new_size);
|
||||||
|
|
||||||
|
if (new_updown) {
|
||||||
|
node_updown = new_updown;
|
||||||
|
max_updown_nodes = new_size;
|
||||||
|
DEBUGLOG("realloced more space for nodes. now %d\n",
|
||||||
|
max_updown_nodes);
|
||||||
|
} else {
|
||||||
|
log_error
|
||||||
|
("Realloc failed. Node status for clvmd will be wrong. quitting\n");
|
||||||
|
exit(999);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node_updown[nodeid] = 1;
|
||||||
|
DEBUGLOG("Added new node %d to updown list\n", nodeid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _cluster_closedown()
|
||||||
|
{
|
||||||
|
unlock_all();
|
||||||
|
dlm_release_lockspace(LOCKSPACE_NAME, lockspace, 1);
|
||||||
|
cman_finish(c_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_listening(int nodeid)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
do {
|
||||||
|
status = cman_is_listening(c_handle, nodeid, CLUSTER_PORT_CLVMD);
|
||||||
|
if (status < 0 && errno == EBUSY) { /* Don't busywait */
|
||||||
|
sleep(1);
|
||||||
|
errno = EBUSY; /* In case sleep trashes it */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (status < 0 && errno == EBUSY);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the list of CLVMDs running.
|
||||||
|
called only at startup time */
|
||||||
|
static void count_clvmds_running(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_nodes; i++) {
|
||||||
|
node_updown[nodes[i].cn_nodeid] = is_listening(nodes[i].cn_nodeid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a list of active cluster members */
|
||||||
|
static void get_members()
|
||||||
|
{
|
||||||
|
int retnodes;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
num_nodes = cman_get_node_count(c_handle);
|
||||||
|
if (num_nodes == -1) {
|
||||||
|
log_error("Unable to get node count");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not enough room for new nodes list ? */
|
||||||
|
if (num_nodes > count_nodes && nodes) {
|
||||||
|
free(nodes);
|
||||||
|
nodes = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nodes == NULL) {
|
||||||
|
count_nodes = num_nodes + 10; /* Overallocate a little */
|
||||||
|
nodes = malloc(count_nodes * sizeof(struct cman_node));
|
||||||
|
if (!nodes) {
|
||||||
|
log_error("Unable to allocate nodes array\n");
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = cman_get_nodes(c_handle, count_nodes, &retnodes, nodes);
|
||||||
|
if (status < 0) {
|
||||||
|
log_error("Unable to get node details");
|
||||||
|
exit(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node_updown == NULL) {
|
||||||
|
node_updown =
|
||||||
|
(int *) malloc(sizeof(int) *
|
||||||
|
max(num_nodes, max_updown_nodes));
|
||||||
|
memset(node_updown, 0,
|
||||||
|
sizeof(int) * max(num_nodes, max_updown_nodes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Convert a node name to a CSID */
|
||||||
|
static int _csid_from_name(char *csid, char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_nodes; i++) {
|
||||||
|
if (strcmp(name, nodes[i].cn_name) == 0) {
|
||||||
|
memcpy(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a CSID to a node name */
|
||||||
|
static int _name_from_csid(char *csid, char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_nodes; i++) {
|
||||||
|
if (memcmp(csid, &nodes[i].cn_nodeid, CMAN_MAX_CSID_LEN) == 0) {
|
||||||
|
strcpy(name, nodes[i].cn_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Who?? */
|
||||||
|
strcpy(name, "Unknown");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a node ID to a node name */
|
||||||
|
static int name_from_nodeid(int nodeid, char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_nodes; i++) {
|
||||||
|
if (nodeid == nodes[i].cn_nodeid) {
|
||||||
|
strcpy(name, nodes[i].cn_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Who?? */
|
||||||
|
strcpy(name, "Unknown");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a CSID to a node ID */
|
||||||
|
static int nodeid_from_csid(char *csid)
|
||||||
|
{
|
||||||
|
int nodeid;
|
||||||
|
|
||||||
|
memcpy(&nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||||
|
|
||||||
|
return nodeid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _is_quorate()
|
||||||
|
{
|
||||||
|
return cman_is_quorate(c_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sync_ast_routine(void *arg)
|
||||||
|
{
|
||||||
|
struct lock_wait *lwait = arg;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&lwait->mutex);
|
||||||
|
pthread_cond_signal(&lwait->cond);
|
||||||
|
pthread_mutex_unlock(&lwait->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _sync_lock(const char *resource, int mode, int flags, int *lockid)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct lock_wait lwait;
|
||||||
|
|
||||||
|
if (!lockid) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
|
||||||
|
/* Conversions need the lockid in the LKSB */
|
||||||
|
if (flags & LKF_CONVERT)
|
||||||
|
lwait.lksb.sb_lkid = *lockid;
|
||||||
|
|
||||||
|
pthread_cond_init(&lwait.cond, NULL);
|
||||||
|
pthread_mutex_init(&lwait.mutex, NULL);
|
||||||
|
pthread_mutex_lock(&lwait.mutex);
|
||||||
|
|
||||||
|
status = dlm_ls_lock(lockspace,
|
||||||
|
mode,
|
||||||
|
&lwait.lksb,
|
||||||
|
flags,
|
||||||
|
resource,
|
||||||
|
strlen(resource),
|
||||||
|
0, sync_ast_routine, &lwait, NULL, NULL);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
/* Wait for it to complete */
|
||||||
|
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||||
|
pthread_mutex_unlock(&lwait.mutex);
|
||||||
|
|
||||||
|
*lockid = lwait.lksb.sb_lkid;
|
||||||
|
|
||||||
|
errno = lwait.lksb.sb_status;
|
||||||
|
DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
|
||||||
|
if (lwait.lksb.sb_status)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _sync_unlock(const char *resource /* UNUSED */, int lockid)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct lock_wait lwait;
|
||||||
|
|
||||||
|
DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
|
||||||
|
|
||||||
|
pthread_cond_init(&lwait.cond, NULL);
|
||||||
|
pthread_mutex_init(&lwait.mutex, NULL);
|
||||||
|
pthread_mutex_lock(&lwait.mutex);
|
||||||
|
|
||||||
|
status = dlm_ls_unlock(lockspace, lockid, 0, &lwait.lksb, &lwait);
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
/* Wait for it to complete */
|
||||||
|
pthread_cond_wait(&lwait.cond, &lwait.mutex);
|
||||||
|
pthread_mutex_unlock(&lwait.mutex);
|
||||||
|
|
||||||
|
errno = lwait.lksb.sb_status;
|
||||||
|
if (lwait.lksb.sb_status != EUNLOCK)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _get_cluster_name(char *buf, int buflen)
|
||||||
|
{
|
||||||
|
cman_cluster_t cluster_info;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = cman_get_cluster(c_handle, &cluster_info);
|
||||||
|
if (!status) {
|
||||||
|
strncpy(buf, cluster_info.ci_name, buflen);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cluster_ops _cluster_cman_ops = {
|
||||||
|
.cluster_init_completed = _cluster_init_completed,
|
||||||
|
.cluster_send_message = _cluster_send_message,
|
||||||
|
.name_from_csid = _name_from_csid,
|
||||||
|
.csid_from_name = _csid_from_name,
|
||||||
|
.get_num_nodes = _get_num_nodes,
|
||||||
|
.cluster_fd_callback = _cluster_fd_callback,
|
||||||
|
.get_main_cluster_fd = _get_main_cluster_fd,
|
||||||
|
.cluster_do_node_callback = _cluster_do_node_callback,
|
||||||
|
.is_quorate = _is_quorate,
|
||||||
|
.get_our_csid = _get_our_csid,
|
||||||
|
.add_up_node = _add_up_node,
|
||||||
|
.cluster_closedown = _cluster_closedown,
|
||||||
|
.get_cluster_name = _get_cluster_name,
|
||||||
|
.sync_lock = _sync_lock,
|
||||||
|
.sync_unlock = _sync_unlock,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cluster_ops *init_cman_cluster(void)
|
||||||
|
{
|
||||||
|
if (!_init_cluster())
|
||||||
|
return &_cluster_cman_ops;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
306
daemons/clvmd/clvmd-command.c
Normal file
306
daemons/clvmd/clvmd-command.c
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
CLVMD Cluster LVM daemon command processor.
|
||||||
|
|
||||||
|
To add commands to the daemon simply add a processor in do_command and return
|
||||||
|
and messages back in buf and the length in *retlen. The initial value of
|
||||||
|
buflen is the maximum size of the buffer. if buf is not large enough then it
|
||||||
|
may be reallocated by the functions in here to a suitable size bearing in
|
||||||
|
mind that anything larger than the passed-in size will have to be returned
|
||||||
|
using the system LV and so performance will suffer.
|
||||||
|
|
||||||
|
The status return will be negated and passed back to the originating node.
|
||||||
|
|
||||||
|
pre- and post- command routines are called only on the local node. The
|
||||||
|
purpose is primarily to get and release locks, though the pre- routine should
|
||||||
|
also do any other local setups required by the command (if any) and can
|
||||||
|
return a failure code that prevents the command from being distributed around
|
||||||
|
the cluster
|
||||||
|
|
||||||
|
The pre- and post- routines are run in their own thread so can block as long
|
||||||
|
they like, do_command is run in the main clvmd thread so should not block for
|
||||||
|
too long. If the pre-command returns an error code (!=0) then the command
|
||||||
|
will not be propogated around the cluster but the post-command WILL be called
|
||||||
|
|
||||||
|
Also note that the pre and post routine are *always* called on the local
|
||||||
|
node, even if the command to be executed was only requested to run on a
|
||||||
|
remote node. It may peek inside the client structure to check the status of
|
||||||
|
the command.
|
||||||
|
|
||||||
|
The clients of the daemon must, naturally, understand the return messages and
|
||||||
|
codes.
|
||||||
|
|
||||||
|
Routines in here may only READ the values in the client structure passed in
|
||||||
|
apart from client->private which they are free to do what they like with.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "locking.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "lvm-functions.h"
|
||||||
|
#include "clvmd-comms.h"
|
||||||
|
#include "clvm.h"
|
||||||
|
#include "clvmd.h"
|
||||||
|
#include "libdlm.h"
|
||||||
|
|
||||||
|
extern struct cluster_ops *clops;
|
||||||
|
|
||||||
|
/* This is where all the real work happens:
|
||||||
|
NOTE: client will be NULL when this is executed on a remote node */
|
||||||
|
int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
||||||
|
char **buf, int buflen, int *retlen)
|
||||||
|
{
|
||||||
|
char *args = msg->node + strlen(msg->node) + 1;
|
||||||
|
int arglen = msglen - sizeof(struct clvm_header) - strlen(msg->node);
|
||||||
|
int status = 0;
|
||||||
|
char *lockname;
|
||||||
|
struct utsname nodeinfo;
|
||||||
|
unsigned char lock_cmd;
|
||||||
|
unsigned char lock_flags;
|
||||||
|
|
||||||
|
/* Do the command */
|
||||||
|
switch (msg->cmd) {
|
||||||
|
/* Just a test message */
|
||||||
|
case CLVMD_CMD_TEST:
|
||||||
|
if (arglen > buflen) {
|
||||||
|
buflen = arglen + 200;
|
||||||
|
*buf = realloc(*buf, buflen);
|
||||||
|
}
|
||||||
|
uname(&nodeinfo);
|
||||||
|
*retlen = 1 + snprintf(*buf, buflen, "TEST from %s: %s v%s",
|
||||||
|
nodeinfo.nodename, args,
|
||||||
|
nodeinfo.release);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_LOCK_VG:
|
||||||
|
/* Check to see if the VG is in use by LVM1 */
|
||||||
|
status = do_check_lvm1(&args[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_LOCK_LV:
|
||||||
|
/* This is the biggie */
|
||||||
|
lock_cmd = args[0] & 0x3F;
|
||||||
|
lock_flags = args[1];
|
||||||
|
lockname = &args[2];
|
||||||
|
status = do_lock_lv(lock_cmd, lock_flags, lockname);
|
||||||
|
/* Replace EIO with something less scary */
|
||||||
|
if (status == EIO) {
|
||||||
|
*retlen =
|
||||||
|
1 + snprintf(*buf, buflen,
|
||||||
|
get_last_lvm_error());
|
||||||
|
return EIO;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_REFRESH:
|
||||||
|
do_refresh_cache();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||||
|
status = clops->get_cluster_name(*buf, buflen);
|
||||||
|
if (!status)
|
||||||
|
*retlen = strlen(*buf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Won't get here because command is validated in pre_command */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the status of the command and return the error text */
|
||||||
|
if (status) {
|
||||||
|
*retlen = 1 + snprintf(*buf, buflen, strerror(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lock_vg(struct local_client *client)
|
||||||
|
{
|
||||||
|
struct dm_hash_table *lock_hash;
|
||||||
|
struct clvm_header *header =
|
||||||
|
(struct clvm_header *) client->bits.localsock.cmd;
|
||||||
|
unsigned char lock_cmd;
|
||||||
|
unsigned char lock_flags;
|
||||||
|
char *args = header->node + strlen(header->node) + 1;
|
||||||
|
int lkid;
|
||||||
|
int status = 0;
|
||||||
|
char *lockname;
|
||||||
|
|
||||||
|
/* Keep a track of VG locks in our own hash table. In current
|
||||||
|
practice there should only ever be more than two VGs locked
|
||||||
|
if a user tries to merge lots of them at once */
|
||||||
|
if (client->bits.localsock.private) {
|
||||||
|
lock_hash = (struct dm_hash_table *)client->bits.localsock.private;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lock_hash = dm_hash_create(3);
|
||||||
|
if (!lock_hash)
|
||||||
|
return ENOMEM;
|
||||||
|
client->bits.localsock.private = (void *)lock_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_cmd = args[0] & 0x3F;
|
||||||
|
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) {
|
||||||
|
|
||||||
|
lkid = (int)(long)dm_hash_lookup(lock_hash, lockname);
|
||||||
|
if (lkid == 0)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
status = sync_unlock(lockname, lkid);
|
||||||
|
if (status)
|
||||||
|
status = errno;
|
||||||
|
else
|
||||||
|
dm_hash_remove(lock_hash, lockname);
|
||||||
|
}
|
||||||
|
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 (status)
|
||||||
|
status = errno;
|
||||||
|
else
|
||||||
|
dm_hash_insert(lock_hash, lockname, (void *)(long)lkid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Pre-command is a good place to get locks that are needed only for the duration
|
||||||
|
of the commands around the cluster (don't forget to free them in post-command),
|
||||||
|
and to sanity check the command arguments */
|
||||||
|
int do_pre_command(struct local_client *client)
|
||||||
|
{
|
||||||
|
struct clvm_header *header =
|
||||||
|
(struct clvm_header *) client->bits.localsock.cmd;
|
||||||
|
unsigned char lock_cmd;
|
||||||
|
unsigned char lock_flags;
|
||||||
|
char *args = header->node + strlen(header->node) + 1;
|
||||||
|
int lockid;
|
||||||
|
int status = 0;
|
||||||
|
char *lockname;
|
||||||
|
|
||||||
|
switch (header->cmd) {
|
||||||
|
case CLVMD_CMD_TEST:
|
||||||
|
status = sync_lock("CLVMD_TEST", LKM_EXMODE, 0, &lockid);
|
||||||
|
client->bits.localsock.private = (void *)(long)lockid;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_LOCK_VG:
|
||||||
|
status = lock_vg(client);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_LOCK_LV:
|
||||||
|
lock_cmd = args[0];
|
||||||
|
lock_flags = args[1];
|
||||||
|
lockname = &args[2];
|
||||||
|
status = pre_lock_lv(lock_cmd, lock_flags, lockname);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_REFRESH:
|
||||||
|
case CLVMD_CMD_GET_CLUSTERNAME:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_error("Unknown command %d received\n", header->cmd);
|
||||||
|
status = EINVAL;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that the post-command routine is called even if the pre-command or the real command
|
||||||
|
failed */
|
||||||
|
int do_post_command(struct local_client *client)
|
||||||
|
{
|
||||||
|
struct clvm_header *header =
|
||||||
|
(struct clvm_header *) client->bits.localsock.cmd;
|
||||||
|
int status = 0;
|
||||||
|
unsigned char lock_cmd;
|
||||||
|
unsigned char lock_flags;
|
||||||
|
char *args = header->node + strlen(header->node) + 1;
|
||||||
|
char *lockname;
|
||||||
|
|
||||||
|
switch (header->cmd) {
|
||||||
|
case CLVMD_CMD_TEST:
|
||||||
|
status =
|
||||||
|
sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
||||||
|
client->bits.localsock.private = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_LOCK_VG:
|
||||||
|
/* Nothing to do here */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLVMD_CMD_LOCK_LV:
|
||||||
|
lock_cmd = args[0];
|
||||||
|
lock_flags = args[1];
|
||||||
|
lockname = &args[2];
|
||||||
|
status = post_lock_lv(lock_cmd, lock_flags, lockname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Called when the client is about to be deleted */
|
||||||
|
void cmd_client_cleanup(struct local_client *client)
|
||||||
|
{
|
||||||
|
if (client->bits.localsock.private) {
|
||||||
|
|
||||||
|
struct dm_hash_node *v;
|
||||||
|
struct dm_hash_table *lock_hash =
|
||||||
|
(struct dm_hash_table *)client->bits.localsock.private;
|
||||||
|
|
||||||
|
dm_hash_iterate(v, lock_hash) {
|
||||||
|
int lkid = (int)(long)dm_hash_get_data(lock_hash, v);
|
||||||
|
char *lockname = dm_hash_get_key(lock_hash, v);
|
||||||
|
|
||||||
|
DEBUGLOG("cleanup: Unlocking lock %s %x\n", lockname, lkid);
|
||||||
|
sync_unlock(lockname, lkid);
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_hash_destroy(lock_hash);
|
||||||
|
client->bits.localsock.private = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
76
daemons/clvmd/clvmd-comms.h
Normal file
76
daemons/clvmd/clvmd-comms.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abstraction layer for clvmd cluster communications
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CLVMD_COMMS_H
|
||||||
|
#define _CLVMD_COMMS_H
|
||||||
|
|
||||||
|
struct local_client;
|
||||||
|
|
||||||
|
struct cluster_ops {
|
||||||
|
void (*cluster_init_completed) (void);
|
||||||
|
|
||||||
|
int (*cluster_send_message) (void *buf, int msglen, char *csid,
|
||||||
|
const char *errtext);
|
||||||
|
int (*name_from_csid) (char *csid, char *name);
|
||||||
|
int (*csid_from_name) (char *csid, char *name);
|
||||||
|
int (*get_num_nodes) (void);
|
||||||
|
int (*cluster_fd_callback) (struct local_client *fd, char *buf, int len,
|
||||||
|
char *csid, struct local_client **new_client);
|
||||||
|
int (*get_main_cluster_fd) (void); /* gets accept FD or cman cluster socket */
|
||||||
|
int (*cluster_do_node_callback) (struct local_client *client,
|
||||||
|
void (*callback) (struct local_client *,
|
||||||
|
char *csid, int node_up));
|
||||||
|
int (*is_quorate) (void);
|
||||||
|
|
||||||
|
void (*get_our_csid) (char *csid);
|
||||||
|
void (*add_up_node) (char *csid);
|
||||||
|
void (*reread_config) (void);
|
||||||
|
void (*cluster_closedown) (void);
|
||||||
|
|
||||||
|
int (*get_cluster_name)(char *buf, int buflen);
|
||||||
|
|
||||||
|
int (*sync_lock) (const char *resource, int mode, int flags, int *lockid);
|
||||||
|
int (*sync_unlock) (const char *resource, int lockid);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef USE_GULM
|
||||||
|
# include "tcp-comms.h"
|
||||||
|
struct cluster_ops *init_gulm_cluster(void);
|
||||||
|
#define MAX_CSID_LEN GULM_MAX_CSID_LEN
|
||||||
|
#define MAX_CLUSTER_MEMBER_NAME_LEN GULM_MAX_CLUSTER_MEMBER_NAME_LEN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_CMAN
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include "libcman.h"
|
||||||
|
# define CMAN_MAX_CSID_LEN 4
|
||||||
|
# ifndef MAX_CSID_LEN
|
||||||
|
# define MAX_CSID_LEN CMAN_MAX_CSID_LEN
|
||||||
|
# endif
|
||||||
|
# undef MAX_CLUSTER_MEMBER_NAME_LEN
|
||||||
|
# define MAX_CLUSTER_MEMBER_NAME_LEN CMAN_MAX_NODENAME_LEN
|
||||||
|
# define CMAN_MAX_CLUSTER_MESSAGE 1500
|
||||||
|
# define CLUSTER_PORT_CLVMD 11
|
||||||
|
struct cluster_ops *init_cman_cluster(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
1009
daemons/clvmd/clvmd-gulm.c
Normal file
1009
daemons/clvmd/clvmd-gulm.c
Normal file
File diff suppressed because it is too large
Load Diff
13
daemons/clvmd/clvmd-gulm.h
Normal file
13
daemons/clvmd/clvmd-gulm.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
/* DLM constant that clvmd uses as a generic NONBLOCK lock flag */
|
||||||
|
#define LKF_NOQUEUE 1
|
||||||
|
|
||||||
|
extern int get_next_node_csid(void **context, char *csid);
|
||||||
|
extern void add_down_node(char *csid);
|
||||||
|
extern int gulm_fd(void);
|
||||||
|
extern int get_ip_address(char *node, char *addr);
|
||||||
|
extern void tcp_remove_client(char *csid);
|
||||||
|
extern int alloc_client(int fd, char *csid, struct local_client **new_client);
|
||||||
|
|
||||||
|
void gulm_add_up_node(char *csid);
|
||||||
|
int gulm_name_from_csid(char *csid, char *name);
|
||||||
1919
daemons/clvmd/clvmd.c
Normal file
1919
daemons/clvmd/clvmd.c
Normal file
File diff suppressed because it is too large
Load Diff
121
daemons/clvmd/clvmd.h
Normal file
121
daemons/clvmd/clvmd.h
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CLVMD_H
|
||||||
|
#define _CLVMD_H
|
||||||
|
|
||||||
|
#define CLVMD_MAJOR_VERSION 0
|
||||||
|
#define CLVMD_MINOR_VERSION 2
|
||||||
|
#define CLVMD_PATCH_VERSION 1
|
||||||
|
|
||||||
|
/* Name of the cluster LVM admin lock */
|
||||||
|
#define ADMIN_LOCK_NAME "CLVMD_ADMIN"
|
||||||
|
|
||||||
|
/* Default time (in seconds) we will wait for all remote commands to execute
|
||||||
|
before declaring them dead */
|
||||||
|
#define DEFAULT_CMD_TIMEOUT 60
|
||||||
|
|
||||||
|
/* One of these for each reply we get from command execution on a node */
|
||||||
|
struct node_reply {
|
||||||
|
char node[MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||||
|
char *replymsg;
|
||||||
|
int status;
|
||||||
|
struct node_reply *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These exist for the use of local sockets only when we are
|
||||||
|
* collecting responses from all cluster nodes
|
||||||
|
*/
|
||||||
|
struct localsock_bits {
|
||||||
|
struct node_reply *replies;
|
||||||
|
int num_replies;
|
||||||
|
int expected_replies;
|
||||||
|
time_t sent_time; /* So we can check for timeouts */
|
||||||
|
int in_progress; /* Only execute one cmd at a time per client */
|
||||||
|
int sent_out; /* Flag to indicate that a command was sent
|
||||||
|
to remote nodes */
|
||||||
|
void *private; /* Private area for command processor use */
|
||||||
|
void *cmd; /* Whole command as passed down local socket */
|
||||||
|
int cmd_len; /* Length of above */
|
||||||
|
int pipe; /* Pipe to send PRE completion status down */
|
||||||
|
int finished; /* Flag to tell subthread to exit */
|
||||||
|
int all_success; /* Set to 0 if any node (or the pre_command)
|
||||||
|
failed */
|
||||||
|
struct local_client *pipe_client;
|
||||||
|
pthread_t threadid;
|
||||||
|
enum { PRE_COMMAND, POST_COMMAND, QUIT } state;
|
||||||
|
pthread_mutex_t mutex; /* Main thread and worker synchronisation */
|
||||||
|
pthread_cond_t cond;
|
||||||
|
|
||||||
|
pthread_mutex_t reply_mutex; /* Protect reply structure */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Entries for PIPE clients */
|
||||||
|
struct pipe_bits {
|
||||||
|
struct local_client *client; /* Actual (localsock) client */
|
||||||
|
pthread_t threadid; /* Our own copy of the thread id */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Entries for Network socket clients */
|
||||||
|
struct netsock_bits {
|
||||||
|
void *private;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*fd_callback_t) (struct local_client * fd, char *buf, int len,
|
||||||
|
char *csid, struct local_client ** new_client);
|
||||||
|
|
||||||
|
/* One of these for each fd we are listening on */
|
||||||
|
struct local_client {
|
||||||
|
int fd;
|
||||||
|
enum { CLUSTER_MAIN_SOCK, CLUSTER_DATA_SOCK, LOCAL_RENDEZVOUS,
|
||||||
|
LOCAL_SOCK, THREAD_PIPE, CLUSTER_INTERNAL } type;
|
||||||
|
struct local_client *next;
|
||||||
|
unsigned short xid;
|
||||||
|
fd_callback_t callback;
|
||||||
|
uint8_t removeme;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct localsock_bits localsock;
|
||||||
|
struct pipe_bits pipe;
|
||||||
|
struct netsock_bits net;
|
||||||
|
} bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEBUGLOG(fmt, args...) debuglog(fmt, ## args);
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
#define max(a,b) ((a)>(b)?(a):(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The real command processor is in clvmd-command.c */
|
||||||
|
extern int do_command(struct local_client *client, struct clvm_header *msg,
|
||||||
|
int msglen, char **buf, int buflen, int *retlen);
|
||||||
|
|
||||||
|
/* Pre and post command routines are called only on the local node */
|
||||||
|
extern int do_pre_command(struct local_client *client);
|
||||||
|
extern int do_post_command(struct local_client *client);
|
||||||
|
extern void cmd_client_cleanup(struct local_client *client);
|
||||||
|
extern int add_client(struct local_client *new_client);
|
||||||
|
|
||||||
|
extern void clvmd_cluster_init_completed(void);
|
||||||
|
extern void process_message(struct local_client *client, char *buf, int len, char *csid);
|
||||||
|
extern void debuglog(const char *fmt, ... );
|
||||||
|
|
||||||
|
int sync_lock(const char *resource, int mode, int flags, int *lockid);
|
||||||
|
int sync_unlock(const char *resource, int lockid);
|
||||||
|
|
||||||
|
#endif
|
||||||
226
daemons/clvmd/cnxman-socket.h
Normal file
226
daemons/clvmd/cnxman-socket.h
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*******************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
|
||||||
|
** Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
**
|
||||||
|
** This copyrighted material is made available to anyone wishing to use,
|
||||||
|
** modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
** of the GNU General Public License v.2.
|
||||||
|
**
|
||||||
|
*******************************************************************************
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* CMAN socket interface header,
|
||||||
|
may be include by user or kernel code */
|
||||||
|
|
||||||
|
#ifndef __CNXMAN_SOCKET_H
|
||||||
|
#define __CNXMAN_SOCKET_H
|
||||||
|
|
||||||
|
/* A currently unused number. TIPC also uses this number and you're unlikely
|
||||||
|
to be using both.
|
||||||
|
*/
|
||||||
|
#define AF_CLUSTER 30
|
||||||
|
#define PF_CLUSTER AF_CLUSTER
|
||||||
|
|
||||||
|
/* Protocol(socket) types */
|
||||||
|
#define CLPROTO_MASTER 2
|
||||||
|
#define CLPROTO_CLIENT 3
|
||||||
|
|
||||||
|
/* ioctls -- should register these properly */
|
||||||
|
#define SIOCCLUSTER_NOTIFY _IOW('x', 0x01, int)
|
||||||
|
#define SIOCCLUSTER_REMOVENOTIFY _IO( 'x', 0x02)
|
||||||
|
#define SIOCCLUSTER_GETMEMBERS _IOR('x', 0x03, struct cl_cluster_nodelist)
|
||||||
|
#define SIOCCLUSTER_SETEXPECTED_VOTES _IOW('x', 0x04, int)
|
||||||
|
#define SIOCCLUSTER_ISQUORATE _IO( 'x', 0x05)
|
||||||
|
#define SIOCCLUSTER_ISLISTENING _IOW('x', 0x06, struct cl_listen_request)
|
||||||
|
#define SIOCCLUSTER_GETALLMEMBERS _IOR('x', 0x07, struct cl_cluster_nodelist)
|
||||||
|
#define SIOCCLUSTER_SET_VOTES _IOW('x', 0x08, int)
|
||||||
|
#define SIOCCLUSTER_GET_VERSION _IOR('x', 0x09, struct cl_version)
|
||||||
|
#define SIOCCLUSTER_SET_VERSION _IOW('x', 0x0a, struct cl_version)
|
||||||
|
#define SIOCCLUSTER_ISACTIVE _IO( 'x', 0x0b)
|
||||||
|
#define SIOCCLUSTER_KILLNODE _IOW('x', 0x0c, int)
|
||||||
|
#define SIOCCLUSTER_GET_JOINCOUNT _IO( 'x', 0x0d)
|
||||||
|
#define SIOCCLUSTER_SERVICE_REGISTER _IOW('x', 0x0e, char)
|
||||||
|
#define SIOCCLUSTER_SERVICE_UNREGISTER _IO('x', 0x0f)
|
||||||
|
#define SIOCCLUSTER_SERVICE_JOIN _IO( 'x', 0x10)
|
||||||
|
#define SIOCCLUSTER_SERVICE_LEAVE _IO( 'x', 0x20)
|
||||||
|
#define SIOCCLUSTER_SERVICE_SETSIGNAL _IOW('x', 0x30, int)
|
||||||
|
#define SIOCCLUSTER_SERVICE_STARTDONE _IOW('x', 0x40, unsigned int)
|
||||||
|
#define SIOCCLUSTER_SERVICE_GETEVENT _IOR('x', 0x50, struct cl_service_event)
|
||||||
|
#define SIOCCLUSTER_SERVICE_GETMEMBERS _IOR('x', 0x60, struct cl_cluster_nodelist)
|
||||||
|
#define SIOCCLUSTER_SERVICE_GLOBALID _IOR('x', 0x70, uint32_t)
|
||||||
|
#define SIOCCLUSTER_SERVICE_SETLEVEL _IOR('x', 0x80, int)
|
||||||
|
#define SIOCCLUSTER_GETNODE _IOWR('x', 0x90, struct cl_cluster_node)
|
||||||
|
#define SIOCCLUSTER_BARRIER _IOW('x', 0x0a0, struct cl_barrier_info)
|
||||||
|
|
||||||
|
/* These were setsockopts */
|
||||||
|
#define SIOCCLUSTER_PASS_SOCKET _IOW('x', 0x0b0, struct cl_passed_sock)
|
||||||
|
#define SIOCCLUSTER_SET_NODENAME _IOW('x', 0x0b1, char *)
|
||||||
|
#define SIOCCLUSTER_SET_NODEID _IOW('x', 0x0b2, int)
|
||||||
|
#define SIOCCLUSTER_JOIN_CLUSTER _IOW('x', 0x0b3, struct cl_join_cluster_info)
|
||||||
|
#define SIOCCLUSTER_LEAVE_CLUSTER _IOW('x', 0x0b4, int)
|
||||||
|
|
||||||
|
|
||||||
|
/* Maximum size of a cluster message */
|
||||||
|
#define CMAN_MAX_CLUSTER_MESSAGE 1500
|
||||||
|
#define CMAN_MAX_CLUSTER_MEMBER_NAME_LEN 255
|
||||||
|
#define MAX_BARRIER_NAME_LEN 33
|
||||||
|
#define MAX_SA_ADDR_LEN 12
|
||||||
|
#define MAX_CLUSTER_NAME_LEN 16
|
||||||
|
|
||||||
|
/* Well-known cluster port numbers */
|
||||||
|
#define CLUSTER_PORT_MEMBERSHIP 1 /* Mustn't block during cluster
|
||||||
|
* transitions! */
|
||||||
|
#define CLUSTER_PORT_SERVICES 2
|
||||||
|
#define CLUSTER_PORT_SYSMAN 10 /* Remote execution daemon */
|
||||||
|
#define CLUSTER_PORT_CLVMD 11 /* Cluster LVM daemon */
|
||||||
|
#define CLUSTER_PORT_SLM 12 /* LVM SLM (simple lock manager) */
|
||||||
|
|
||||||
|
/* Port numbers above this will be blocked when the cluster is inquorate or in
|
||||||
|
* transition */
|
||||||
|
#define HIGH_PROTECTED_PORT 9
|
||||||
|
|
||||||
|
/* Reasons for leaving the cluster */
|
||||||
|
#define CLUSTER_LEAVEFLAG_DOWN 0 /* Normal shutdown */
|
||||||
|
#define CLUSTER_LEAVEFLAG_KILLED 1
|
||||||
|
#define CLUSTER_LEAVEFLAG_PANIC 2
|
||||||
|
#define CLUSTER_LEAVEFLAG_REMOVED 3 /* This one can reduce quorum */
|
||||||
|
#define CLUSTER_LEAVEFLAG_REJECTED 4 /* Not allowed into the cluster in the
|
||||||
|
* first place */
|
||||||
|
#define CLUSTER_LEAVEFLAG_INCONSISTENT 5 /* Our view of the cluster is
|
||||||
|
* in a minority */
|
||||||
|
#define CLUSTER_LEAVEFLAG_DEAD 6 /* Discovered to be dead */
|
||||||
|
#define CLUSTER_LEAVEFLAG_FORCE 0x10 /* Forced by command-line */
|
||||||
|
|
||||||
|
/* OOB messages sent to a local socket */
|
||||||
|
#define CLUSTER_OOB_MSG_PORTCLOSED 1
|
||||||
|
#define CLUSTER_OOB_MSG_STATECHANGE 2
|
||||||
|
#define CLUSTER_OOB_MSG_SERVICEEVENT 3
|
||||||
|
|
||||||
|
/* Sendmsg flags, these are above the normal sendmsg flags so they don't
|
||||||
|
* interfere */
|
||||||
|
#define MSG_NOACK 0x010000 /* Don't need an ACK for this message */
|
||||||
|
#define MSG_QUEUE 0x020000 /* Queue the message for sending later */
|
||||||
|
#define MSG_MULTICAST 0x080000 /* Message was sent to all nodes in the cluster
|
||||||
|
*/
|
||||||
|
#define MSG_ALLINT 0x100000 /* Send out of all interfaces */
|
||||||
|
#define MSG_REPLYEXP 0x200000 /* Reply is expected */
|
||||||
|
|
||||||
|
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
|
||||||
|
NODESTATE_DEAD } nodestate_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct sockaddr_cl {
|
||||||
|
unsigned short scl_family;
|
||||||
|
unsigned char scl_flags;
|
||||||
|
unsigned char scl_port;
|
||||||
|
int scl_nodeid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is how we pass the multicast & receive sockets into kernel space.
|
||||||
|
*/
|
||||||
|
struct cl_passed_sock {
|
||||||
|
int fd; /* FD of master socket to do multicast on */
|
||||||
|
int number; /* Socket number, to match up recvonly & bcast
|
||||||
|
* sockets */
|
||||||
|
int multicast; /* Is it multicast or receive ? */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Cluster configuration info passed when we join the cluster */
|
||||||
|
struct cl_join_cluster_info {
|
||||||
|
unsigned char votes;
|
||||||
|
unsigned int expected_votes;
|
||||||
|
unsigned int two_node;
|
||||||
|
unsigned int config_version;
|
||||||
|
|
||||||
|
char cluster_name[17];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the structure, per node, returned from the membership ioctl */
|
||||||
|
struct cl_cluster_node {
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int node_id;
|
||||||
|
unsigned int us;
|
||||||
|
unsigned int leave_reason;
|
||||||
|
unsigned int incarnation;
|
||||||
|
nodestate_t state;
|
||||||
|
char name[CMAN_MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||||
|
unsigned char votes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The struct passed to the membership ioctls */
|
||||||
|
struct cl_cluster_nodelist {
|
||||||
|
uint32_t max_members;
|
||||||
|
struct cl_cluster_node *nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Structure passed to SIOCCLUSTER_ISLISTENING */
|
||||||
|
struct cl_listen_request {
|
||||||
|
unsigned char port;
|
||||||
|
int nodeid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* A Cluster PORTCLOSED message - received by a local user as an OOB message */
|
||||||
|
struct cl_portclosed_oob {
|
||||||
|
unsigned char cmd; /* CLUSTER_OOB_MSG_PORTCLOSED */
|
||||||
|
unsigned char port;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Get all version numbers or set the config version */
|
||||||
|
struct cl_version {
|
||||||
|
unsigned int major;
|
||||||
|
unsigned int minor;
|
||||||
|
unsigned int patch;
|
||||||
|
unsigned int config;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* structure passed to barrier ioctls */
|
||||||
|
struct cl_barrier_info {
|
||||||
|
char cmd;
|
||||||
|
char name[MAX_BARRIER_NAME_LEN];
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned long arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum { SERVICE_EVENT_STOP, SERVICE_EVENT_START, SERVICE_EVENT_FINISH,
|
||||||
|
SERVICE_EVENT_LEAVEDONE } service_event_t;
|
||||||
|
|
||||||
|
typedef enum { SERVICE_START_FAILED, SERVICE_START_JOIN, SERVICE_START_LEAVE }
|
||||||
|
service_start_t;
|
||||||
|
|
||||||
|
struct cl_service_event {
|
||||||
|
service_event_t type;
|
||||||
|
service_start_t start_type;
|
||||||
|
unsigned int event_id;
|
||||||
|
unsigned int last_stop;
|
||||||
|
unsigned int last_start;
|
||||||
|
unsigned int last_finish;
|
||||||
|
unsigned int node_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Commands to the barrier ioctl */
|
||||||
|
#define BARRIER_IOCTL_REGISTER 1
|
||||||
|
#define BARRIER_IOCTL_CHANGE 2
|
||||||
|
#define BARRIER_IOCTL_DELETE 3
|
||||||
|
#define BARRIER_IOCTL_WAIT 4
|
||||||
|
|
||||||
|
/* Attributes of a barrier - bitmask */
|
||||||
|
#define BARRIER_ATTR_AUTODELETE 1
|
||||||
|
#define BARRIER_ATTR_MULTISTEP 2
|
||||||
|
#define BARRIER_ATTR_MANUAL 4
|
||||||
|
#define BARRIER_ATTR_ENABLED 8
|
||||||
|
#define BARRIER_ATTR_CALLBACK 16
|
||||||
|
|
||||||
|
/* Attribute setting commands */
|
||||||
|
#define BARRIER_SETATTR_AUTODELETE 1
|
||||||
|
#define BARRIER_SETATTR_MULTISTEP 2
|
||||||
|
#define BARRIER_SETATTR_ENABLED 3
|
||||||
|
#define BARRIER_SETATTR_NODES 4
|
||||||
|
#define BARRIER_SETATTR_CALLBACK 5
|
||||||
|
#define BARRIER_SETATTR_TIMEOUT 6
|
||||||
|
|
||||||
|
#endif
|
||||||
602
daemons/clvmd/lvm-functions.c
Normal file
602
daemons/clvmd/lvm-functions.c
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "lvm-types.h"
|
||||||
|
#include "libdlm.h"
|
||||||
|
#include "clvm.h"
|
||||||
|
#include "clvmd-comms.h"
|
||||||
|
#include "clvmd.h"
|
||||||
|
#include "lvm-functions.h"
|
||||||
|
|
||||||
|
/* LVM2 headers */
|
||||||
|
#include "toolcontext.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "activate.h"
|
||||||
|
#include "locking.h"
|
||||||
|
#include "defaults.h"
|
||||||
|
|
||||||
|
static struct cmd_context *cmd = NULL;
|
||||||
|
static struct dm_hash_table *lv_hash = NULL;
|
||||||
|
static pthread_mutex_t lv_hash_lock;
|
||||||
|
static char last_error[1024];
|
||||||
|
|
||||||
|
struct lv_info {
|
||||||
|
int lock_id;
|
||||||
|
int lock_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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->lock_mode;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called at shutdown to tidy the lockspace */
|
||||||
|
void unlock_all()
|
||||||
|
{
|
||||||
|
struct dm_hash_node *v;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lv_hash_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets a real lock and keeps the info in the hash table */
|
||||||
|
int hold_lock(char *resource, int mode, int flags)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
int saved_errno;
|
||||||
|
struct lv_info *lvi;
|
||||||
|
|
||||||
|
flags &= LKF_NOQUEUE; /* Only LKF_NOQUEUE is valid here */
|
||||||
|
|
||||||
|
pthread_mutex_lock(&lv_hash_lock);
|
||||||
|
lvi = dm_hash_lookup(lv_hash, resource);
|
||||||
|
pthread_mutex_unlock(&lv_hash_lock);
|
||||||
|
if (lvi) {
|
||||||
|
/* Already exists - convert it */
|
||||||
|
status =
|
||||||
|
sync_lock(resource, mode, LKF_CONVERT | flags,
|
||||||
|
&lvi->lock_id);
|
||||||
|
saved_errno = errno;
|
||||||
|
if (!status)
|
||||||
|
lvi->lock_mode = mode;
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
DEBUGLOG("hold_lock. convert to %d failed: %s\n", mode,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
errno = saved_errno;
|
||||||
|
} else {
|
||||||
|
lvi = malloc(sizeof(struct lv_info));
|
||||||
|
if (!lvi)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
lvi->lock_mode = mode;
|
||||||
|
status = sync_lock(resource, mode, flags, &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);
|
||||||
|
}
|
||||||
|
errno = saved_errno;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock and remove it from the hash table */
|
||||||
|
int hold_unlock(char *resource)
|
||||||
|
{
|
||||||
|
struct lv_info *lvi;
|
||||||
|
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) {
|
||||||
|
DEBUGLOG("hold_unlock, lock not already held\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
free(lvi);
|
||||||
|
} else {
|
||||||
|
DEBUGLOG("hold_unlock. unlock failed(%d): %s\n", status,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = saved_errno;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Watch the return codes here.
|
||||||
|
liblvm API functions return 1(true) for success, 0(false) for failure and don't set errno.
|
||||||
|
libdlm API functions return 0 for success, -1 for failure and do set errno.
|
||||||
|
These functions here return 0 for success or >0 for failure (where the retcode is errno)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Activate LV exclusive or non-exclusive */
|
||||||
|
static int do_activate_lv(char *resource, unsigned char lock_flags, int mode)
|
||||||
|
{
|
||||||
|
int oldmode;
|
||||||
|
int status;
|
||||||
|
int activate_lv;
|
||||||
|
int exclusive = 0;
|
||||||
|
struct lvinfo lvi;
|
||||||
|
|
||||||
|
/* Is it already open ? */
|
||||||
|
oldmode = get_current_lock(resource);
|
||||||
|
if (oldmode == mode) {
|
||||||
|
return 0; /* Nothing to do */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does the config file want us to activate this LV ? */
|
||||||
|
if (!lv_activation_filter(cmd, resource, &activate_lv))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
if (!activate_lv)
|
||||||
|
return 0; /* Success, we did nothing! */
|
||||||
|
|
||||||
|
/* Do we need to activate exclusively? */
|
||||||
|
if ((activate_lv == 2) || (mode == LKM_EXMODE)) {
|
||||||
|
exclusive = 1;
|
||||||
|
mode = LKM_EXMODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get the lock if it's a clustered volume group */
|
||||||
|
if (lock_flags & LCK_CLUSTER_VG) {
|
||||||
|
status = hold_lock(resource, mode, LKF_NOQUEUE);
|
||||||
|
if (status) {
|
||||||
|
/* Return an LVM-sensible error for this.
|
||||||
|
* Forcing EIO makes the upper level return this text
|
||||||
|
* rather than the strerror text for EAGAIN.
|
||||||
|
*/
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
sprintf(last_error, "Volume is busy on another node");
|
||||||
|
errno = EIO;
|
||||||
|
}
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If it's suspended then resume it */
|
||||||
|
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
if (lvi.suspended)
|
||||||
|
if (!lv_resume(cmd, resource))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
/* Now activate it */
|
||||||
|
if (!lv_activate(cmd, resource, exclusive))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resume the LV if it was active */
|
||||||
|
static int do_resume_lv(char *resource)
|
||||||
|
{
|
||||||
|
int oldmode;
|
||||||
|
|
||||||
|
/* Is it open ? */
|
||||||
|
oldmode = get_current_lock(resource);
|
||||||
|
if (oldmode == -1) {
|
||||||
|
DEBUGLOG("do_resume_lv, lock not already held\n");
|
||||||
|
return 0; /* We don't need to do anything */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lv_resume_if_active(cmd, resource))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Suspend the device if active */
|
||||||
|
static int do_suspend_lv(char *resource)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
return 0; /* Not active, so it's OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only suspend it if it exists */
|
||||||
|
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
if (lvi.exists) {
|
||||||
|
if (!lv_suspend_if_active(cmd, resource)) {
|
||||||
|
return EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_deactivate_lv(char *resource, unsigned char lock_flags)
|
||||||
|
{
|
||||||
|
int oldmode;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* Is it open ? */
|
||||||
|
oldmode = get_current_lock(resource);
|
||||||
|
if (oldmode == -1 && (lock_flags & LCK_CLUSTER_VG)) {
|
||||||
|
DEBUGLOG("do_deactivate_lock, lock not already held\n");
|
||||||
|
return 0; /* We don't need to do anything */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lv_deactivate(cmd, resource))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
if (lock_flags & LCK_CLUSTER_VG) {
|
||||||
|
status = hold_unlock(resource);
|
||||||
|
if (status)
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the LOCK_LV part that happens on all nodes in the cluster -
|
||||||
|
it is responsible for the interaction with device-mapper and LVM */
|
||||||
|
int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
DEBUGLOG("do_lock_lv: resource '%s', cmd = 0x%x, flags = %x\n",
|
||||||
|
resource, command, lock_flags);
|
||||||
|
|
||||||
|
if (!cmd->config_valid || config_files_changed(cmd)) {
|
||||||
|
/* Reinitialise various settings inc. logging, filters */
|
||||||
|
if (!refresh_toolcontext(cmd)) {
|
||||||
|
log_error("Updated config file invalid. Aborting.");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lock_flags & LCK_PARTIAL_MODE)
|
||||||
|
init_partial(1);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
case LCK_LV_EXCLUSIVE:
|
||||||
|
status = do_activate_lv(resource, lock_flags, LKM_EXMODE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LCK_LV_SUSPEND:
|
||||||
|
status = do_suspend_lv(resource);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LCK_UNLOCK:
|
||||||
|
case LCK_LV_RESUME: /* if active */
|
||||||
|
status = do_resume_lv(resource);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LCK_LV_ACTIVATE:
|
||||||
|
status = do_activate_lv(resource, lock_flags, LKM_CRMODE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LCK_LV_DEACTIVATE:
|
||||||
|
status = do_deactivate_lv(resource, lock_flags);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUGLOG("Invalid LV command 0x%x\n", command);
|
||||||
|
status = EINVAL;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* clean the pool for another command */
|
||||||
|
dm_pool_empty(cmd->mem);
|
||||||
|
|
||||||
|
DEBUGLOG("Command return is %d\n", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Functions to do on the local node only BEFORE the cluster-wide stuff above happens */
|
||||||
|
int pre_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
|
||||||
|
{
|
||||||
|
/* Nearly all the stuff happens cluster-wide. Apart from SUSPEND. Here we get the
|
||||||
|
lock out on this node (because we are the node modifying the metadata)
|
||||||
|
before suspending cluster-wide.
|
||||||
|
*/
|
||||||
|
if (command == LCK_LV_SUSPEND) {
|
||||||
|
DEBUGLOG("pre_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||||
|
resource, command, lock_flags);
|
||||||
|
|
||||||
|
if (hold_lock(resource, LKM_PWMODE, LKF_NOQUEUE))
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Functions to do on the local node only AFTER the cluster-wide stuff above happens */
|
||||||
|
int post_lock_lv(unsigned char command, unsigned char lock_flags,
|
||||||
|
char *resource)
|
||||||
|
{
|
||||||
|
/* Opposite of above, done on resume after a metadata update */
|
||||||
|
if (command == LCK_LV_RESUME) {
|
||||||
|
int oldmode;
|
||||||
|
|
||||||
|
DEBUGLOG
|
||||||
|
("post_lock_lv: resource '%s', cmd = 0x%x, flags = %d\n",
|
||||||
|
resource, command, lock_flags);
|
||||||
|
|
||||||
|
/* If the lock state is PW then restore it to what it was */
|
||||||
|
oldmode = get_current_lock(resource);
|
||||||
|
if (oldmode == LKM_PWMODE) {
|
||||||
|
struct lvinfo lvi;
|
||||||
|
|
||||||
|
if (!lv_info_by_lvid(cmd, resource, &lvi, 0))
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
if (lvi.exists) {
|
||||||
|
if (hold_lock(resource, LKM_CRMODE, 0))
|
||||||
|
return errno;
|
||||||
|
} else {
|
||||||
|
if (hold_unlock(resource))
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if a VG is un use by LVM1 so we don't stomp on it */
|
||||||
|
int do_check_lvm1(char *vgname)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = check_lvm1_vg_inactive(cmd, vgname);
|
||||||
|
|
||||||
|
return status == 1 ? 0 : EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_refresh_cache()
|
||||||
|
{
|
||||||
|
DEBUGLOG("Refreshing context\n");
|
||||||
|
log_notice("Refreshing context");
|
||||||
|
return refresh_toolcontext(cmd)==1?0:-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Only called at gulm startup. Drop any leftover VG or P_orphan locks
|
||||||
|
that might be hanging around if we died for any reason
|
||||||
|
*/
|
||||||
|
static void drop_vg_locks()
|
||||||
|
{
|
||||||
|
char vg[128];
|
||||||
|
char line[255];
|
||||||
|
FILE *vgs =
|
||||||
|
popen
|
||||||
|
("lvm pvs --nolocking --noheadings -o vg_name", "r");
|
||||||
|
|
||||||
|
sync_unlock("P_orphans", LCK_EXCL);
|
||||||
|
|
||||||
|
if (!vgs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), vgs)) {
|
||||||
|
char *vgend;
|
||||||
|
char *vgstart;
|
||||||
|
|
||||||
|
if (line[strlen(line)-1] == '\n')
|
||||||
|
line[strlen(line)-1] = '\0';
|
||||||
|
|
||||||
|
vgstart = line + strspn(line, " ");
|
||||||
|
vgend = vgstart + strcspn(vgstart, " ");
|
||||||
|
*vgend = '\0';
|
||||||
|
|
||||||
|
if (strncmp(vgstart, "WARNING:", 8) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sprintf(vg, "V_%s", vgstart);
|
||||||
|
sync_unlock(vg, LCK_EXCL);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (fclose(vgs))
|
||||||
|
DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ideally, clvmd should be started before any LVs are active
|
||||||
|
* but this may not be the case...
|
||||||
|
* I suppose this also comes in handy if clvmd crashes, not that it would!
|
||||||
|
*/
|
||||||
|
static void *get_initial_state()
|
||||||
|
{
|
||||||
|
char lv[64], vg[64], flags[25], vg_flags[25];
|
||||||
|
char uuid[65];
|
||||||
|
char line[255];
|
||||||
|
FILE *lvs =
|
||||||
|
popen
|
||||||
|
("lvm lvs --nolocking --noheadings -o vg_uuid,lv_uuid,lv_attr,vg_attr",
|
||||||
|
"r");
|
||||||
|
|
||||||
|
if (!lvs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), lvs)) {
|
||||||
|
if (sscanf(line, "%s %s %s %s\n", vg, lv, flags, vg_flags) == 4) {
|
||||||
|
|
||||||
|
/* States: s:suspended a:active S:dropped snapshot I:invalid snapshot */
|
||||||
|
if (strlen(vg) == 38 && /* is is a valid UUID ? */
|
||||||
|
(flags[4] == 'a' || flags[4] == 's') && /* is it active or suspended? */
|
||||||
|
vg_flags[5] == 'c') { /* is it clustered ? */
|
||||||
|
/* Convert hyphen-separated UUIDs into one */
|
||||||
|
memcpy(&uuid[0], &vg[0], 6);
|
||||||
|
memcpy(&uuid[6], &vg[7], 4);
|
||||||
|
memcpy(&uuid[10], &vg[12], 4);
|
||||||
|
memcpy(&uuid[14], &vg[17], 4);
|
||||||
|
memcpy(&uuid[18], &vg[22], 4);
|
||||||
|
memcpy(&uuid[22], &vg[27], 4);
|
||||||
|
memcpy(&uuid[26], &vg[32], 6);
|
||||||
|
memcpy(&uuid[32], &lv[0], 6);
|
||||||
|
memcpy(&uuid[38], &lv[7], 4);
|
||||||
|
memcpy(&uuid[42], &lv[12], 4);
|
||||||
|
memcpy(&uuid[46], &lv[17], 4);
|
||||||
|
memcpy(&uuid[50], &lv[22], 4);
|
||||||
|
memcpy(&uuid[54], &lv[27], 4);
|
||||||
|
memcpy(&uuid[58], &lv[32], 6);
|
||||||
|
uuid[64] = '\0';
|
||||||
|
|
||||||
|
DEBUGLOG("getting initial lock for %s\n", uuid);
|
||||||
|
hold_lock(uuid, LKM_CRMODE, LKF_NOQUEUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fclose(lvs))
|
||||||
|
DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lvm2_log_fn(int level, const char *file, int line,
|
||||||
|
const char *message)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Ignore non-error messages, but store the latest one for returning
|
||||||
|
* to the user.
|
||||||
|
*/
|
||||||
|
if (level != _LOG_ERR && level != _LOG_FATAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
strncpy(last_error, message, sizeof(last_error));
|
||||||
|
last_error[sizeof(last_error)-1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This checks some basic cluster-LVM configuration stuff */
|
||||||
|
static void check_config()
|
||||||
|
{
|
||||||
|
int locking_type;
|
||||||
|
|
||||||
|
locking_type = find_config_tree_int(cmd, "global/locking_type", 1);
|
||||||
|
|
||||||
|
if (locking_type == 3) /* compiled-in cluster support */
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (locking_type == 2) { /* External library, check name */
|
||||||
|
const char *libname;
|
||||||
|
|
||||||
|
libname = find_config_tree_str(cmd, "global/locking_library",
|
||||||
|
"");
|
||||||
|
if (strstr(libname, "liblvm2clusterlock.so"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
log_error("Incorrect LVM locking library specified in lvm.conf, cluster operations may not work.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log_error("locking_type not set correctly in lvm.conf, cluster operations will not work.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_lvhash()
|
||||||
|
{
|
||||||
|
/* Create hash table for keeping LV locks & status */
|
||||||
|
lv_hash = dm_hash_create(100);
|
||||||
|
pthread_mutex_init(&lv_hash_lock, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called to initialise the LVM context of the daemon */
|
||||||
|
int init_lvm(int using_gulm)
|
||||||
|
{
|
||||||
|
if (!(cmd = create_toolcontext(NULL, 0, 1))) {
|
||||||
|
log_error("Failed to allocate command context");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use LOG_DAEMON for syslog messages instead of LOG_USER */
|
||||||
|
init_syslog(LOG_DAEMON);
|
||||||
|
init_debug(_LOG_ERR);
|
||||||
|
|
||||||
|
/* Check lvm.conf is setup for cluster-LVM */
|
||||||
|
check_config();
|
||||||
|
|
||||||
|
/* Remove any non-LV locks that may have been left around */
|
||||||
|
if (using_gulm)
|
||||||
|
drop_vg_locks();
|
||||||
|
|
||||||
|
get_initial_state();
|
||||||
|
|
||||||
|
/* Trap log messages so we can pass them back to the user */
|
||||||
|
init_log_fn(lvm2_log_fn);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
37
daemons/clvmd/lvm-functions.h
Normal file
37
daemons/clvmd/lvm-functions.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Functions in lvm-functions.c */
|
||||||
|
|
||||||
|
#ifndef _LVM_FUNCTIONS_H
|
||||||
|
#define _LVM_FUNCTIONS_H
|
||||||
|
|
||||||
|
extern int pre_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||||
|
char *resource);
|
||||||
|
extern int do_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||||
|
char *resource);
|
||||||
|
extern int post_lock_lv(unsigned char lock_cmd, unsigned char lock_flags,
|
||||||
|
char *resource);
|
||||||
|
extern int do_check_lvm1(char *vgname);
|
||||||
|
extern int do_refresh_cache(void);
|
||||||
|
extern int init_lvm(int using_gulm);
|
||||||
|
extern void init_lvhash(void);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif
|
||||||
320
daemons/clvmd/refresh_clvmd.c
Normal file
320
daemons/clvmd/refresh_clvmd.c
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004-2006 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tell all clvmds in a cluster to refresh their toolcontext
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libdevmapper.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "clvm.h"
|
||||||
|
#include "refresh_clvmd.h"
|
||||||
|
|
||||||
|
typedef struct lvm_response {
|
||||||
|
char node[255];
|
||||||
|
char *response;
|
||||||
|
int status;
|
||||||
|
int len;
|
||||||
|
} lvm_response_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This gets stuck at the start of memory we allocate so we
|
||||||
|
* can sanity-check it at deallocation time
|
||||||
|
*/
|
||||||
|
#define LVM_SIGNATURE 0x434C564D
|
||||||
|
|
||||||
|
static int _clvmd_sock = -1;
|
||||||
|
|
||||||
|
/* Open connection to the Cluster Manager daemon */
|
||||||
|
static int _open_local_sock(void)
|
||||||
|
{
|
||||||
|
int local_socket;
|
||||||
|
struct sockaddr_un sockaddr;
|
||||||
|
|
||||||
|
/* Open local socket */
|
||||||
|
if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
||||||
|
fprintf(stderr, "Local socket creation failed: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||||
|
memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
|
||||||
|
|
||||||
|
sockaddr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
|
if (connect(local_socket,(struct sockaddr *) &sockaddr,
|
||||||
|
sizeof(sockaddr))) {
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
|
fprintf(stderr, "connect() failed on local socket: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
if (close(local_socket))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return local_socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send a request and return the status */
|
||||||
|
static int _send_request(char *inbuf, int inlen, char **retbuf)
|
||||||
|
{
|
||||||
|
char outbuf[PIPE_BUF];
|
||||||
|
struct clvm_header *outheader = (struct clvm_header *) outbuf;
|
||||||
|
int len;
|
||||||
|
int off;
|
||||||
|
int buflen;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Send it to CLVMD */
|
||||||
|
rewrite:
|
||||||
|
if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
|
||||||
|
if (err == -1 && errno == EINTR)
|
||||||
|
goto rewrite;
|
||||||
|
fprintf(stderr, "Error writing data to clvmd: %s", strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the response */
|
||||||
|
reread:
|
||||||
|
if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto reread;
|
||||||
|
fprintf(stderr, "Error reading data from clvmd: %s", strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
fprintf(stderr, "EOF reading CLVMD");
|
||||||
|
errno = ENOTCONN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
buflen = len + outheader->arglen;
|
||||||
|
*retbuf = dm_malloc(buflen);
|
||||||
|
if (!*retbuf) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the header */
|
||||||
|
memcpy(*retbuf, outbuf, len);
|
||||||
|
outheader = (struct clvm_header *) *retbuf;
|
||||||
|
|
||||||
|
/* Read the returned values */
|
||||||
|
off = 1; /* we've already read the first byte */
|
||||||
|
while (off <= outheader->arglen && len > 0) {
|
||||||
|
len = read(_clvmd_sock, outheader->args + off,
|
||||||
|
buflen - off - offsetof(struct clvm_header, args));
|
||||||
|
if (len > 0)
|
||||||
|
off += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Was it an error ? */
|
||||||
|
if (outheader->status != 0) {
|
||||||
|
errno = outheader->status;
|
||||||
|
|
||||||
|
/* Only return an error here if there are no node-specific
|
||||||
|
errors present in the message that might have more detail */
|
||||||
|
if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
|
||||||
|
fprintf(stderr, "cluster request failed: %s\n", strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build the structure header and parse-out wildcard node names */
|
||||||
|
static void _build_header(struct clvm_header *head, int cmd, const char *node,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
head->cmd = cmd;
|
||||||
|
head->status = 0;
|
||||||
|
head->flags = 0;
|
||||||
|
head->clientid = 0;
|
||||||
|
head->arglen = len;
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
/*
|
||||||
|
* Allow a couple of special node names:
|
||||||
|
* "*" for all nodes,
|
||||||
|
* "." for the local node only
|
||||||
|
*/
|
||||||
|
if (strcmp(node, "*") == 0) {
|
||||||
|
head->node[0] = '\0';
|
||||||
|
} else if (strcmp(node, ".") == 0) {
|
||||||
|
head->node[0] = '\0';
|
||||||
|
head->flags = CLVMD_FLAG_LOCAL;
|
||||||
|
} else
|
||||||
|
strcpy(head->node, node);
|
||||||
|
} else
|
||||||
|
head->node[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a message to a(or all) node(s) in the cluster and wait for replies
|
||||||
|
*/
|
||||||
|
static int _cluster_request(char cmd, const char *node, void *data, int len,
|
||||||
|
lvm_response_t ** response, int *num)
|
||||||
|
{
|
||||||
|
char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1];
|
||||||
|
char *inptr;
|
||||||
|
char *retbuf = NULL;
|
||||||
|
int status;
|
||||||
|
int i;
|
||||||
|
int num_responses = 0;
|
||||||
|
struct clvm_header *head = (struct clvm_header *) outbuf;
|
||||||
|
lvm_response_t *rarray;
|
||||||
|
|
||||||
|
*num = 0;
|
||||||
|
|
||||||
|
if (_clvmd_sock == -1)
|
||||||
|
_clvmd_sock = _open_local_sock();
|
||||||
|
|
||||||
|
if (_clvmd_sock == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_build_header(head, cmd, node, len);
|
||||||
|
memcpy(head->node + strlen(head->node) + 1, data, len);
|
||||||
|
|
||||||
|
status = _send_request(outbuf, sizeof(struct clvm_header) +
|
||||||
|
strlen(head->node) + len, &retbuf);
|
||||||
|
if (!status)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Count the number of responses we got */
|
||||||
|
head = (struct clvm_header *) retbuf;
|
||||||
|
inptr = head->args;
|
||||||
|
while (inptr[0]) {
|
||||||
|
num_responses++;
|
||||||
|
inptr += strlen(inptr) + 1;
|
||||||
|
inptr += sizeof(int);
|
||||||
|
inptr += strlen(inptr) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate response array.
|
||||||
|
* With an extra pair of INTs on the front to sanity
|
||||||
|
* check the pointer when we are given it back to free
|
||||||
|
*/
|
||||||
|
*response = dm_malloc(sizeof(lvm_response_t) * num_responses +
|
||||||
|
sizeof(int) * 2);
|
||||||
|
if (!*response) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
status = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rarray = *response;
|
||||||
|
|
||||||
|
/* Unpack the response into an lvm_response_t array */
|
||||||
|
inptr = head->args;
|
||||||
|
i = 0;
|
||||||
|
while (inptr[0]) {
|
||||||
|
strcpy(rarray[i].node, inptr);
|
||||||
|
inptr += strlen(inptr) + 1;
|
||||||
|
|
||||||
|
memcpy(&rarray[i].status, inptr, sizeof(int));
|
||||||
|
inptr += sizeof(int);
|
||||||
|
|
||||||
|
rarray[i].response = dm_malloc(strlen(inptr) + 1);
|
||||||
|
if (rarray[i].response == NULL) {
|
||||||
|
/* Free up everything else and return error */
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
dm_free(rarray[i].response);
|
||||||
|
free(*response);
|
||||||
|
errno = ENOMEM;
|
||||||
|
status = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(rarray[i].response, inptr);
|
||||||
|
rarray[i].len = strlen(inptr);
|
||||||
|
inptr += strlen(inptr) + 1;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
*num = num_responses;
|
||||||
|
*response = rarray;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (retbuf)
|
||||||
|
dm_free(retbuf);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free reply array */
|
||||||
|
static int _cluster_free_request(lvm_response_t * response, int num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
dm_free(response[i].response);
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_free(response);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int refresh_clvmd()
|
||||||
|
{
|
||||||
|
int num_responses;
|
||||||
|
char args[1]; // No args really.
|
||||||
|
lvm_response_t *response;
|
||||||
|
int saved_errno;
|
||||||
|
int status;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
status = _cluster_request(CLVMD_CMD_REFRESH, "*", args, 0, &response, &num_responses);
|
||||||
|
|
||||||
|
/* If any nodes were down then display them and return an error */
|
||||||
|
for (i = 0; i < num_responses; i++) {
|
||||||
|
if (response[i].status == EHOSTDOWN) {
|
||||||
|
fprintf(stderr, "clvmd not running on node %s",
|
||||||
|
response[i].node);
|
||||||
|
status = 0;
|
||||||
|
errno = response[i].status;
|
||||||
|
} else if (response[i].status) {
|
||||||
|
fprintf(stderr, "Error resetting node %s: %s",
|
||||||
|
response[i].node,
|
||||||
|
response[i].response[0] ?
|
||||||
|
response[i].response :
|
||||||
|
strerror(response[i].status));
|
||||||
|
status = 0;
|
||||||
|
errno = response[i].status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saved_errno = errno;
|
||||||
|
_cluster_free_request(response, num_responses);
|
||||||
|
errno = saved_errno;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
2
daemons/clvmd/refresh_clvmd.h
Normal file
2
daemons/clvmd/refresh_clvmd.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
int refresh_clvmd(void);
|
||||||
|
|
||||||
371
daemons/clvmd/system-lv.c
Normal file
371
daemons/clvmd/system-lv.c
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Routines dealing with the System LV */
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <mntent.h>
|
||||||
|
|
||||||
|
#include "libdlm.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "locking.h"
|
||||||
|
#include "system-lv.h"
|
||||||
|
#include "clvm.h"
|
||||||
|
#include "clvmd-comms.h"
|
||||||
|
#include "clvmd.h"
|
||||||
|
#ifdef HAVE_CCS
|
||||||
|
#include "ccs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SYSTEM_LV_FILESYSTEM "ext2"
|
||||||
|
#define SYSTEM_LV_MOUNTPOINT "/tmp/.clvmd-XXXXXX"
|
||||||
|
|
||||||
|
extern char *config_filename(void);
|
||||||
|
|
||||||
|
static char system_lv_name[PATH_MAX] = { '\0' };
|
||||||
|
static char mount_point[PATH_MAX] = { '\0' };
|
||||||
|
static int mounted = 0;
|
||||||
|
static int mounted_rw = 0;
|
||||||
|
static int lockid;
|
||||||
|
static const char *lock_name = "CLVM_SYSTEM_LV";
|
||||||
|
|
||||||
|
/* Look in /proc/mounts or (as a last resort) /etc/mtab to
|
||||||
|
see if the system-lv is mounted. If it is mounted and we
|
||||||
|
think it's not then abort because we don't have the right
|
||||||
|
lock status and we don't know what other processes are doing with it.
|
||||||
|
|
||||||
|
Returns 1 for mounted, 0 for not mounted so it matches the condition
|
||||||
|
of the "mounted" static variable above.
|
||||||
|
*/
|
||||||
|
static int is_really_mounted(void)
|
||||||
|
{
|
||||||
|
FILE *mountfile;
|
||||||
|
struct mntent *ment;
|
||||||
|
|
||||||
|
mountfile = setmntent("/proc/mounts", "r");
|
||||||
|
if (!mountfile) {
|
||||||
|
mountfile = setmntent("/etc/mtab", "r");
|
||||||
|
if (!mountfile) {
|
||||||
|
log_error("Unable to open /proc/mounts or /etc/mtab");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for system LV name in the file */
|
||||||
|
do {
|
||||||
|
ment = getmntent(mountfile);
|
||||||
|
if (ment) {
|
||||||
|
if (strcmp(ment->mnt_fsname, system_lv_name) == 0) {
|
||||||
|
endmntent(mountfile);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (ment);
|
||||||
|
|
||||||
|
endmntent(mountfile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the system LV name from the config file */
|
||||||
|
static int find_system_lv(void)
|
||||||
|
{
|
||||||
|
if (system_lv_name[0] == '\0') {
|
||||||
|
#ifdef HAVE_CCS
|
||||||
|
int error;
|
||||||
|
ccs_node_t *ctree;
|
||||||
|
|
||||||
|
/* Read the cluster config file */
|
||||||
|
/* Open the config file */
|
||||||
|
error = open_ccs_file(&ctree, "clvm.ccs");
|
||||||
|
if (error) {
|
||||||
|
perror("reading config file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(system_lv_name, find_ccs_str(ctree,
|
||||||
|
"cluster/systemlv", '/',
|
||||||
|
"/dev/vg/system_lv"));
|
||||||
|
|
||||||
|
/* Finished with config file */
|
||||||
|
close_ccs_file(ctree);
|
||||||
|
#else
|
||||||
|
if (getenv("CLVMD_SYSTEM_LV"))
|
||||||
|
strcpy(system_lv_name, getenv("CLVMD_SYSTEM_LV"));
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See if it has been mounted outside our control */
|
||||||
|
if (is_really_mounted() != mounted) {
|
||||||
|
log_error
|
||||||
|
("The system LV state has been mounted/umounted outside the control of clvmd\n"
|
||||||
|
"it cannot not be used for cluster communications until this is fixed.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No prizes */
|
||||||
|
int system_lv_umount(void)
|
||||||
|
{
|
||||||
|
if (!mounted)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (umount(mount_point) < 0) {
|
||||||
|
log_error("umount of system LV (%s) failed: %m\n",
|
||||||
|
system_lv_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_unlock(lock_name, lockid);
|
||||||
|
mounted = 0;
|
||||||
|
|
||||||
|
/* Remove the mount point */
|
||||||
|
rmdir(mount_point);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int system_lv_mount(int readwrite)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
int saved_errno;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (find_system_lv()) {
|
||||||
|
errno = EBUSY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is it already mounted suitably? */
|
||||||
|
if (mounted) {
|
||||||
|
if (!readwrite || (readwrite && mounted_rw)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
/* Mounted RO and we need RW */
|
||||||
|
if (system_lv_umount() < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Randomize the mount point */
|
||||||
|
strcpy(mount_point, SYSTEM_LV_MOUNTPOINT);
|
||||||
|
fd = mkstemp(mount_point);
|
||||||
|
if (fd < 0) {
|
||||||
|
log_error("mkstemp for system LV mount point failed: %m\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Race condition here but there's no mkstemp for directories */
|
||||||
|
close(fd);
|
||||||
|
unlink(mount_point);
|
||||||
|
mkdir(mount_point, 0600);
|
||||||
|
|
||||||
|
/* Make sure we have a system-lv lock */
|
||||||
|
status =
|
||||||
|
sync_lock(lock_name, (readwrite) ? LKM_EXMODE : LKM_CRMODE, 0,
|
||||||
|
&lockid);
|
||||||
|
if (status < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Mount it */
|
||||||
|
if (mount(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
|
||||||
|
MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_SYNCHRONOUS
|
||||||
|
| (readwrite ? 0 : MS_RDONLY), NULL) < 0) {
|
||||||
|
/* mount(2) returns EINVAL if the volume has no FS on it. So, if we want to
|
||||||
|
write to it we try to make a filesystem in it and retry the mount */
|
||||||
|
if (errno == EINVAL && readwrite) {
|
||||||
|
char cmd[256];
|
||||||
|
|
||||||
|
log_error("Attempting mkfs on system LV device %s\n",
|
||||||
|
system_lv_name);
|
||||||
|
snprintf(cmd, sizeof(cmd), "/sbin/mkfs -t %s %s",
|
||||||
|
SYSTEM_LV_FILESYSTEM, system_lv_name);
|
||||||
|
system(cmd);
|
||||||
|
|
||||||
|
if (mount
|
||||||
|
(system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM,
|
||||||
|
MS_MGC_VAL | MS_NOSUID | MS_NODEV | MS_NOEXEC |
|
||||||
|
MS_SYNCHRONOUS | (readwrite ? 0 : MS_RDONLY),
|
||||||
|
NULL) == 0)
|
||||||
|
goto mounted;
|
||||||
|
}
|
||||||
|
|
||||||
|
saved_errno = errno;
|
||||||
|
log_error("mount of system LV (%s, %s, %s) failed: %m\n",
|
||||||
|
system_lv_name, mount_point, SYSTEM_LV_FILESYSTEM);
|
||||||
|
sync_unlock(lock_name, lockid);
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted:
|
||||||
|
/* Set the internal flags */
|
||||||
|
mounted = 1;
|
||||||
|
mounted_rw = readwrite;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Erase *all* files in the root directory of the system LV.
|
||||||
|
This *MUST* be called with an appropriate lock held!
|
||||||
|
The LV is left mounted RW because it is assumed that the
|
||||||
|
caller wants to write something here after clearing some space */
|
||||||
|
int system_lv_eraseall(void)
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *ent;
|
||||||
|
char fname[PATH_MAX];
|
||||||
|
|
||||||
|
/* Must be mounted R/W */
|
||||||
|
system_lv_mount(1);
|
||||||
|
|
||||||
|
dir = opendir(mount_point);
|
||||||
|
if (!dir)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while ((ent = readdir(dir))) {
|
||||||
|
struct stat st;
|
||||||
|
snprintf(fname, sizeof(fname), "%s/%s", mount_point,
|
||||||
|
ent->d_name);
|
||||||
|
|
||||||
|
if (stat(fname, &st)) {
|
||||||
|
if (S_ISREG(st.st_mode))
|
||||||
|
unlink(fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a "high-level" routine - it mounts the system LV, writes
|
||||||
|
the data into a file named after this node and then umounts the LV
|
||||||
|
again */
|
||||||
|
int system_lv_write_data(char *data, ssize_t len)
|
||||||
|
{
|
||||||
|
struct utsname nodeinfo;
|
||||||
|
char fname[PATH_MAX];
|
||||||
|
int outfile;
|
||||||
|
ssize_t thiswrite;
|
||||||
|
ssize_t written;
|
||||||
|
|
||||||
|
if (system_lv_mount(1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Build the file name we are goingto use. */
|
||||||
|
uname(&nodeinfo);
|
||||||
|
snprintf(fname, sizeof(fname), "%s/%s", mount_point, nodeinfo.nodename);
|
||||||
|
|
||||||
|
/* Open the file for output */
|
||||||
|
outfile = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0600);
|
||||||
|
if (outfile < 0) {
|
||||||
|
int saved_errno = errno;
|
||||||
|
system_lv_umount();
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
written = 0;
|
||||||
|
do {
|
||||||
|
thiswrite = write(outfile, data + written, len - written);
|
||||||
|
if (thiswrite > 0)
|
||||||
|
written += thiswrite;
|
||||||
|
|
||||||
|
} while (written < len && thiswrite > 0);
|
||||||
|
|
||||||
|
close(outfile);
|
||||||
|
|
||||||
|
system_lv_umount();
|
||||||
|
return (thiswrite < 0) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a "high-level" routine - it mounts the system LV, reads
|
||||||
|
the data from a named file and then umounts the LV
|
||||||
|
again */
|
||||||
|
int system_lv_read_data(char *fname_base, char *data, ssize_t *len)
|
||||||
|
{
|
||||||
|
char fname[PATH_MAX];
|
||||||
|
int outfile;
|
||||||
|
struct stat st;
|
||||||
|
ssize_t filesize;
|
||||||
|
ssize_t thisread;
|
||||||
|
ssize_t readbytes;
|
||||||
|
|
||||||
|
if (system_lv_mount(0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Build the file name we are going to use. */
|
||||||
|
snprintf(fname, sizeof(fname), "%s/%s", mount_point, fname_base);
|
||||||
|
|
||||||
|
/* Get the file size and stuff. Actually we only need the file size but
|
||||||
|
this will also check that the file exists */
|
||||||
|
if (stat(fname, &st) < 0) {
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
|
log_error("stat of file %s on system LV failed: %m\n", fname);
|
||||||
|
system_lv_umount();
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
filesize = st.st_size;
|
||||||
|
|
||||||
|
outfile = open(fname, O_RDONLY);
|
||||||
|
if (outfile < 0) {
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
|
log_error("open of file %s on system LV failed: %m\n", fname);
|
||||||
|
system_lv_umount();
|
||||||
|
errno = saved_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
readbytes = 0;
|
||||||
|
do {
|
||||||
|
thisread =
|
||||||
|
read(outfile, data + readbytes, filesize - readbytes);
|
||||||
|
if (thisread > 0)
|
||||||
|
readbytes += thisread;
|
||||||
|
|
||||||
|
} while (readbytes < filesize && thisread > 0);
|
||||||
|
|
||||||
|
close(outfile);
|
||||||
|
|
||||||
|
system_lv_umount();
|
||||||
|
|
||||||
|
*len = readbytes;
|
||||||
|
return (thisread < 0) ? -1 : 0;
|
||||||
|
}
|
||||||
30
daemons/clvmd/system-lv.h
Normal file
30
daemons/clvmd/system-lv.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CLVM_SYSTEM_LV_H
|
||||||
|
#define _CLVM_SYSTEM_LV_H
|
||||||
|
|
||||||
|
/* Prototypes for System-LV functions */
|
||||||
|
|
||||||
|
/* "low-level" functions */
|
||||||
|
extern int system_lv_umount(void);
|
||||||
|
extern int system_lv_mount(int readwrite);
|
||||||
|
extern int system_lv_eraseall(void);
|
||||||
|
|
||||||
|
/* "high-level" functions */
|
||||||
|
extern int system_lv_write_data(char *data, ssize_t len);
|
||||||
|
extern int system_lv_read_data(char *fname_base, char *data, ssize_t *len);
|
||||||
|
|
||||||
|
#endif
|
||||||
505
daemons/clvmd/tcp-comms.c
Normal file
505
daemons/clvmd/tcp-comms.c
Normal file
@@ -0,0 +1,505 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*******************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) Sistina Software, Inc. 2002-2003 All rights reserved.
|
||||||
|
** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||||
|
**
|
||||||
|
*******************************************************************************
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#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/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "libdevmapper.h"
|
||||||
|
#include "clvm.h"
|
||||||
|
#include "clvmd-comms.h"
|
||||||
|
#include "clvmd.h"
|
||||||
|
#include "clvmd-gulm.h"
|
||||||
|
|
||||||
|
#define DEFAULT_TCP_PORT 21064
|
||||||
|
|
||||||
|
static int listen_fd = -1;
|
||||||
|
static int tcp_port;
|
||||||
|
struct dm_hash_table *sock_hash;
|
||||||
|
|
||||||
|
static int get_our_ip_address(char *addr, int *family);
|
||||||
|
static int read_from_tcpsock(struct local_client *fd, char *buf, int len, char *csid,
|
||||||
|
struct local_client **new_client);
|
||||||
|
|
||||||
|
/* Called by init_cluster() to open up the listening socket */
|
||||||
|
int init_comms(unsigned short port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
|
||||||
|
sock_hash = dm_hash_create(100);
|
||||||
|
tcp_port = port ? : DEFAULT_TCP_PORT;
|
||||||
|
|
||||||
|
listen_fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if (listen_fd < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int one = 1;
|
||||||
|
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
|
||||||
|
setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr)); // Bind to INADDR_ANY
|
||||||
|
addr.sin6_family = AF_INET6;
|
||||||
|
addr.sin6_port = htons(tcp_port);
|
||||||
|
|
||||||
|
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||||
|
{
|
||||||
|
DEBUGLOG("Can't bind to port: %s\n", strerror(errno));
|
||||||
|
syslog(LOG_ERR, "Can't bind to port %d, is clvmd already running ?", tcp_port);
|
||||||
|
close(listen_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(listen_fd, 5);
|
||||||
|
|
||||||
|
/* Set Close-on-exec */
|
||||||
|
fcntl(listen_fd, F_SETFD, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_remove_client(char *csid)
|
||||||
|
{
|
||||||
|
struct local_client *client;
|
||||||
|
DEBUGLOG("tcp_remove_client\n");
|
||||||
|
|
||||||
|
/* Don't actually close the socket here - that's the
|
||||||
|
job of clvmd.c whch will do the job when it notices the
|
||||||
|
other end has gone. We just need to remove the client(s) from
|
||||||
|
the hash table so we don't try to use it for sending any more */
|
||||||
|
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||||
|
if (client)
|
||||||
|
{
|
||||||
|
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||||
|
client->removeme = 1;
|
||||||
|
close(client->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for a mangled one too */
|
||||||
|
csid[0] ^= 0x80;
|
||||||
|
|
||||||
|
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||||
|
if (client)
|
||||||
|
{
|
||||||
|
dm_hash_remove_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||||
|
client->removeme = 1;
|
||||||
|
close(client->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put it back as we found it */
|
||||||
|
csid[0] ^= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
int alloc_client(int fd, char *csid, struct local_client **new_client)
|
||||||
|
{
|
||||||
|
struct local_client *client;
|
||||||
|
|
||||||
|
DEBUGLOG("alloc_client %d csid = %s\n", fd, print_csid(csid));
|
||||||
|
|
||||||
|
/* Create a local_client and return it */
|
||||||
|
client = malloc(sizeof(struct local_client));
|
||||||
|
if (!client)
|
||||||
|
{
|
||||||
|
DEBUGLOG("malloc failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(client, 0, sizeof(struct local_client));
|
||||||
|
client->fd = fd;
|
||||||
|
client->type = CLUSTER_DATA_SOCK;
|
||||||
|
client->callback = read_from_tcpsock;
|
||||||
|
if (new_client)
|
||||||
|
*new_client = client;
|
||||||
|
|
||||||
|
/* Add to our list of node sockets */
|
||||||
|
if (dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN))
|
||||||
|
{
|
||||||
|
DEBUGLOG("alloc_client mangling CSID for second connection\n");
|
||||||
|
/* This is a duplicate connection but we can't close it because
|
||||||
|
the other end may already have started sending.
|
||||||
|
So, we mangle the IP address and keep it, all sending will
|
||||||
|
go out of the main FD
|
||||||
|
*/
|
||||||
|
csid[0] ^= 0x80;
|
||||||
|
client->bits.net.flags = 1; /* indicate mangled CSID */
|
||||||
|
|
||||||
|
/* If it still exists then kill the connection as we should only
|
||||||
|
ever have one incoming connection from each node */
|
||||||
|
if (dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN))
|
||||||
|
{
|
||||||
|
DEBUGLOG("Multiple incoming connections from node\n");
|
||||||
|
syslog(LOG_ERR, " Bogus incoming connection from %d.%d.%d.%d\n", csid[0],csid[1],csid[2],csid[3]);
|
||||||
|
|
||||||
|
free(client);
|
||||||
|
errno = ECONNREFUSED;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dm_hash_insert_binary(sock_hash, csid, GULM_MAX_CSID_LEN, client);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_main_gulm_cluster_fd()
|
||||||
|
{
|
||||||
|
return listen_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read on main comms (listen) socket, accept it */
|
||||||
|
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid,
|
||||||
|
struct local_client **new_client)
|
||||||
|
{
|
||||||
|
int newfd;
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
int status;
|
||||||
|
char name[GULM_MAX_CLUSTER_MEMBER_NAME_LEN];
|
||||||
|
|
||||||
|
DEBUGLOG("cluster_fd_callback\n");
|
||||||
|
*new_client = NULL;
|
||||||
|
newfd = accept(listen_fd, (struct sockaddr *)&addr, &addrlen);
|
||||||
|
|
||||||
|
DEBUGLOG("cluster_fd_callback, newfd=%d (errno=%d)\n", newfd, errno);
|
||||||
|
if (!newfd)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "error in accept: %m");
|
||||||
|
errno = EAGAIN;
|
||||||
|
return -1; /* Don't return an error or clvmd will close the listening FD */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the client is a member of the cluster
|
||||||
|
and reject if not.
|
||||||
|
*/
|
||||||
|
if (gulm_name_from_csid((char *)&addr.sin6_addr, name) < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "Got connect from non-cluster node %s\n",
|
||||||
|
print_csid((char *)&addr.sin6_addr));
|
||||||
|
DEBUGLOG("Got connect from non-cluster node %s\n",
|
||||||
|
print_csid((char *)&addr.sin6_addr));
|
||||||
|
close(newfd);
|
||||||
|
|
||||||
|
errno = EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = alloc_client(newfd, (char *)&addr.sin6_addr, new_client);
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
DEBUGLOG("cluster_fd_callback, alloc_client failed, status = %d\n", status);
|
||||||
|
close(newfd);
|
||||||
|
/* See above... */
|
||||||
|
errno = EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DEBUGLOG("cluster_fd_callback, returning %d, %p\n", newfd, *new_client);
|
||||||
|
return newfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get at least 'len' bytes from the socket */
|
||||||
|
static int really_read(int fd, char *buf, int len)
|
||||||
|
{
|
||||||
|
int got, offset;
|
||||||
|
|
||||||
|
got = offset = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
got = read(fd, buf+offset, len-offset);
|
||||||
|
DEBUGLOG("really_read. got %d bytes\n", got);
|
||||||
|
offset += got;
|
||||||
|
} while (got > 0 && offset < len);
|
||||||
|
|
||||||
|
if (got < 0)
|
||||||
|
return got;
|
||||||
|
else
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int read_from_tcpsock(struct local_client *client, char *buf, int len, char *csid,
|
||||||
|
struct local_client **new_client)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
socklen_t slen = sizeof(addr);
|
||||||
|
struct clvm_header *header = (struct clvm_header *)buf;
|
||||||
|
int status;
|
||||||
|
uint32_t arglen;
|
||||||
|
|
||||||
|
DEBUGLOG("read_from_tcpsock fd %d\n", client->fd);
|
||||||
|
*new_client = NULL;
|
||||||
|
|
||||||
|
/* Get "csid" */
|
||||||
|
getpeername(client->fd, (struct sockaddr *)&addr, &slen);
|
||||||
|
memcpy(csid, &addr.sin6_addr, GULM_MAX_CSID_LEN);
|
||||||
|
|
||||||
|
/* Read just the header first, then get the rest if there is any.
|
||||||
|
* Stream sockets, sigh.
|
||||||
|
*/
|
||||||
|
status = really_read(client->fd, buf, sizeof(struct clvm_header));
|
||||||
|
if (status > 0)
|
||||||
|
{
|
||||||
|
int status2;
|
||||||
|
|
||||||
|
arglen = ntohl(header->arglen);
|
||||||
|
|
||||||
|
/* Get the rest */
|
||||||
|
if (arglen && arglen < GULM_MAX_CLUSTER_MESSAGE)
|
||||||
|
{
|
||||||
|
status2 = really_read(client->fd, buf+status, arglen);
|
||||||
|
if (status2 > 0)
|
||||||
|
status += status2;
|
||||||
|
else
|
||||||
|
status = status2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGLOG("read_from_tcpsock, status = %d(errno = %d)\n", status, errno);
|
||||||
|
|
||||||
|
/* Remove it from the hash table if there's an error, clvmd will
|
||||||
|
remove the socket from its lists and free the client struct */
|
||||||
|
if (status == 0 ||
|
||||||
|
(status < 0 && errno != EAGAIN && errno != EINTR))
|
||||||
|
{
|
||||||
|
char remcsid[GULM_MAX_CSID_LEN];
|
||||||
|
|
||||||
|
memcpy(remcsid, csid, GULM_MAX_CSID_LEN);
|
||||||
|
close(client->fd);
|
||||||
|
|
||||||
|
/* If the csid was mangled, then make sure we remove the right entry */
|
||||||
|
if (client->bits.net.flags)
|
||||||
|
remcsid[0] ^= 0x80;
|
||||||
|
dm_hash_remove_binary(sock_hash, remcsid, GULM_MAX_CSID_LEN);
|
||||||
|
|
||||||
|
/* Tell cluster manager layer */
|
||||||
|
add_down_node(remcsid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gulm_add_up_node(csid);
|
||||||
|
/* Send it back to clvmd */
|
||||||
|
process_message(client, buf, status, csid);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gulm_connect_csid(char *csid, struct local_client **newclient)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
int status;
|
||||||
|
int one = 1;
|
||||||
|
|
||||||
|
DEBUGLOG("Connecting socket\n");
|
||||||
|
fd = socket(PF_INET6, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "Unable to create new socket: %m");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.sin6_family = AF_INET6;
|
||||||
|
memcpy(&addr.sin6_addr, csid, GULM_MAX_CSID_LEN);
|
||||||
|
addr.sin6_port = htons(tcp_port);
|
||||||
|
|
||||||
|
DEBUGLOG("Connecting socket %d\n", fd);
|
||||||
|
if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0)
|
||||||
|
{
|
||||||
|
/* "Connection refused" is "normal" because clvmd may not yet be running
|
||||||
|
* on that node.
|
||||||
|
*/
|
||||||
|
if (errno != ECONNREFUSED)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "Unable to connect to remote node: %m");
|
||||||
|
}
|
||||||
|
DEBUGLOG("Unable to connect to remote node: %s\n", strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Close-on-exec */
|
||||||
|
fcntl(fd, F_SETFD, 1);
|
||||||
|
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(int));
|
||||||
|
|
||||||
|
status = alloc_client(fd, csid, newclient);
|
||||||
|
if (status)
|
||||||
|
close(fd);
|
||||||
|
else
|
||||||
|
add_client(*newclient);
|
||||||
|
|
||||||
|
/* If we can connect to it, it must be running a clvmd */
|
||||||
|
gulm_add_up_node(csid);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send a message to a known CSID */
|
||||||
|
static int tcp_send_message(void *buf, int msglen, unsigned char *csid, const char *errtext)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
struct local_client *client;
|
||||||
|
char ourcsid[GULM_MAX_CSID_LEN];
|
||||||
|
|
||||||
|
assert(csid);
|
||||||
|
|
||||||
|
DEBUGLOG("tcp_send_message, csid = %s, msglen = %d\n", print_csid(csid), msglen);
|
||||||
|
|
||||||
|
/* Don't connect to ourself */
|
||||||
|
get_our_gulm_csid(ourcsid);
|
||||||
|
if (memcmp(csid, ourcsid, GULM_MAX_CSID_LEN) == 0)
|
||||||
|
return msglen;
|
||||||
|
|
||||||
|
client = dm_hash_lookup_binary(sock_hash, csid, GULM_MAX_CSID_LEN);
|
||||||
|
if (!client)
|
||||||
|
{
|
||||||
|
status = gulm_connect_csid(csid, &client);
|
||||||
|
if (status)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DEBUGLOG("tcp_send_message, fd = %d\n", client->fd);
|
||||||
|
|
||||||
|
return write(client->fd, buf, msglen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||||
|
{
|
||||||
|
int status=0;
|
||||||
|
|
||||||
|
DEBUGLOG("cluster send message, csid = %p, msglen = %d\n", csid, msglen);
|
||||||
|
|
||||||
|
/* If csid is NULL then send to all known (not just connected) nodes */
|
||||||
|
if (!csid)
|
||||||
|
{
|
||||||
|
void *context = NULL;
|
||||||
|
char loop_csid[GULM_MAX_CSID_LEN];
|
||||||
|
|
||||||
|
/* Loop round all gulm-known nodes */
|
||||||
|
while (get_next_node_csid(&context, loop_csid))
|
||||||
|
{
|
||||||
|
status = tcp_send_message(buf, msglen, loop_csid, errtext);
|
||||||
|
if (status == 0 ||
|
||||||
|
(status < 0 && (errno == EAGAIN || errno == EINTR)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
status = tcp_send_message(buf, msglen, csid, errtext);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To get our own IP address we get the locally bound address of the
|
||||||
|
socket that's talking to GULM in the assumption(eek) that it will
|
||||||
|
be on the "right" network in a multi-homed system */
|
||||||
|
static int get_our_ip_address(char *addr, int *family)
|
||||||
|
{
|
||||||
|
struct utsname info;
|
||||||
|
|
||||||
|
uname(&info);
|
||||||
|
get_ip_address(info.nodename, addr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Public version of above for those that don't care what protocol
|
||||||
|
we're using */
|
||||||
|
void get_our_gulm_csid(char *csid)
|
||||||
|
{
|
||||||
|
static char our_csid[GULM_MAX_CSID_LEN];
|
||||||
|
static int got_csid = 0;
|
||||||
|
|
||||||
|
if (!got_csid)
|
||||||
|
{
|
||||||
|
int family;
|
||||||
|
|
||||||
|
memset(our_csid, 0, sizeof(our_csid));
|
||||||
|
if (get_our_ip_address(our_csid, &family))
|
||||||
|
{
|
||||||
|
got_csid = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(csid, our_csid, GULM_MAX_CSID_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void map_v4_to_v6(struct in_addr *ip4, struct in6_addr *ip6)
|
||||||
|
{
|
||||||
|
ip6->s6_addr32[0] = 0;
|
||||||
|
ip6->s6_addr32[1] = 0;
|
||||||
|
ip6->s6_addr32[2] = htonl(0xffff);
|
||||||
|
ip6->s6_addr32[3] = ip4->s_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get someone else's IP address from DNS */
|
||||||
|
int get_ip_address(char *node, char *addr)
|
||||||
|
{
|
||||||
|
struct hostent *he;
|
||||||
|
|
||||||
|
memset(addr, 0, GULM_MAX_CSID_LEN);
|
||||||
|
|
||||||
|
// TODO: what do we do about multi-homed hosts ???
|
||||||
|
// CCSs ip_interfaces solved this but some bugger removed it.
|
||||||
|
|
||||||
|
/* Try IPv6 first. The man page for gethostbyname implies that
|
||||||
|
it will lookup ip6 & ip4 names, but it seems not to */
|
||||||
|
he = gethostbyname2(node, AF_INET6);
|
||||||
|
if (he)
|
||||||
|
{
|
||||||
|
memcpy(addr, he->h_addr_list[0],
|
||||||
|
he->h_length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
he = gethostbyname2(node, AF_INET);
|
||||||
|
if (!he)
|
||||||
|
return -1;
|
||||||
|
map_v4_to_v6((struct in_addr *)he->h_addr_list[0], (struct in6_addr *)addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *print_csid(char *csid)
|
||||||
|
{
|
||||||
|
static char buf[128];
|
||||||
|
int *icsid = (int *)csid;
|
||||||
|
|
||||||
|
sprintf(buf, "[%x.%x.%x.%x]",
|
||||||
|
icsid[0],icsid[1],icsid[2],icsid[3]);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
13
daemons/clvmd/tcp-comms.h
Normal file
13
daemons/clvmd/tcp-comms.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#define GULM_MAX_CLUSTER_MESSAGE 1600
|
||||||
|
#define GULM_MAX_CSID_LEN sizeof(struct in6_addr)
|
||||||
|
#define GULM_MAX_CLUSTER_MEMBER_NAME_LEN 128
|
||||||
|
|
||||||
|
extern int init_comms(unsigned short);
|
||||||
|
extern char *print_csid(char *);
|
||||||
|
int get_main_gulm_cluster_fd(void);
|
||||||
|
int cluster_fd_gulm_callback(struct local_client *fd, char *buf, int len, char *csid, struct local_client **new_client);
|
||||||
|
int gulm_cluster_send_message(void *buf, int msglen, char *csid, const char *errtext);
|
||||||
|
void get_our_gulm_csid(char *csid);
|
||||||
|
int gulm_connect_csid(char *csid, struct local_client **newclient);
|
||||||
19
daemons/dmeventd/.exported_symbols
Normal file
19
daemons/dmeventd/.exported_symbols
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
dm_event_handler_create
|
||||||
|
dm_event_handler_destroy
|
||||||
|
dm_event_handler_set_dso
|
||||||
|
dm_event_handler_set_dev_name
|
||||||
|
dm_event_handler_set_uuid
|
||||||
|
dm_event_handler_set_major
|
||||||
|
dm_event_handler_set_minor
|
||||||
|
dm_event_handler_set_event_mask
|
||||||
|
dm_event_handler_get_dso
|
||||||
|
dm_event_handler_get_devname
|
||||||
|
dm_event_handler_get_uuid
|
||||||
|
dm_event_handler_get_major
|
||||||
|
dm_event_handler_get_minor
|
||||||
|
dm_event_handler_get_event_mask
|
||||||
|
dm_event_register_handler
|
||||||
|
dm_event_unregister_handler
|
||||||
|
dm_event_get_registered_device
|
||||||
|
dm_event_handler_set_timeout
|
||||||
|
dm_event_handler_get_timeout
|
||||||
83
daemons/dmeventd/Makefile.in
Normal file
83
daemons/dmeventd/Makefile.in
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# This file is part of the device-mapper userspace tools.
|
||||||
|
#
|
||||||
|
# This copyrighted material is made available to anyone wishing to use,
|
||||||
|
# modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
# of the GNU Lesser General Public License v.2.1.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
srcdir = @srcdir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
SOURCES = libdevmapper-event.c
|
||||||
|
|
||||||
|
LIB_STATIC = libdevmapper-event.a
|
||||||
|
|
||||||
|
ifeq ("@LIB_SUFFIX@","dylib")
|
||||||
|
LIB_SHARED = libdevmapper-event.dylib
|
||||||
|
else
|
||||||
|
LIB_SHARED = libdevmapper-event.so
|
||||||
|
endif
|
||||||
|
|
||||||
|
TARGETS = dmeventd
|
||||||
|
CLEAN_TARGETS = dmeventd.o
|
||||||
|
|
||||||
|
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
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@PKGCONFIG@", "yes")
|
||||||
|
INSTALL_TYPE += install_pkgconfig
|
||||||
|
endif
|
||||||
|
|
||||||
|
install: $(INSTALL_TYPE) install_include install_dmeventd
|
||||||
|
|
||||||
|
install_include:
|
||||||
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 444 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) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||||
|
$(libdir)/libdevmapper-event.a.$(LIB_VERSION)
|
||||||
|
$(LN_S) -f libdevmapper-event.a.$(LIB_VERSION) $(libdir)/libdevmapper-event.a
|
||||||
|
|
||||||
|
.PHONY: distclean_lib distclean
|
||||||
|
|
||||||
|
distclean_lib:
|
||||||
|
$(RM) libdevmapper-event.pc
|
||||||
|
|
||||||
|
distclean: distclean_lib
|
||||||
|
|
||||||
1762
daemons/dmeventd/dmeventd.c
Normal file
1762
daemons/dmeventd/dmeventd.c
Normal file
File diff suppressed because it is too large
Load Diff
52
daemons/dmeventd/dmeventd.h
Normal file
52
daemons/dmeventd/dmeventd.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef __DMEVENTD_DOT_H__
|
||||||
|
#define __DMEVENTD_DOT_H__
|
||||||
|
|
||||||
|
/* FIXME This stuff must be configurable. */
|
||||||
|
|
||||||
|
#define DM_EVENT_DAEMON "/sbin/dmeventd"
|
||||||
|
#define DM_EVENT_LOCKFILE "/var/lock/dmeventd"
|
||||||
|
#define DM_EVENT_FIFO_CLIENT "/var/run/dmeventd-client"
|
||||||
|
#define DM_EVENT_FIFO_SERVER "/var/run/dmeventd-server"
|
||||||
|
#define DM_EVENT_PIDFILE "/var/run/dmeventd.pid"
|
||||||
|
|
||||||
|
#define DM_EVENT_DEFAULT_TIMEOUT 10
|
||||||
|
|
||||||
|
/* Commands for the daemon passed in the message below. */
|
||||||
|
enum dm_event_command {
|
||||||
|
DM_EVENT_CMD_ACTIVE = 1,
|
||||||
|
DM_EVENT_CMD_REGISTER_FOR_EVENT,
|
||||||
|
DM_EVENT_CMD_UNREGISTER_FOR_EVENT,
|
||||||
|
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
|
||||||
|
DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
|
||||||
|
DM_EVENT_CMD_SET_TIMEOUT,
|
||||||
|
DM_EVENT_CMD_GET_TIMEOUT,
|
||||||
|
DM_EVENT_CMD_HELLO,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Message passed between client and daemon. */
|
||||||
|
struct dm_event_daemon_message {
|
||||||
|
uint32_t cmd;
|
||||||
|
uint32_t size;
|
||||||
|
char *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME Is this meant to be exported? I can't see where the
|
||||||
|
interface uses it. */
|
||||||
|
/* Fifos for client/daemon communication. */
|
||||||
|
struct dm_event_fifos {
|
||||||
|
int client;
|
||||||
|
int server;
|
||||||
|
const char *client_path;
|
||||||
|
const char *server_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* EXIT_SUCCESS 0 -- stdlib.h */
|
||||||
|
/* EXIT_FAILURE 1 -- stdlib.h */
|
||||||
|
#define EXIT_LOCKFILE_INUSE 2
|
||||||
|
#define EXIT_DESC_CLOSE_FAILURE 3
|
||||||
|
#define EXIT_DESC_OPEN_FAILURE 4
|
||||||
|
#define EXIT_OPEN_PID_FAILURE 5
|
||||||
|
#define EXIT_FIFO_FAILURE 6
|
||||||
|
#define EXIT_CHDIR_FAILURE 7
|
||||||
|
|
||||||
|
#endif /* __DMEVENTD_DOT_H__ */
|
||||||
786
daemons/dmeventd/libdevmapper-event.c
Normal file
786
daemons/dmeventd/libdevmapper-event.c
Normal file
@@ -0,0 +1,786 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of the device-mapper userspace tools.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU Lesser General Public License v.2.1.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "libdevmapper-event.h"
|
||||||
|
//#include "libmultilog.h"
|
||||||
|
#include "dmeventd.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <arpa/inet.h> /* for htonl, ntohl */
|
||||||
|
|
||||||
|
static int _sequence_nr = 0;
|
||||||
|
|
||||||
|
struct dm_event_handler {
|
||||||
|
char *dso;
|
||||||
|
|
||||||
|
char *dev_name;
|
||||||
|
|
||||||
|
char *uuid;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
uint32_t timeout;
|
||||||
|
|
||||||
|
enum dm_event_mask mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
if (dmevh->dev_name)
|
||||||
|
dm_free(dmevh->dev_name);
|
||||||
|
if (dmevh->uuid)
|
||||||
|
dm_free(dmevh->uuid);
|
||||||
|
dmevh->dev_name = dmevh->uuid = NULL;
|
||||||
|
dmevh->major = dmevh->minor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dm_event_handler *dm_event_handler_create(void)
|
||||||
|
{
|
||||||
|
struct dm_event_handler *dmevh = NULL;
|
||||||
|
|
||||||
|
if (!(dmevh = dm_malloc(sizeof(*dmevh))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;
|
||||||
|
dmevh->major = dmevh->minor = 0;
|
||||||
|
dmevh->mask = 0;
|
||||||
|
dmevh->timeout = 0;
|
||||||
|
|
||||||
|
return dmevh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
if (dmevh->dso)
|
||||||
|
dm_free(dmevh->dso);
|
||||||
|
dm_free(dmevh);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
|
||||||
|
{
|
||||||
|
if (!path) /* noop */
|
||||||
|
return 0;
|
||||||
|
if (dmevh->dso)
|
||||||
|
dm_free(dmevh->dso);
|
||||||
|
|
||||||
|
dmevh->dso = dm_strdup(path);
|
||||||
|
if (!dmevh->dso)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
|
||||||
|
{
|
||||||
|
if (!dev_name)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
|
||||||
|
dmevh->dev_name = dm_strdup(dev_name);
|
||||||
|
if (!dmevh->dev_name)
|
||||||
|
return -ENOMEM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
|
||||||
|
{
|
||||||
|
if (!uuid)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
|
||||||
|
dmevh->uuid = dm_strdup(uuid);
|
||||||
|
if (!dmevh->dev_name)
|
||||||
|
return -ENOMEM;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
|
||||||
|
{
|
||||||
|
int minor = dmevh->minor;
|
||||||
|
|
||||||
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
|
||||||
|
dmevh->major = major;
|
||||||
|
dmevh->minor = minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
|
||||||
|
{
|
||||||
|
int major = dmevh->major;
|
||||||
|
|
||||||
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
|
||||||
|
dmevh->major = major;
|
||||||
|
dmevh->minor = minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
|
||||||
|
enum dm_event_mask evmask)
|
||||||
|
{
|
||||||
|
dmevh->mask = evmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
|
||||||
|
{
|
||||||
|
dmevh->timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
return dmevh->dso;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
return dmevh->dev_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
return dmevh->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
return dmevh->major;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
return dmevh->minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
return dmevh->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
return dmevh->mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _check_message_id(struct dm_event_daemon_message *msg)
|
||||||
|
{
|
||||||
|
int pid, seq_nr;
|
||||||
|
|
||||||
|
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
|
||||||
|
(pid != getpid()) || (seq_nr != _sequence_nr)) {
|
||||||
|
log_error("Ignoring out-of-sequence reply from dmeventd. "
|
||||||
|
"Expected %d:%d but received %s", getpid(),
|
||||||
|
_sequence_nr, msg->data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* daemon_read
|
||||||
|
* @fifos
|
||||||
|
* @msg
|
||||||
|
*
|
||||||
|
* Read message from daemon.
|
||||||
|
*
|
||||||
|
* Returns: 0 on failure, 1 on success
|
||||||
|
*/
|
||||||
|
static int _daemon_read(struct dm_event_fifos *fifos,
|
||||||
|
struct dm_event_daemon_message *msg)
|
||||||
|
{
|
||||||
|
unsigned bytes = 0;
|
||||||
|
int ret, i;
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval tval = { 0, 0 };
|
||||||
|
size_t size = 2 * sizeof(uint32_t); /* status + size */
|
||||||
|
char *buf = alloca(size);
|
||||||
|
int header = 1;
|
||||||
|
|
||||||
|
while (bytes < size) {
|
||||||
|
for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
|
||||||
|
/* Watch daemon read FIFO for input. */
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(fifos->server, &fds);
|
||||||
|
tval.tv_sec = 1;
|
||||||
|
ret = select(fifos->server + 1, &fds, NULL, NULL,
|
||||||
|
&tval);
|
||||||
|
if (ret < 0 && errno != EINTR) {
|
||||||
|
log_error("Unable to read from event server");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret < 1) {
|
||||||
|
log_error("Unable to read from event server.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = read(fifos->server, buf + bytes, size);
|
||||||
|
if (ret < 0) {
|
||||||
|
if ((errno == EINTR) || (errno == EAGAIN))
|
||||||
|
continue;
|
||||||
|
else {
|
||||||
|
log_error("Unable to read from event server.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes += ret;
|
||||||
|
if (bytes == 2 * sizeof(uint32_t) && header) {
|
||||||
|
msg->cmd = ntohl(*((uint32_t *)buf));
|
||||||
|
msg->size = ntohl(*((uint32_t *)buf + 1));
|
||||||
|
buf = msg->data = dm_malloc(msg->size);
|
||||||
|
size = msg->size;
|
||||||
|
bytes = 0;
|
||||||
|
header = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes != size) {
|
||||||
|
if (msg->data)
|
||||||
|
dm_free(msg->data);
|
||||||
|
msg->data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes == size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write message to daemon. */
|
||||||
|
static int _daemon_write(struct dm_event_fifos *fifos,
|
||||||
|
struct dm_event_daemon_message *msg)
|
||||||
|
{
|
||||||
|
unsigned bytes = 0;
|
||||||
|
int ret = 0;
|
||||||
|
fd_set fds;
|
||||||
|
|
||||||
|
size_t size = 2 * sizeof(uint32_t) + msg->size;
|
||||||
|
char *buf = alloca(size);
|
||||||
|
char drainbuf[128];
|
||||||
|
struct timeval tval = { 0, 0 };
|
||||||
|
|
||||||
|
*((uint32_t *)buf) = htonl(msg->cmd);
|
||||||
|
*((uint32_t *)buf + 1) = htonl(msg->size);
|
||||||
|
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
|
||||||
|
|
||||||
|
/* drain the answer fifo */
|
||||||
|
while (1) {
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(fifos->server, &fds);
|
||||||
|
tval.tv_usec = 100;
|
||||||
|
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
|
||||||
|
if ((ret < 0) && (errno != EINTR)) {
|
||||||
|
log_error("Unable to talk to event daemon");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ret == 0)
|
||||||
|
break;
|
||||||
|
read(fifos->server, drainbuf, 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (bytes < size) {
|
||||||
|
do {
|
||||||
|
/* Watch daemon write FIFO to be ready for output. */
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(fifos->client, &fds);
|
||||||
|
ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
|
||||||
|
if ((ret < 0) && (errno != EINTR)) {
|
||||||
|
log_error("Unable to talk to event daemon");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} while (ret < 1);
|
||||||
|
|
||||||
|
ret = write(fifos->client, ((char *) buf) + bytes,
|
||||||
|
size - bytes);
|
||||||
|
if (ret < 0) {
|
||||||
|
if ((errno == EINTR) || (errno == EAGAIN))
|
||||||
|
continue;
|
||||||
|
else {
|
||||||
|
log_error("Unable to talk to event daemon");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes == size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _daemon_talk(struct dm_event_fifos *fifos,
|
||||||
|
struct dm_event_daemon_message *msg, int cmd,
|
||||||
|
const char *dso_name, const char *dev_name,
|
||||||
|
enum dm_event_mask evmask, uint32_t timeout)
|
||||||
|
{
|
||||||
|
const char *dso = dso_name ? dso_name : "";
|
||||||
|
const char *dev = dev_name ? dev_name : "";
|
||||||
|
const char *fmt = "%d:%d %s %s %u %" PRIu32;
|
||||||
|
int msg_size;
|
||||||
|
memset(msg, 0, sizeof(*msg));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set command and pack the arguments
|
||||||
|
* into ASCII message string.
|
||||||
|
*/
|
||||||
|
msg->cmd = cmd;
|
||||||
|
if (cmd == DM_EVENT_CMD_HELLO)
|
||||||
|
fmt = "%d:%d HELLO";
|
||||||
|
if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
|
||||||
|
dso, dev, evmask, timeout)) < 0) {
|
||||||
|
log_error("_daemon_talk: message allocation failed");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
msg->size = msg_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write command and message to and
|
||||||
|
* read status return code from daemon.
|
||||||
|
*/
|
||||||
|
if (!_daemon_write(fifos, msg)) {
|
||||||
|
stack;
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!_daemon_read(fifos, msg)) {
|
||||||
|
stack;
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
} while (!_check_message_id(msg));
|
||||||
|
|
||||||
|
_sequence_nr++;
|
||||||
|
|
||||||
|
return (int32_t) msg->cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start_daemon
|
||||||
|
*
|
||||||
|
* This function forks off a process (dmeventd) that will handle
|
||||||
|
* the events. I am currently test opening one of the fifos to
|
||||||
|
* ensure that the daemon is running and listening... I thought
|
||||||
|
* this would be less expensive than fork/exec'ing every time.
|
||||||
|
* Perhaps there is an even quicker/better way (no, checking the
|
||||||
|
* lock file is _not_ a better way).
|
||||||
|
*
|
||||||
|
* Returns: 1 on success, 0 otherwise
|
||||||
|
*/
|
||||||
|
static int _start_daemon(struct dm_event_fifos *fifos)
|
||||||
|
{
|
||||||
|
int pid, ret = 0;
|
||||||
|
int status;
|
||||||
|
struct stat statbuf;
|
||||||
|
|
||||||
|
if (stat(fifos->client_path, &statbuf))
|
||||||
|
goto start_server;
|
||||||
|
|
||||||
|
if (!S_ISFIFO(statbuf.st_mode)) {
|
||||||
|
log_error("%s is not a fifo.", fifos->client_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Anyone listening? If not, errno will be ENXIO */
|
||||||
|
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
|
||||||
|
if (fifos->client >= 0) {
|
||||||
|
/* server is running and listening */
|
||||||
|
|
||||||
|
close(fifos->client);
|
||||||
|
return 1;
|
||||||
|
} else if (errno != ENXIO) {
|
||||||
|
/* problem */
|
||||||
|
|
||||||
|
log_error("%s: Can't open client fifo %s: %s",
|
||||||
|
__func__, fifos->client_path, strerror(errno));
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_server:
|
||||||
|
/* server is not running */
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if (pid < 0)
|
||||||
|
log_error("Unable to fork.");
|
||||||
|
|
||||||
|
else if (!pid) {
|
||||||
|
execvp(DMEVENTD_PATH, NULL);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else {
|
||||||
|
if (waitpid(pid, &status, 0) < 0)
|
||||||
|
log_error("Unable to start dmeventd: %s",
|
||||||
|
strerror(errno));
|
||||||
|
else if (WEXITSTATUS(status))
|
||||||
|
log_error("Unable to start dmeventd.");
|
||||||
|
else
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize client. */
|
||||||
|
static int _init_client(struct dm_event_fifos *fifos)
|
||||||
|
{
|
||||||
|
/* FIXME? Is fifo the most suitable method? Why not share
|
||||||
|
comms/daemon code with something else e.g. multipath? */
|
||||||
|
|
||||||
|
/* init fifos */
|
||||||
|
memset(fifos, 0, sizeof(*fifos));
|
||||||
|
fifos->client_path = DM_EVENT_FIFO_CLIENT;
|
||||||
|
fifos->server_path = DM_EVENT_FIFO_SERVER;
|
||||||
|
|
||||||
|
if (!_start_daemon(fifos)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the fifo used to read from the daemon. */
|
||||||
|
if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
|
||||||
|
log_error("%s: open server fifo %s",
|
||||||
|
__func__, fifos->server_path);
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock out anyone else trying to do communication with the daemon. */
|
||||||
|
if (flock(fifos->server, LOCK_EX) < 0) {
|
||||||
|
log_error("%s: flock %s", __func__, fifos->server_path);
|
||||||
|
close(fifos->server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
|
||||||
|
if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
|
||||||
|
log_error("%s: Can't open client fifo %s: %s",
|
||||||
|
__func__, fifos->client_path, strerror(errno));
|
||||||
|
close(fifos->server);
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _dtr_client(struct dm_event_fifos *fifos)
|
||||||
|
{
|
||||||
|
if (flock(fifos->server, LOCK_UN))
|
||||||
|
log_error("flock unlock %s", fifos->server_path);
|
||||||
|
|
||||||
|
close(fifos->client);
|
||||||
|
close(fifos->server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get uuid of a device */
|
||||||
|
static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
struct dm_task *dmt;
|
||||||
|
struct dm_info info;
|
||||||
|
|
||||||
|
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
|
||||||
|
log_error("_get_device_info: dm_task creation for info failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dmevh->uuid)
|
||||||
|
dm_task_set_uuid(dmt, dmevh->uuid);
|
||||||
|
else if (dmevh->dev_name)
|
||||||
|
dm_task_set_name(dmt, dmevh->dev_name);
|
||||||
|
else if (dmevh->major && dmevh->minor) {
|
||||||
|
dm_task_set_major(dmt, dmevh->major);
|
||||||
|
dm_task_set_minor(dmt, dmevh->minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Add name or uuid or devno to messages */
|
||||||
|
if (!dm_task_run(dmt)) {
|
||||||
|
log_error("_get_device_info: dm_task_run() failed");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dm_task_get_info(dmt, &info)) {
|
||||||
|
log_error("_get_device_info: failed to get info for device");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.exists) {
|
||||||
|
log_error("_get_device_info: device not found");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dmt;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the event (de)registration call and return negative error codes. */
|
||||||
|
static int _do_event(int cmd, struct dm_event_daemon_message *msg,
|
||||||
|
const char *dso_name, const char *dev_name,
|
||||||
|
enum dm_event_mask evmask, uint32_t timeout)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct dm_event_fifos fifos;
|
||||||
|
|
||||||
|
if (!_init_client(&fifos)) {
|
||||||
|
stack;
|
||||||
|
return -ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0);
|
||||||
|
if (!ret)
|
||||||
|
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
|
||||||
|
|
||||||
|
/* what is the opposite of init? */
|
||||||
|
_dtr_client(&fifos);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* External library interface. */
|
||||||
|
int dm_event_register_handler(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
int ret = 1, err;
|
||||||
|
const char *uuid;
|
||||||
|
struct dm_task *dmt;
|
||||||
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
|
if (!(dmt = _get_device_info(dmevh))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid = dm_task_get_uuid(dmt);
|
||||||
|
|
||||||
|
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
|
||||||
|
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
||||||
|
log_error("%s: event registration failed: %s",
|
||||||
|
dm_task_get_name(dmt),
|
||||||
|
msg.data ? msg.data : strerror(-err));
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.data)
|
||||||
|
dm_free(msg.data);
|
||||||
|
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
|
||||||
|
{
|
||||||
|
int ret = 1, err;
|
||||||
|
const char *uuid;
|
||||||
|
struct dm_task *dmt;
|
||||||
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
|
if (!(dmt = _get_device_info(dmevh))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid = dm_task_get_uuid(dmt);
|
||||||
|
|
||||||
|
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
|
||||||
|
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
|
||||||
|
log_error("%s: event deregistration failed: %s",
|
||||||
|
dm_task_get_name(dmt),
|
||||||
|
msg.data ? msg.data : strerror(-err));
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.data)
|
||||||
|
dm_free(msg.data);
|
||||||
|
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetch a string off src and duplicate it into *dest. */
|
||||||
|
/* FIXME: move to separate module to share with the daemon. */
|
||||||
|
static char *_fetch_string(char **src, const int delimiter)
|
||||||
|
{
|
||||||
|
char *p, *ret;
|
||||||
|
|
||||||
|
if ((p = strchr(*src, delimiter)))
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
if ((ret = dm_strdup(*src)))
|
||||||
|
*src += strlen(ret) + 1;
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
*p = delimiter;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse a device message from the daemon. */
|
||||||
|
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
|
||||||
|
char **uuid, enum dm_event_mask *evmask)
|
||||||
|
{
|
||||||
|
char *id = NULL;
|
||||||
|
char *p = msg->data;
|
||||||
|
|
||||||
|
if ((id = _fetch_string(&p, ' ')) &&
|
||||||
|
(*dso_name = _fetch_string(&p, ' ')) &&
|
||||||
|
(*uuid = _fetch_string(&p, ' '))) {
|
||||||
|
*evmask = atoi(p);
|
||||||
|
|
||||||
|
dm_free(id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id)
|
||||||
|
dm_free(id);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dm_event_get_registered_device
|
||||||
|
* @dso_name
|
||||||
|
* @device_path
|
||||||
|
* @mask
|
||||||
|
* @next
|
||||||
|
*
|
||||||
|
* Returns: 0 if handler found, error (-ENOMEM, -ENOENT) otherwise
|
||||||
|
*/
|
||||||
|
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
const char *uuid = NULL;
|
||||||
|
char *reply_dso = NULL, *reply_uuid = NULL;
|
||||||
|
enum dm_event_mask reply_mask = 0;
|
||||||
|
struct dm_task *dmt = NULL;
|
||||||
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
|
if (!(dmt = _get_device_info(dmevh))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid = dm_task_get_uuid(dmt);
|
||||||
|
|
||||||
|
if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
|
||||||
|
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
|
||||||
|
&msg, dmevh->dso, uuid, dmevh->mask, 0))) {
|
||||||
|
/* FIXME this will probably horribly break if we get
|
||||||
|
ill-formatted reply */
|
||||||
|
ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
|
||||||
|
} else {
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
|
if (msg.data) {
|
||||||
|
dm_free(msg.data);
|
||||||
|
msg.data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
dmevh->uuid = dm_strdup(reply_uuid);
|
||||||
|
if (!dmevh->uuid) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dmt = _get_device_info(dmevh))) {
|
||||||
|
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_event_handler_set_dso(dmevh, reply_dso);
|
||||||
|
dm_event_handler_set_event_mask(dmevh, reply_mask);
|
||||||
|
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
|
||||||
|
if (!dmevh->dev_name) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dm_info info;
|
||||||
|
if (!dm_task_get_info(dmt, &info)) {
|
||||||
|
ret = -1;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
dmevh->major = info.major;
|
||||||
|
dmevh->minor = info.minor;
|
||||||
|
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (msg.data)
|
||||||
|
dm_free(msg.data);
|
||||||
|
_dm_event_handler_clear_dev_info(dmevh);
|
||||||
|
dm_task_destroy(dmt);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 /* left out for now */
|
||||||
|
|
||||||
|
static char *_skip_string(char *src, const int delimiter)
|
||||||
|
{
|
||||||
|
src = srtchr(src, delimiter);
|
||||||
|
if (src && *(src + 1))
|
||||||
|
return src + 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
|
||||||
|
{
|
||||||
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
|
if (!device_exists(device_path))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
|
||||||
|
NULL, device_path, 0, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct dm_event_daemon_message msg = { 0, 0, NULL };
|
||||||
|
|
||||||
|
if (!device_exists(device_path))
|
||||||
|
return -ENODEV;
|
||||||
|
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
|
||||||
|
0, 0))) {
|
||||||
|
char *p = _skip_string(msg.data, ' ');
|
||||||
|
if (!p) {
|
||||||
|
log_error("malformed reply from dmeventd '%s'\n",
|
||||||
|
msg.data);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
*timeout = atoi(p);
|
||||||
|
}
|
||||||
|
if (msg.data)
|
||||||
|
dm_free(msg.data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
106
daemons/dmeventd/libdevmapper-event.h
Normal file
106
daemons/dmeventd/libdevmapper-event.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of the device-mapper userspace tools.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU Lesser General Public License v.2.1.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that this file is released only as part of a technology preview
|
||||||
|
* and its contents may change in future updates in ways that do not
|
||||||
|
* preserve compatibility.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIB_DMEVENT_H
|
||||||
|
#define LIB_DMEVENT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Event library interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum dm_event_mask {
|
||||||
|
DM_EVENT_SETTINGS_MASK = 0x0000FF,
|
||||||
|
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
|
||||||
|
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
|
||||||
|
|
||||||
|
DM_EVENT_ERROR_MASK = 0x00FF00,
|
||||||
|
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
|
||||||
|
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
|
||||||
|
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
|
||||||
|
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
|
||||||
|
|
||||||
|
DM_EVENT_STATUS_MASK = 0xFF0000,
|
||||||
|
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
|
||||||
|
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occured */
|
||||||
|
|
||||||
|
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
|
||||||
|
|
||||||
|
struct dm_event_handler;
|
||||||
|
|
||||||
|
struct dm_event_handler *dm_event_handler_create(void);
|
||||||
|
void dm_event_handler_destroy(struct dm_event_handler *dmevh);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Path of shared library to handle events.
|
||||||
|
*
|
||||||
|
* All of dso, device_name and uuid strings are duplicated, you do not
|
||||||
|
* need to keep the pointers valid after the call succeeds. Thes may
|
||||||
|
* return -ENOMEM though.
|
||||||
|
*/
|
||||||
|
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Identify the device to monitor by exactly one of device_name, uuid or
|
||||||
|
* device number. String arguments are duplicated, see above.
|
||||||
|
*/
|
||||||
|
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
|
||||||
|
|
||||||
|
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
|
||||||
|
|
||||||
|
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
|
||||||
|
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
|
||||||
|
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specify mask for events to monitor.
|
||||||
|
*/
|
||||||
|
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
|
||||||
|
enum dm_event_mask evmask);
|
||||||
|
|
||||||
|
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
|
||||||
|
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
|
||||||
|
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
|
||||||
|
int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
|
||||||
|
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
|
||||||
|
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh);
|
||||||
|
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
|
||||||
|
|
||||||
|
/* FIXME Review interface (what about this next thing?) */
|
||||||
|
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initiate monitoring using dmeventd.
|
||||||
|
*/
|
||||||
|
int dm_event_register_handler(const struct dm_event_handler *dmevh);
|
||||||
|
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
|
||||||
|
|
||||||
|
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
|
||||||
|
detailed descriptions. */
|
||||||
|
void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
|
||||||
|
int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
|
||||||
|
int unregister_device(const char *device_name, const char *uuid, int major,
|
||||||
|
int minor, void **user);
|
||||||
|
|
||||||
|
#endif
|
||||||
12
daemons/dmeventd/libdevmapper-event.pc.in
Normal file
12
daemons/dmeventd/libdevmapper-event.pc.in
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: devmapper-event
|
||||||
|
Description: device-mapper event library
|
||||||
|
Version: @DM_LIB_VERSION@
|
||||||
|
Requires: devmapper
|
||||||
|
Cflags: -I${includedir}
|
||||||
|
Libs: -L${libdir} -ldevmapper-event
|
||||||
|
Libs.private: -lpthread -ldl
|
||||||
22
daemons/dmeventd/plugins/Makefile.in
Normal file
22
daemons/dmeventd/plugins/Makefile.in
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004-2005 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@
|
||||||
|
|
||||||
|
SUBDIRS += mirror
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
3
daemons/dmeventd/plugins/mirror/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
process_event
|
||||||
|
register_device
|
||||||
|
unregister_device
|
||||||
36
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
36
daemons/dmeventd/plugins/mirror/Makefile.in
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004-2005 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 -llvm2cmd
|
||||||
|
|
||||||
|
SOURCES = dmeventd_mirror.c
|
||||||
|
|
||||||
|
ifeq ("@LIB_SUFFIX@","dylib")
|
||||||
|
LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
|
||||||
|
else
|
||||||
|
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||||
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||||
|
$(libdir)/$<.$(LIB_VERSION)
|
||||||
|
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||||
|
|
||||||
281
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
281
daemons/dmeventd/plugins/mirror/dmeventd_mirror.c
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
* 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 "libdevmapper.h"
|
||||||
|
#include "libdevmapper-event.h"
|
||||||
|
#include "lvm2cmd.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||||
|
/* FIXME Missing openlog? */
|
||||||
|
|
||||||
|
#define ME_IGNORE 0
|
||||||
|
#define ME_INSYNC 1
|
||||||
|
#define ME_FAILURE 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* register_device() is called first and performs initialisation.
|
||||||
|
* Only one device may be registered or unregistered at a time.
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of active registrations.
|
||||||
|
*/
|
||||||
|
static int _register_count = 0;
|
||||||
|
|
||||||
|
static struct dm_pool *_mem_pool = NULL;
|
||||||
|
static void *_lvm_handle = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently only one event can be processed at a time.
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static int _get_mirror_event(char *params)
|
||||||
|
{
|
||||||
|
int i, r = ME_INSYNC;
|
||||||
|
char **args = NULL;
|
||||||
|
char *dev_status_str;
|
||||||
|
char *log_status_str;
|
||||||
|
char *sync_str;
|
||||||
|
char *p = NULL;
|
||||||
|
int log_argc, num_devs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dm core parms: 0 409600 mirror
|
||||||
|
* Mirror core parms: 2 253:4 253:5 400/400
|
||||||
|
* New-style failure params: 1 AA
|
||||||
|
* New-style log params: 3 cluster 253:3 A
|
||||||
|
* or 3 disk 253:3 A
|
||||||
|
* or 1 core
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* number of devices */
|
||||||
|
if (!dm_split_words(params, 1, 0, &p))
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
|
if (!(num_devs = atoi(p)))
|
||||||
|
goto out_parse;
|
||||||
|
p += strlen(p) + 1;
|
||||||
|
|
||||||
|
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
|
||||||
|
args = dm_malloc((num_devs + 7) * sizeof(char *));
|
||||||
|
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
|
dev_status_str = args[2 + num_devs];
|
||||||
|
log_argc = atoi(args[3 + num_devs]);
|
||||||
|
log_status_str = args[3 + num_devs + log_argc];
|
||||||
|
sync_str = args[num_devs];
|
||||||
|
|
||||||
|
/* Check for bad mirror devices */
|
||||||
|
for (i = 0; i < num_devs; i++)
|
||||||
|
if (dev_status_str[i] == 'D') {
|
||||||
|
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
|
||||||
|
r = ME_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for bad disk log device */
|
||||||
|
if (log_argc > 1 && log_status_str[0] == 'D') {
|
||||||
|
syslog(LOG_ERR, "Log device, %s, has failed.\n",
|
||||||
|
args[2 + num_devs + log_argc]);
|
||||||
|
r = ME_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == ME_FAILURE)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
p = strstr(sync_str, "/");
|
||||||
|
if (p) {
|
||||||
|
p[0] = '\0';
|
||||||
|
if (strcmp(sync_str, p+1))
|
||||||
|
r = ME_IGNORE;
|
||||||
|
p[0] = '/';
|
||||||
|
} else
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (args)
|
||||||
|
dm_free(args);
|
||||||
|
return r;
|
||||||
|
|
||||||
|
out_parse:
|
||||||
|
if (args)
|
||||||
|
dm_free(args);
|
||||||
|
syslog(LOG_ERR, "Unable to parse mirror status string.");
|
||||||
|
return ME_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _temporary_log_fn(int level, const char *file,
|
||||||
|
int line, const char *format)
|
||||||
|
{
|
||||||
|
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||||
|
syslog(LOG_CRIT, "%s", format);
|
||||||
|
else
|
||||||
|
syslog(LOG_DEBUG, "%s", format);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _remove_failed_devices(const char *device)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
||||||
|
char cmd_str[CMD_SIZE];
|
||||||
|
char *vg = NULL, *lv = NULL, *layer = NULL;
|
||||||
|
|
||||||
|
if (strlen(device) > 200) /* FIXME Use real restriction */
|
||||||
|
return -ENAMETOOLONG; /* FIXME These return code distinctions are not used so remove them! */
|
||||||
|
|
||||||
|
if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
|
||||||
|
syslog(LOG_ERR, "Unable to determine VG name from %s",
|
||||||
|
device);
|
||||||
|
return -ENOMEM; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Is any sanity-checking required on %s? */
|
||||||
|
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
|
||||||
|
/* this error should be caught above, but doesn't hurt to check again */
|
||||||
|
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||||
|
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||||
|
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||||
|
}
|
||||||
|
|
||||||
|
r = lvm2_run(_lvm_handle, cmd_str);
|
||||||
|
|
||||||
|
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||||
|
return (r == 1) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||||
|
void **unused __attribute((unused)))
|
||||||
|
{
|
||||||
|
void *next = NULL;
|
||||||
|
uint64_t start, length;
|
||||||
|
char *target_type = NULL;
|
||||||
|
char *params;
|
||||||
|
const char *device = dm_task_get_name(dmt);
|
||||||
|
|
||||||
|
if (pthread_mutex_trylock(&_event_mutex)) {
|
||||||
|
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
|
||||||
|
pthread_mutex_lock(&_event_mutex);
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
next = dm_get_next_target(dmt, next, &start, &length,
|
||||||
|
&target_type, ¶ms);
|
||||||
|
|
||||||
|
if (!target_type) {
|
||||||
|
syslog(LOG_INFO, "%s mapping lost.\n", device);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(target_type, "mirror")) {
|
||||||
|
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(_get_mirror_event(params)) {
|
||||||
|
case ME_INSYNC:
|
||||||
|
/* FIXME: all we really know is that this
|
||||||
|
_part_ of the device is in sync
|
||||||
|
Also, this is not an error
|
||||||
|
*/
|
||||||
|
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
|
||||||
|
break;
|
||||||
|
case ME_FAILURE:
|
||||||
|
syslog(LOG_ERR, "Device failure in %s\n", device);
|
||||||
|
if (_remove_failed_devices(device))
|
||||||
|
/* FIXME Why are all the error return codes unused? Get rid of them? */
|
||||||
|
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
|
||||||
|
device);
|
||||||
|
/* Should check before warning user that device is now linear
|
||||||
|
else
|
||||||
|
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||||
|
device);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case ME_IGNORE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* FIXME Provide value then! */
|
||||||
|
syslog(LOG_INFO, "Unknown event received.\n");
|
||||||
|
}
|
||||||
|
} while (next);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_event_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||||
|
void **unused __attribute((unused)))
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need some space for allocations. 1024 should be more
|
||||||
|
* than enough for what we need (device mapper name splitting)
|
||||||
|
*/
|
||||||
|
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!_lvm_handle) {
|
||||||
|
lvm2_log_fn(_temporary_log_fn);
|
||||||
|
if (!(_lvm_handle = lvm2_init())) {
|
||||||
|
dm_pool_destroy(_mem_pool);
|
||||||
|
_mem_pool = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
|
||||||
|
/* FIXME Temporary: move to dmeventd core */
|
||||||
|
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||||
|
}
|
||||||
|
|
||||||
|
_register_count++;
|
||||||
|
r = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||||
|
void **unused __attribute((unused)))
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
|
||||||
|
device);
|
||||||
|
|
||||||
|
if (!--_register_count) {
|
||||||
|
dm_pool_destroy(_mem_pool);
|
||||||
|
_mem_pool = NULL;
|
||||||
|
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||||
|
lvm2_exit(_lvm_handle);
|
||||||
|
_lvm_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
6
debian/README.Debian
vendored
Normal file
6
debian/README.Debian
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
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
Normal file
82
debian/changelog
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
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
Normal file
24
debian/control
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
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
Normal file
25
debian/copyright
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
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
Normal file
4
debian/dirs
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
etc/lvm
|
||||||
|
usr/share/man/man5
|
||||||
|
usr/share/man/man8
|
||||||
|
sbin
|
||||||
5
debian/docs
vendored
Normal file
5
debian/docs
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
BUGS
|
||||||
|
README
|
||||||
|
VERSION
|
||||||
|
WHATS_NEW
|
||||||
|
doc/*
|
||||||
64
debian/init.d
vendored
Normal file
64
debian/init.d
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#! /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
Normal file
26
debian/manpages
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
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
Executable file
119
debian/rules
vendored
Executable file
@@ -0,0 +1,119 @@
|
|||||||
|
#!/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
|
||||||
22
dmeventd/Makefile.in
Normal file
22
dmeventd/Makefile.in
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004-2005 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@
|
||||||
|
|
||||||
|
SUBDIRS += mirror
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
3
dmeventd/mirror/.exported_symbols
Normal file
3
dmeventd/mirror/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
process_event
|
||||||
|
register_device
|
||||||
|
unregister_device
|
||||||
36
dmeventd/mirror/Makefile.in
Normal file
36
dmeventd/mirror/Makefile.in
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004-2005 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 -llvm2cmd
|
||||||
|
|
||||||
|
SOURCES = dmeventd_mirror.c
|
||||||
|
|
||||||
|
ifeq ("@LIB_SUFFIX@","dylib")
|
||||||
|
LIB_SHARED = libdevmapper-event-lvm2mirror.dylib
|
||||||
|
else
|
||||||
|
LIB_SHARED = libdevmapper-event-lvm2mirror.so
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
install: libdevmapper-event-lvm2mirror.$(LIB_SUFFIX)
|
||||||
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||||
|
$(libdir)/$<.$(LIB_VERSION)
|
||||||
|
$(LN_S) -f $<.$(LIB_VERSION) $(libdir)/$<
|
||||||
|
|
||||||
281
dmeventd/mirror/dmeventd_mirror.c
Normal file
281
dmeventd/mirror/dmeventd_mirror.c
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
* 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 "libdevmapper.h"
|
||||||
|
#include "libdevmapper-event.h"
|
||||||
|
#include "lvm2cmd.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <syslog.h> /* FIXME Replace syslog with multilog */
|
||||||
|
/* FIXME Missing openlog? */
|
||||||
|
|
||||||
|
#define ME_IGNORE 0
|
||||||
|
#define ME_INSYNC 1
|
||||||
|
#define ME_FAILURE 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* register_device() is called first and performs initialisation.
|
||||||
|
* Only one device may be registered or unregistered at a time.
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t _register_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of active registrations.
|
||||||
|
*/
|
||||||
|
static int _register_count = 0;
|
||||||
|
|
||||||
|
static struct dm_pool *_mem_pool = NULL;
|
||||||
|
static void *_lvm_handle = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently only one event can be processed at a time.
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t _event_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
static int _get_mirror_event(char *params)
|
||||||
|
{
|
||||||
|
int i, r = ME_INSYNC;
|
||||||
|
char **args = NULL;
|
||||||
|
char *dev_status_str;
|
||||||
|
char *log_status_str;
|
||||||
|
char *sync_str;
|
||||||
|
char *p = NULL;
|
||||||
|
int log_argc, num_devs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dm core parms: 0 409600 mirror
|
||||||
|
* Mirror core parms: 2 253:4 253:5 400/400
|
||||||
|
* New-style failure params: 1 AA
|
||||||
|
* New-style log params: 3 cluster 253:3 A
|
||||||
|
* or 3 disk 253:3 A
|
||||||
|
* or 1 core
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* number of devices */
|
||||||
|
if (!dm_split_words(params, 1, 0, &p))
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
|
if (!(num_devs = atoi(p)))
|
||||||
|
goto out_parse;
|
||||||
|
p += strlen(p) + 1;
|
||||||
|
|
||||||
|
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
|
||||||
|
args = dm_malloc((num_devs + 7) * sizeof(char *));
|
||||||
|
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
|
dev_status_str = args[2 + num_devs];
|
||||||
|
log_argc = atoi(args[3 + num_devs]);
|
||||||
|
log_status_str = args[3 + num_devs + log_argc];
|
||||||
|
sync_str = args[num_devs];
|
||||||
|
|
||||||
|
/* Check for bad mirror devices */
|
||||||
|
for (i = 0; i < num_devs; i++)
|
||||||
|
if (dev_status_str[i] == 'D') {
|
||||||
|
syslog(LOG_ERR, "Mirror device, %s, has failed.\n", args[i]);
|
||||||
|
r = ME_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for bad disk log device */
|
||||||
|
if (log_argc > 1 && log_status_str[0] == 'D') {
|
||||||
|
syslog(LOG_ERR, "Log device, %s, has failed.\n",
|
||||||
|
args[2 + num_devs + log_argc]);
|
||||||
|
r = ME_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == ME_FAILURE)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
p = strstr(sync_str, "/");
|
||||||
|
if (p) {
|
||||||
|
p[0] = '\0';
|
||||||
|
if (strcmp(sync_str, p+1))
|
||||||
|
r = ME_IGNORE;
|
||||||
|
p[0] = '/';
|
||||||
|
} else
|
||||||
|
goto out_parse;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (args)
|
||||||
|
dm_free(args);
|
||||||
|
return r;
|
||||||
|
|
||||||
|
out_parse:
|
||||||
|
if (args)
|
||||||
|
dm_free(args);
|
||||||
|
syslog(LOG_ERR, "Unable to parse mirror status string.");
|
||||||
|
return ME_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _temporary_log_fn(int level, const char *file,
|
||||||
|
int line, const char *format)
|
||||||
|
{
|
||||||
|
if (!strncmp(format, "WARNING: ", 9) && (level < 5))
|
||||||
|
syslog(LOG_CRIT, "%s", format);
|
||||||
|
else
|
||||||
|
syslog(LOG_DEBUG, "%s", format);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _remove_failed_devices(const char *device)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
#define CMD_SIZE 256 /* FIXME Use system restriction */
|
||||||
|
char cmd_str[CMD_SIZE];
|
||||||
|
char *vg = NULL, *lv = NULL, *layer = NULL;
|
||||||
|
|
||||||
|
if (strlen(device) > 200) /* FIXME Use real restriction */
|
||||||
|
return -ENAMETOOLONG; /* FIXME These return code distinctions are not used so remove them! */
|
||||||
|
|
||||||
|
if (!dm_split_lvm_name(_mem_pool, device, &vg, &lv, &layer)) {
|
||||||
|
syslog(LOG_ERR, "Unable to determine VG name from %s",
|
||||||
|
device);
|
||||||
|
return -ENOMEM; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Is any sanity-checking required on %s? */
|
||||||
|
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
|
||||||
|
/* this error should be caught above, but doesn't hurt to check again */
|
||||||
|
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
|
||||||
|
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||||
|
return -ENAMETOOLONG; /* FIXME Replace with generic error return - reason for failure has already got logged */
|
||||||
|
}
|
||||||
|
|
||||||
|
r = lvm2_run(_lvm_handle, cmd_str);
|
||||||
|
|
||||||
|
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
|
||||||
|
return (r == 1) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_event(struct dm_task *dmt, enum dm_event_mask event,
|
||||||
|
void **unused __attribute((unused)))
|
||||||
|
{
|
||||||
|
void *next = NULL;
|
||||||
|
uint64_t start, length;
|
||||||
|
char *target_type = NULL;
|
||||||
|
char *params;
|
||||||
|
const char *device = dm_task_get_name(dmt);
|
||||||
|
|
||||||
|
if (pthread_mutex_trylock(&_event_mutex)) {
|
||||||
|
syslog(LOG_NOTICE, "Another thread is handling an event. Waiting...");
|
||||||
|
pthread_mutex_lock(&_event_mutex);
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
next = dm_get_next_target(dmt, next, &start, &length,
|
||||||
|
&target_type, ¶ms);
|
||||||
|
|
||||||
|
if (!target_type) {
|
||||||
|
syslog(LOG_INFO, "%s mapping lost.\n", device);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(target_type, "mirror")) {
|
||||||
|
syslog(LOG_INFO, "%s has unmirrored portion.\n", device);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(_get_mirror_event(params)) {
|
||||||
|
case ME_INSYNC:
|
||||||
|
/* FIXME: all we really know is that this
|
||||||
|
_part_ of the device is in sync
|
||||||
|
Also, this is not an error
|
||||||
|
*/
|
||||||
|
syslog(LOG_NOTICE, "%s is now in-sync\n", device);
|
||||||
|
break;
|
||||||
|
case ME_FAILURE:
|
||||||
|
syslog(LOG_ERR, "Device failure in %s\n", device);
|
||||||
|
if (_remove_failed_devices(device))
|
||||||
|
/* FIXME Why are all the error return codes unused? Get rid of them? */
|
||||||
|
syslog(LOG_ERR, "Failed to remove faulty devices in %s\n",
|
||||||
|
device);
|
||||||
|
/* Should check before warning user that device is now linear
|
||||||
|
else
|
||||||
|
syslog(LOG_NOTICE, "%s is now a linear device.\n",
|
||||||
|
device);
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case ME_IGNORE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* FIXME Provide value then! */
|
||||||
|
syslog(LOG_INFO, "Unknown event received.\n");
|
||||||
|
}
|
||||||
|
} while (next);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_event_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int register_device(const char *device, const char *uuid, int major, int minor,
|
||||||
|
void **unused __attribute((unused)))
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "Monitoring mirror device %s for events\n", device);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need some space for allocations. 1024 should be more
|
||||||
|
* than enough for what we need (device mapper name splitting)
|
||||||
|
*/
|
||||||
|
if (!_mem_pool && !(_mem_pool = dm_pool_create("mirror_dso", 1024)))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!_lvm_handle) {
|
||||||
|
lvm2_log_fn(_temporary_log_fn);
|
||||||
|
if (!(_lvm_handle = lvm2_init())) {
|
||||||
|
dm_pool_destroy(_mem_pool);
|
||||||
|
_mem_pool = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
lvm2_log_level(_lvm_handle, LVM2_LOG_SUPPRESS);
|
||||||
|
/* FIXME Temporary: move to dmeventd core */
|
||||||
|
lvm2_run(_lvm_handle, "_memlock_inc");
|
||||||
|
}
|
||||||
|
|
||||||
|
_register_count++;
|
||||||
|
r = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unregister_device(const char *device, const char *uuid, int major, int minor,
|
||||||
|
void **unused __attribute((unused)))
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&_register_mutex);
|
||||||
|
|
||||||
|
syslog(LOG_INFO, "No longer monitoring mirror device %s for events\n",
|
||||||
|
device);
|
||||||
|
|
||||||
|
if (!--_register_count) {
|
||||||
|
dm_pool_destroy(_mem_pool);
|
||||||
|
_mem_pool = NULL;
|
||||||
|
lvm2_run(_lvm_handle, "_memlock_dec");
|
||||||
|
lvm2_exit(_lvm_handle);
|
||||||
|
_lvm_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_register_mutex);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
29
doc/Makefile.in
Normal file
29
doc/Makefile.in
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2004 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@
|
||||||
|
|
||||||
|
CONFSRC=example.conf
|
||||||
|
CONFDEST=lvm.conf
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
install:
|
||||||
|
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||||
|
echo "Installing $(CONFSRC) as $(confdir)/$(CONFDEST)"; \
|
||||||
|
@INSTALL@ -D $(OWNER) $(GROUP) -m 644 $(CONFSRC) \
|
||||||
|
$(confdir)/$(CONFDEST); \
|
||||||
|
fi
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Wow! This is really incredible documentation!
|
|
||||||
379
doc/example.conf
Normal file
379
doc/example.conf
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
# This is an example configuration file for the LVM2 system.
|
||||||
|
# It contains the default settings that would be used if there was no
|
||||||
|
# /etc/lvm/lvm.conf file.
|
||||||
|
#
|
||||||
|
# Refer to 'man lvm.conf' for further information including the file layout.
|
||||||
|
#
|
||||||
|
# To put this file in a different directory and override /etc/lvm set
|
||||||
|
# the environment variable LVM_SYSTEM_DIR before running the tools.
|
||||||
|
|
||||||
|
|
||||||
|
# This section allows you to configure which block devices should
|
||||||
|
# be used by the LVM system.
|
||||||
|
devices {
|
||||||
|
|
||||||
|
# Where do you want your volume groups to appear ?
|
||||||
|
dir = "/dev"
|
||||||
|
|
||||||
|
# An array of directories that contain the device nodes you wish
|
||||||
|
# to use with LVM2.
|
||||||
|
scan = [ "/dev" ]
|
||||||
|
|
||||||
|
# A filter that tells LVM2 to only use a restricted set of devices.
|
||||||
|
# The filter consists of an array of regular expressions. These
|
||||||
|
# expressions can be delimited by a character of your choice, and
|
||||||
|
# prefixed with either an 'a' (for accept) or 'r' (for reject).
|
||||||
|
# The first expression found to match a device name determines if
|
||||||
|
# the device will be accepted or rejected (ignored). Devices that
|
||||||
|
# don't match any patterns are accepted.
|
||||||
|
|
||||||
|
# Be careful if there there are symbolic links or multiple filesystem
|
||||||
|
# entries for the same device as each name is checked separately against
|
||||||
|
# the list of patterns. The effect is that if any name matches any 'a'
|
||||||
|
# pattern, the device is accepted; otherwise if any name matches any 'r'
|
||||||
|
# pattern it is rejected; otherwise it is accepted.
|
||||||
|
|
||||||
|
# Don't have more than one filter line active at once: only one gets used.
|
||||||
|
|
||||||
|
# Run vgscan after you change this parameter to ensure that
|
||||||
|
# the cache file gets regenerated (see below).
|
||||||
|
# If it doesn't do what you expect, check the output of 'vgscan -vvvv'.
|
||||||
|
|
||||||
|
|
||||||
|
# By default we accept every block device:
|
||||||
|
filter = [ "a/.*/" ]
|
||||||
|
|
||||||
|
# Exclude the cdrom drive
|
||||||
|
# filter = [ "r|/dev/cdrom|" ]
|
||||||
|
|
||||||
|
# When testing I like to work with just loopback devices:
|
||||||
|
# filter = [ "a/loop/", "r/.*/" ]
|
||||||
|
|
||||||
|
# Or maybe all loops and ide drives except hdc:
|
||||||
|
# filter =[ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
|
||||||
|
|
||||||
|
# Use anchors if you want to be really specific
|
||||||
|
# filter = [ "a|^/dev/hda8$|", "r/.*/" ]
|
||||||
|
|
||||||
|
# The results of the filtering are cached on disk to avoid
|
||||||
|
# rescanning dud devices (which can take a very long time).
|
||||||
|
# By default this cache is stored in the /etc/lvm/cache directory
|
||||||
|
# in a file called '.cache'.
|
||||||
|
# It is safe to delete the contents: the tools regenerate it.
|
||||||
|
# (The old setting 'cache' is still respected if neither of
|
||||||
|
# these new ones is present.)
|
||||||
|
cache_dir = "/etc/lvm/cache"
|
||||||
|
cache_file_prefix = ""
|
||||||
|
|
||||||
|
# You can turn off writing this cache file by setting this to 0.
|
||||||
|
write_cache_state = 1
|
||||||
|
|
||||||
|
# Advanced settings.
|
||||||
|
|
||||||
|
# List of pairs of additional acceptable block device types found
|
||||||
|
# in /proc/devices with maximum (non-zero) number of partitions.
|
||||||
|
# types = [ "fd", 16 ]
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# in recovery situations.
|
||||||
|
ignore_suspended_devices = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# This section that allows you to configure the nature of the
|
||||||
|
# information that LVM2 reports.
|
||||||
|
log {
|
||||||
|
|
||||||
|
# Controls the messages sent to stdout or stderr.
|
||||||
|
# There are three levels of verbosity, 3 being the most verbose.
|
||||||
|
verbose = 0
|
||||||
|
|
||||||
|
# Should we send log messages through syslog?
|
||||||
|
# 1 is yes; 0 is no.
|
||||||
|
syslog = 1
|
||||||
|
|
||||||
|
# Should we log error and debug messages to a file?
|
||||||
|
# By default there is no log file.
|
||||||
|
#file = "/var/log/lvm2.log"
|
||||||
|
|
||||||
|
# Should we overwrite the log file each time the program is run?
|
||||||
|
# By default we append.
|
||||||
|
overwrite = 0
|
||||||
|
|
||||||
|
# What level of log messages should we send to the log file and/or syslog?
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Whether or not (1 or 0) to display the command name on each line output
|
||||||
|
command_names = 0
|
||||||
|
|
||||||
|
# A prefix to use before the message text (but after the command name,
|
||||||
|
# if selected). Default is two spaces, so you can see/grep the severity
|
||||||
|
# of each message.
|
||||||
|
prefix = " "
|
||||||
|
|
||||||
|
# To make the messages look similar to the original LVM tools use:
|
||||||
|
# indent = 0
|
||||||
|
# command_names = 1
|
||||||
|
# prefix = " -- "
|
||||||
|
|
||||||
|
# Set this if you want log messages during activation.
|
||||||
|
# Don't use this in low memory situations (can deadlock).
|
||||||
|
# activation = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Configuration of metadata backups and archiving. In LVM2 when we
|
||||||
|
# talk about a 'backup' we mean making a copy of the metadata for the
|
||||||
|
# *current* system. The 'archive' contains old metadata configurations.
|
||||||
|
# Backups are stored in a human readeable text format.
|
||||||
|
backup {
|
||||||
|
|
||||||
|
# Should we maintain a backup of the current metadata configuration ?
|
||||||
|
# Use 1 for Yes; 0 for No.
|
||||||
|
# Think very hard before turning this off!
|
||||||
|
backup = 1
|
||||||
|
|
||||||
|
# Where shall we keep it ?
|
||||||
|
# Remember to back up this directory regularly!
|
||||||
|
backup_dir = "/etc/lvm/backup"
|
||||||
|
|
||||||
|
# Should we maintain an archive of old metadata configurations.
|
||||||
|
# Use 1 for Yes; 0 for No.
|
||||||
|
# On by default. Think very hard before turning this off.
|
||||||
|
archive = 1
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# What is the minimum time you wish to keep an archive file for ?
|
||||||
|
retain_days = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
# Settings for the running LVM2 in shell (readline) mode.
|
||||||
|
shell {
|
||||||
|
|
||||||
|
# Number of lines of history to store in ~/.lvm_history
|
||||||
|
history_size = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Allow other users to read the files
|
||||||
|
#umask = 022
|
||||||
|
|
||||||
|
# Enabling test mode means that no changes to the on disk metadata
|
||||||
|
# will be made. Equivalent to having the -t option on every
|
||||||
|
# command. Defaults to off.
|
||||||
|
test = 0
|
||||||
|
|
||||||
|
# Default value for --units argument
|
||||||
|
units = "h"
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
# If the device-mapper kernel driver is not present in your kernel
|
||||||
|
# setting this to 0 should suppress the error messages.
|
||||||
|
activation = 1
|
||||||
|
|
||||||
|
# If we can't communicate with device-mapper, should we try running
|
||||||
|
# the LVM1 tools?
|
||||||
|
# This option only applies to 2.4 kernels and is provided to help you
|
||||||
|
# switch between device-mapper kernels and LVM1 kernels.
|
||||||
|
# The LVM1 tools need to be installed with .lvm1 suffices
|
||||||
|
# e.g. vgscan.lvm1 and they will stop working after you start using
|
||||||
|
# the new lvm2 on-disk metadata format.
|
||||||
|
# The default value is set when the tools are built.
|
||||||
|
# fallback_to_lvm1 = 0
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
|
||||||
|
# Location of proc filesystem
|
||||||
|
proc = "/proc"
|
||||||
|
|
||||||
|
# Type of locking to use. Defaults to local file-based locking (1).
|
||||||
|
# Turn locking off by setting to 0 (dangerous: risks metadata corruption
|
||||||
|
# if LVM2 commands get run concurrently).
|
||||||
|
# Type 2 uses the external shared library locking_library.
|
||||||
|
# Type 3 uses built-in clustered locking.
|
||||||
|
locking_type = 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.
|
||||||
|
# If you are using a customised locking_library you should set this to 0.
|
||||||
|
fallback_to_clustered_locking = 1
|
||||||
|
|
||||||
|
# If an attempt to initialise type 2 or type 3 locking failed, perhaps
|
||||||
|
# because cluster components such as clvmd are not running, with this set
|
||||||
|
# to 1 an attempt will be made to use local file-based locking (type 1).
|
||||||
|
# If this succeeds, only commands against local volume groups will proceed.
|
||||||
|
# Volume Groups marked as clustered will be ignored.
|
||||||
|
fallback_to_local_locking = 1
|
||||||
|
|
||||||
|
# Local non-LV directory that holds file-based locks while commands are
|
||||||
|
# in progress. A directory like /tmp that may get wiped on reboot is OK.
|
||||||
|
locking_dir = "/var/lock/lvm"
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
# Full pathnames can be given.
|
||||||
|
|
||||||
|
# Search this directory first for shared libraries.
|
||||||
|
# library_dir = "/lib"
|
||||||
|
|
||||||
|
# The external locking library to load if locking_type is set to 2.
|
||||||
|
# locking_library = "liblvm2clusterlock.so"
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
# How much stack (in KB) to reserve for use while devices suspended
|
||||||
|
reserved_stack = 256
|
||||||
|
|
||||||
|
# How much memory (in KB) to reserve for use while devices suspended
|
||||||
|
reserved_memory = 8192
|
||||||
|
|
||||||
|
# Nice value used while devices suspended
|
||||||
|
process_priority = -18
|
||||||
|
|
||||||
|
# If volume_list is defined, each LV is only activated if there is a
|
||||||
|
# match against the list.
|
||||||
|
# "vgname" and "vgname/lvname" are matched exactly.
|
||||||
|
# "@tag" matches any tag set in the LV or VG.
|
||||||
|
# "@*" matches if any tag defined on the host is also set in the LV or VG
|
||||||
|
#
|
||||||
|
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||||
|
|
||||||
|
# Size (in KB) of each copy operation when mirroring
|
||||||
|
mirror_region_size = 512
|
||||||
|
|
||||||
|
# 'mirror_image_fault_policy' and 'mirror_log_fault_policy' define
|
||||||
|
# how a device failure affecting a mirror is handled.
|
||||||
|
# A mirror is composed of mirror images (copies) and a log.
|
||||||
|
# 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:
|
||||||
|
#
|
||||||
|
# "remove" - Simply remove the faulty device and run without it. If
|
||||||
|
# the log device fails, the mirror would convert to using
|
||||||
|
# an in-memory log. This means the mirror will not
|
||||||
|
# remember its sync status across crashes/reboots and
|
||||||
|
# the entire mirror will be re-synced. If a
|
||||||
|
# mirror image fails, the mirror will convert to a
|
||||||
|
# non-mirrored device if there is only one remaining good
|
||||||
|
# copy.
|
||||||
|
#
|
||||||
|
# "allocate" - Remove the faulty device and try to allocate space on
|
||||||
|
# a new device to be a replacement for the failed device.
|
||||||
|
# Using this policy for the log is fast and maintains the
|
||||||
|
# ability to remember sync state through crashes/reboots.
|
||||||
|
# Using this policy for a mirror device is slow, as it
|
||||||
|
# requires the mirror to resynchronize the devices, but it
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
mirror_log_fault_policy = "allocate"
|
||||||
|
mirror_device_fault_policy = "remove"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Advanced section #
|
||||||
|
####################
|
||||||
|
|
||||||
|
# Metadata settings
|
||||||
|
#
|
||||||
|
# metadata {
|
||||||
|
# Default number of copies of metadata to hold on each PV. 0, 1 or 2.
|
||||||
|
# You might want to override it from the command line with 0
|
||||||
|
# when running pvcreate on new PVs which are to be added to large VGs.
|
||||||
|
|
||||||
|
# pvmetadatacopies = 1
|
||||||
|
|
||||||
|
# Approximate default size of on-disk metadata areas in sectors.
|
||||||
|
# You should increase this if you have large volume groups or
|
||||||
|
# you want to retain a large on-disk history of your metadata changes.
|
||||||
|
|
||||||
|
# pvmetadatasize = 255
|
||||||
|
|
||||||
|
# List of directories holding live copies of text format metadata.
|
||||||
|
# These directories must not be on logical volumes!
|
||||||
|
# It's possible to use LVM2 with a couple of directories here,
|
||||||
|
# preferably on different (non-LV) filesystems, and with no other
|
||||||
|
# on-disk metadata (pvmetadatacopies = 0). Or this can be in
|
||||||
|
# addition to on-disk metadata areas.
|
||||||
|
# The feature was originally added to simplify testing and is not
|
||||||
|
# supported under low memory situations - the machine could lock up.
|
||||||
|
#
|
||||||
|
# Never edit any files in these directories by hand unless you
|
||||||
|
# you are absolutely sure you know what you are doing! Use
|
||||||
|
# the supplied toolset to make changes (e.g. vgcfgrestore).
|
||||||
|
|
||||||
|
# dirs = [ "/etc/lvm/metadata", "/mnt/disk2/lvm/metadata2" ]
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Event daemon
|
||||||
|
#
|
||||||
|
# dmeventd {
|
||||||
|
# mirror_library is the library used when monitoring a mirror device.
|
||||||
|
#
|
||||||
|
# "libdevmapper-event-lvm2mirror.so" attempts to recover from failures.
|
||||||
|
# It removes failed devices from a volume group and reconfigures a
|
||||||
|
# mirror as necessary.
|
||||||
|
#
|
||||||
|
# mirror_library = "libdevmapper-event-lvm2mirror.so"
|
||||||
|
#}
|
||||||
|
|
||||||
47
doc/example_cmdlib.c
Normal file
47
doc/example_cmdlib.c
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
/* Extract and process output here rather than printing it */
|
||||||
|
|
||||||
|
if (level != 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf("%s\n", format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
void *handle;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
lvm2_log_fn(test_log_fn);
|
||||||
|
|
||||||
|
handle = lvm2_init();
|
||||||
|
|
||||||
|
lvm2_log_level(handle, 1);
|
||||||
|
r = lvm2_run(handle, "vgs --noheadings vg1");
|
||||||
|
|
||||||
|
/* More commands here */
|
||||||
|
|
||||||
|
lvm2_exit(handle);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
52
doc/pvmove_outline.txt
Normal file
52
doc/pvmove_outline.txt
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
Let's say we have an LV, made up of three segments of different PV's,
|
||||||
|
I've also added in the device major:minor as this will be useful
|
||||||
|
later:
|
||||||
|
|
||||||
|
+-----------------------------+
|
||||||
|
| PV1 | PV2 | PV3 | 254:3
|
||||||
|
+----------+---------+--------+
|
||||||
|
|
||||||
|
|
||||||
|
Now our hero decides to PV move PV2 to PV4:
|
||||||
|
|
||||||
|
1. Suspend our LV (254:3), this starts queueing all io, and flushes
|
||||||
|
all pending io. Once the suspend has completed we are free to change
|
||||||
|
the mapping table.
|
||||||
|
|
||||||
|
2. Set up *another* (254:4) device with the mapping table of our LV.
|
||||||
|
|
||||||
|
3. Load a new mapping table into (254:3) that has identity targets for
|
||||||
|
parts that aren't moving, and a mirror target for parts that are.
|
||||||
|
|
||||||
|
4. Unsuspend (254:3)
|
||||||
|
|
||||||
|
So now we have:
|
||||||
|
destination of copy
|
||||||
|
+--------------------->--------------+
|
||||||
|
| |
|
||||||
|
+-----------------------------+ + -----------+
|
||||||
|
| Identity | mirror | Ident. | 254:3 | PV4 |
|
||||||
|
+----------+---------+--------+ +------------+
|
||||||
|
| | |
|
||||||
|
\/ \/ \/
|
||||||
|
+-----------------------------+
|
||||||
|
| PV1 | PV2 | PV3 | 254:4
|
||||||
|
+----------+---------+--------+
|
||||||
|
|
||||||
|
Any writes to segment2 of the LV get intercepted by the mirror target
|
||||||
|
who checks that that chunk has been copied to the new destination, if
|
||||||
|
it hasn't it queues the initial copy and defers the current io until
|
||||||
|
it has finished. Then the current io is written to *both* PV2 and the
|
||||||
|
PV4.
|
||||||
|
|
||||||
|
5. When the copying has completed 254:3 is suspended/pending flushed.
|
||||||
|
|
||||||
|
6. 254:4 is taken down
|
||||||
|
|
||||||
|
7. metadata is updated on disk
|
||||||
|
|
||||||
|
8. 254:3 has new mapping table loaded:
|
||||||
|
|
||||||
|
+-----------------------------+
|
||||||
|
| PV1 | PV4 | PV3 | 254:3
|
||||||
|
+----------+---------+--------+
|
||||||
165
doc/tagging.txt
Normal file
165
doc/tagging.txt
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
Tagging aims
|
||||||
|
============
|
||||||
|
1) Ability to attach an unordered list of tags to LVM metadata objects.
|
||||||
|
2) Ability to add or remove tags easily.
|
||||||
|
3) Ability to select LVM objects for processing according to presence/absence
|
||||||
|
of specific tags.
|
||||||
|
4) Ability to control through the config file which VGs/LVs are activated
|
||||||
|
on different machines using names or tags.
|
||||||
|
5) Ability to overlay settings from different config files e.g. override
|
||||||
|
some settings in a global config file locally.
|
||||||
|
|
||||||
|
Clarifications
|
||||||
|
==============
|
||||||
|
1) Tag character set: A-Za-z0-9_+.-
|
||||||
|
Can't start with hyphen & max length is 128 (NAME_LEN).
|
||||||
|
2) LVM object types that can be tagged:
|
||||||
|
VG, LV, LV segment
|
||||||
|
PV - tags are stored in VG metadata so disappear when PV becomes orphaned
|
||||||
|
Snapshots can't be tagged, but their origin may be.
|
||||||
|
3) A tag can be used in place of any command line LVM object reference that
|
||||||
|
accepts (a) a list of objects; or (b) a single object as long as the
|
||||||
|
tag expands to a single object. This is not supported everywhere yet.
|
||||||
|
Duplicate arguments in a list after argument expansion may get removed
|
||||||
|
retaining the first copy of each argument.
|
||||||
|
4) Wherever there may be ambiguity of argument type, a tag must be prefixed
|
||||||
|
by '@'; elsewhere an '@' prefix is optional.
|
||||||
|
5) LVM1 objects cannot be tagged, as the disk format doesn't support it.
|
||||||
|
6) Tags can be added or removed with --addtag or --deltag.
|
||||||
|
|
||||||
|
Config file Extensions
|
||||||
|
======================
|
||||||
|
To define host tags in config file:
|
||||||
|
|
||||||
|
tags {
|
||||||
|
# Set a tag with the hostname
|
||||||
|
hosttags = 1
|
||||||
|
|
||||||
|
tag1 { }
|
||||||
|
|
||||||
|
tag2 {
|
||||||
|
# If no exact match, tag is not set.
|
||||||
|
host_list = [ "hostname", "dbase" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Activation config file example
|
||||||
|
==============================
|
||||||
|
activation {
|
||||||
|
volume_list = [ "vg1/lvol0", "@database" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
Matches against vgname, vgname/lvname or @tag set in *metadata*.
|
||||||
|
@* matches exactly against *any* tag set on the host.
|
||||||
|
The VG or LV only gets activated if a metadata tag matches.
|
||||||
|
The default if there is no match is not to activate.
|
||||||
|
If volume_list is not present and any tags are defined on the host
|
||||||
|
then it only activates if a host tag matches a metadata tag.
|
||||||
|
If volume_list is not present and no tags are defined on the host
|
||||||
|
then it does activate.
|
||||||
|
|
||||||
|
Multiple config files
|
||||||
|
=====================
|
||||||
|
(a) lvm.conf
|
||||||
|
(b) lvm_<host_tag>.conf
|
||||||
|
|
||||||
|
At startup, load lvm.conf.
|
||||||
|
Process tag settings.
|
||||||
|
If any host tags were defined, load lvm_tag.conf for each tag, if present.
|
||||||
|
|
||||||
|
When searching for a specific config file entry, search order is (b)
|
||||||
|
then (a), stopping at the first match.
|
||||||
|
Within (b) use reverse order tags got set, so file for last tag set is
|
||||||
|
searched first.
|
||||||
|
New tags set in (b) *do* trigger additional config file loads.
|
||||||
|
|
||||||
|
Usage Examples
|
||||||
|
==============
|
||||||
|
1) Simple activation control via metadata with static config files
|
||||||
|
|
||||||
|
lvm.conf: (Identical on every machine - global settings)
|
||||||
|
tags {
|
||||||
|
hostname_tags = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
From any machine in the cluster, add db1 to the list of machines that
|
||||||
|
activate vg1/lvol2:
|
||||||
|
|
||||||
|
lvchange --tag @db1 vg1/lvol2
|
||||||
|
(followed by lvchange -ay to actually activate it)
|
||||||
|
|
||||||
|
|
||||||
|
2) Multiple hosts.
|
||||||
|
|
||||||
|
Activate vg1 only on the database hosts, db1 and db2.
|
||||||
|
Activate vg2 only on the fileserver host fs1.
|
||||||
|
Activate nothing initially on the fileserver backup host fsb1, but be
|
||||||
|
prepared for it to take over from fs1.
|
||||||
|
|
||||||
|
Option (i) - centralised admin, static configuration replicated between hosts
|
||||||
|
# Add @database tag to vg1's metadata
|
||||||
|
vgchange --tag @database vg1
|
||||||
|
|
||||||
|
# Add @fileserver tag to vg2's metadata
|
||||||
|
vgchange --tag @fileserver vg2
|
||||||
|
|
||||||
|
lvm.conf: (Identical on every machine)
|
||||||
|
tags {
|
||||||
|
database {
|
||||||
|
host_list = [ "db1", "db2" ]
|
||||||
|
}
|
||||||
|
fileserver {
|
||||||
|
host_list = [ "fs1" ]
|
||||||
|
}
|
||||||
|
fileserverbackup {
|
||||||
|
host_list = [ "fsb1" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activation {
|
||||||
|
# Only activate if host has a tag that matches a metadata tag
|
||||||
|
volume_list = [ "@*" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
In the event of the fileserver host going down, vg2 can be brought up
|
||||||
|
on fsb1 by running *on any node* 'vgchange --tag @fileserverbackup vg2'
|
||||||
|
followed by 'vgchange -ay vg2'
|
||||||
|
|
||||||
|
|
||||||
|
Option (ii) - localised admin & configuation
|
||||||
|
(i.e. each host holds *locally* which classes of volumes to activate)
|
||||||
|
# Add @database tag to vg1's metadata
|
||||||
|
vgchange --tag @database vg1
|
||||||
|
|
||||||
|
# Add @fileserver tag to vg2's metadata
|
||||||
|
vgchange --tag @fileserver vg2
|
||||||
|
|
||||||
|
lvm.conf: (Identical on every machine - global settings)
|
||||||
|
tags {
|
||||||
|
hosttags = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
lvm_db1.conf: (only needs to be on db1 - could be symlink to lvm_db.conf)
|
||||||
|
activation {
|
||||||
|
volume_list = [ "@database" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
lvm_db2.conf: (only needs to be on db2 - could be symlink to lvm_db.conf)
|
||||||
|
activation {
|
||||||
|
volume_list = [ "@database" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
lvm_fs1.conf: (only needs to be on fs1 - could be symlink to lvm_fs.conf)
|
||||||
|
activation {
|
||||||
|
volume_list = [ "@fileserver" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
If fileserver goes down, to bring a spare machine fsb1 in as fileserver,
|
||||||
|
create lvm_fsb1.conf on fsb1 (or symlink to lvm_fs.conf):
|
||||||
|
|
||||||
|
activation {
|
||||||
|
volume_list = [ "@fileserver" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
and run 'vgchange -ay vg2' or 'vgchange -ay @fileserver'
|
||||||
|
|
||||||
46
doc/testing.txt
Normal file
46
doc/testing.txt
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
Here's how I test new LVM2 builds without interfering with the stable
|
||||||
|
LVM2 that is running the LV's on my development box.
|
||||||
|
|
||||||
|
1) Create a set of loopback devices.
|
||||||
|
|
||||||
|
2) Create a new directory to contain the LVM2 configuration files for
|
||||||
|
this setup. (I use /etc/lvm_loops)
|
||||||
|
|
||||||
|
3) Write a suitable lvm.conf file, this goes in the directory you just
|
||||||
|
created. eg, my /etc/lvm_loops/lvm.conf looks like:
|
||||||
|
|
||||||
|
log {
|
||||||
|
file="/tmp/lvm2_loop.log"
|
||||||
|
level=9
|
||||||
|
verbose=0
|
||||||
|
overwrite=1
|
||||||
|
}
|
||||||
|
|
||||||
|
devices {
|
||||||
|
scan = "/dev"
|
||||||
|
filter = ["a/loop/", "r/.*/"]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
The important this to note is the devices section which makes sure that
|
||||||
|
only the loopback devices are considered for LVM2 operations.
|
||||||
|
|
||||||
|
4) When you want to use this test setup just set the environment
|
||||||
|
variable LVM_SYSTEM_DIR to point to your config directory
|
||||||
|
(/etc/lvm_loops in my case).
|
||||||
|
|
||||||
|
5) It's a good idea to do a vgscan to initialise the filters:
|
||||||
|
|
||||||
|
export LVM_SYSTEM_DIR=/etc/lvm_loops
|
||||||
|
./lvm vgscan
|
||||||
|
|
||||||
|
where ./lvm is the new build of LVM2 that I'm trying out.
|
||||||
|
|
||||||
|
7) Test away. Make sure that you are explicit about which lvm
|
||||||
|
executable you want to execute (eg, ./lvm if you are in
|
||||||
|
LVM2/tools).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
The driver directory
|
|
||||||
50
include/.symlinks
Normal file
50
include/.symlinks
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
../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/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/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/regex/matcher.h
|
||||||
|
../lib/report/report.h
|
||||||
|
../lib/uuid/uuid.h
|
||||||
|
../po/pogen.h
|
||||||
|
../tools/version.h
|
||||||
45
include/Makefile.in
Normal file
45
include/Makefile.in
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004 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
|
||||||
|
|
||||||
|
SHELL = /bin/sh
|
||||||
|
|
||||||
|
srcdir = @srcdir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
LN_S = @LN_S@
|
||||||
|
|
||||||
|
.PHONY: clean distclean all install pofile install_cluster
|
||||||
|
|
||||||
|
all: .symlinks_created
|
||||||
|
|
||||||
|
.symlinks_created: .symlinks
|
||||||
|
find . -maxdepth 1 -type l -exec $(RM) \{\} \;
|
||||||
|
for i in `cat .symlinks`; do $(LN_S) $$i ; done
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
distclean:
|
||||||
|
find . -maxdepth 1 -type l -exec $(RM) \{\} \;
|
||||||
|
$(RM) Makefile .include_symlinks .symlinks_created
|
||||||
|
|
||||||
|
pofile: all
|
||||||
|
|
||||||
|
clean:
|
||||||
|
|
||||||
|
install:
|
||||||
|
|
||||||
|
install_cluster:
|
||||||
|
|
||||||
|
cflow:
|
||||||
|
|
||||||
157
lib/Makefile.in
Normal file
157
lib/Makefile.in
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
# Copyright (C) 2004-2005 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@
|
||||||
|
|
||||||
|
ifeq ("@LVM1@", "shared")
|
||||||
|
SUBDIRS = format1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@POOL@", "shared")
|
||||||
|
SUBDIRS += format_pool
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@SNAPSHOTS@", "shared")
|
||||||
|
SUBDIRS += snapshot
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@MIRRORS@", "shared")
|
||||||
|
SUBDIRS += mirror
|
||||||
|
endif
|
||||||
|
|
||||||
|
SOURCES =\
|
||||||
|
activate/activate.c \
|
||||||
|
cache/lvmcache.c \
|
||||||
|
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/device.c \
|
||||||
|
display/display.c \
|
||||||
|
error/errseg.c \
|
||||||
|
filters/filter-composite.c \
|
||||||
|
filters/filter-persistent.c \
|
||||||
|
filters/filter-regex.c \
|
||||||
|
filters/filter-sysfs.c \
|
||||||
|
filters/filter-md.c \
|
||||||
|
filters/filter.c \
|
||||||
|
format_text/archive.c \
|
||||||
|
format_text/archiver.c \
|
||||||
|
format_text/export.c \
|
||||||
|
format_text/flags.c \
|
||||||
|
format_text/format-text.c \
|
||||||
|
format_text/import.c \
|
||||||
|
format_text/import_vsn1.c \
|
||||||
|
format_text/tags.c \
|
||||||
|
format_text/text_label.c \
|
||||||
|
label/label.c \
|
||||||
|
locking/file_locking.c \
|
||||||
|
locking/locking.c \
|
||||||
|
locking/no_locking.c \
|
||||||
|
log/log.c \
|
||||||
|
metadata/lv_manip.c \
|
||||||
|
metadata/merge.c \
|
||||||
|
metadata/metadata.c \
|
||||||
|
metadata/mirror.c \
|
||||||
|
metadata/pv_manip.c \
|
||||||
|
metadata/pv_map.c \
|
||||||
|
metadata/segtype.c \
|
||||||
|
metadata/snapshot_manip.c \
|
||||||
|
misc/crc.c \
|
||||||
|
misc/lvm-exec.c \
|
||||||
|
misc/lvm-file.c \
|
||||||
|
misc/lvm-string.c \
|
||||||
|
misc/lvm-wrappers.c \
|
||||||
|
misc/timestamp.c \
|
||||||
|
mm/memlock.c \
|
||||||
|
regex/matcher.c \
|
||||||
|
regex/parse_rx.c \
|
||||||
|
regex/ttree.c \
|
||||||
|
report/report.c \
|
||||||
|
striped/striped.c \
|
||||||
|
uuid/uuid.c \
|
||||||
|
zero/zero.c
|
||||||
|
|
||||||
|
ifeq ("@LVM1@", "internal")
|
||||||
|
SOURCES +=\
|
||||||
|
format1/disk-rep.c \
|
||||||
|
format1/format1.c \
|
||||||
|
format1/import-export.c \
|
||||||
|
format1/import-extents.c \
|
||||||
|
format1/layout.c \
|
||||||
|
format1/lvm1-label.c \
|
||||||
|
format1/vg_number.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@POOL@", "internal")
|
||||||
|
SOURCES +=\
|
||||||
|
format_pool/disk_rep.c \
|
||||||
|
format_pool/format_pool.c \
|
||||||
|
format_pool/import_export.c \
|
||||||
|
format_pool/pool_label.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@CLUSTER@", "internal")
|
||||||
|
SOURCES += locking/cluster_locking.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@CLUSTER@", "shared")
|
||||||
|
SUBDIRS += locking
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@SNAPSHOTS@", "internal")
|
||||||
|
SOURCES += snapshot/snapshot.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@MIRRORS@", "internal")
|
||||||
|
SOURCES += mirror/mirrored.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@DEVMAPPER@", "yes")
|
||||||
|
SOURCES +=\
|
||||||
|
activate/dev_manager.c \
|
||||||
|
activate/fs.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@HAVE_LIBDL@", "yes")
|
||||||
|
SOURCES +=\
|
||||||
|
locking/external_locking.c \
|
||||||
|
misc/sharedlib.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@DMEVENTD@", "yes")
|
||||||
|
CLDFLAGS += -ldevmapper-event
|
||||||
|
endif
|
||||||
|
|
||||||
|
LIB_STATIC = liblvm.a
|
||||||
|
|
||||||
|
$(SUBDIRS): $(LIB_STATIC)
|
||||||
|
|
||||||
|
CLEAN_TARGETS += liblvm.cflow
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
liblvm.cflow: $(SOURCES)
|
||||||
|
set -e; (echo -n "SOURCES += "; \
|
||||||
|
echo $(SOURCES) | \
|
||||||
|
sed "s/^/ /;s/ / $(top_srcdir)\/lib\//g;s/$$//"; \
|
||||||
|
) > $@
|
||||||
|
|
||||||
|
cflow: liblvm.cflow
|
||||||
@@ -1 +0,0 @@
|
|||||||
Base library directory
|
|
||||||
1033
lib/activate/activate.c
Normal file
1033
lib/activate/activate.c
Normal file
File diff suppressed because it is too large
Load Diff
104
lib/activate/activate.h
Normal file
104
lib/activate/activate.h
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LVM_ACTIVATE_H
|
||||||
|
#define LVM_ACTIVATE_H
|
||||||
|
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
struct lvinfo {
|
||||||
|
int exists;
|
||||||
|
int suspended;
|
||||||
|
unsigned int open_count;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
int read_only;
|
||||||
|
int live_table;
|
||||||
|
int inactive_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_activation(int activation);
|
||||||
|
int activation(void);
|
||||||
|
|
||||||
|
int driver_version(char *version, size_t size);
|
||||||
|
int library_version(char *version, size_t size);
|
||||||
|
int lvm1_present(struct cmd_context *cmd);
|
||||||
|
|
||||||
|
int target_present(const char *target_name, int use_modprobe);
|
||||||
|
int 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);
|
||||||
|
int list_lv_modules(struct dm_pool *mem, const struct logical_volume *lv,
|
||||||
|
struct list *modules);
|
||||||
|
|
||||||
|
void activation_release(void);
|
||||||
|
void activation_exit(void);
|
||||||
|
|
||||||
|
int lv_suspend(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
int lv_resume(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive);
|
||||||
|
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||||
|
int exclusive);
|
||||||
|
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
|
||||||
|
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns 1 if info structure has been populated, else 0.
|
||||||
|
*/
|
||||||
|
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
|
||||||
|
int with_open_count);
|
||||||
|
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||||
|
struct lvinfo *info, int with_open_count);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
|
||||||
|
*/
|
||||||
|
int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
||||||
|
int *activate_lv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns 1 if percent has been set, else 0.
|
||||||
|
*/
|
||||||
|
int lv_snapshot_percent(const struct logical_volume *lv, float *percent);
|
||||||
|
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv,
|
||||||
|
int wait, float *percent, uint32_t *event_nr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return number of LVs in the VG that are active.
|
||||||
|
*/
|
||||||
|
int lvs_in_vg_activated(struct volume_group *vg);
|
||||||
|
int lvs_in_vg_activated_by_uuid_only(struct volume_group *vg);
|
||||||
|
int lvs_in_vg_opened(struct volume_group *vg);
|
||||||
|
|
||||||
|
|
||||||
|
int monitor_dev_for_events(struct cmd_context *cmd,
|
||||||
|
struct logical_volume *lv, int do_reg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns 1 if PV has a dependency tree that uses anything in VG.
|
||||||
|
*/
|
||||||
|
int pv_uses_vg(struct physical_volume *pv,
|
||||||
|
struct volume_group *vg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns 1 if mapped device is not suspended.
|
||||||
|
*/
|
||||||
|
int device_is_usable(dev_t dev);
|
||||||
|
|
||||||
|
#endif
|
||||||
1149
lib/activate/dev_manager.c
Normal file
1149
lib/activate/dev_manager.c
Normal file
File diff suppressed because it is too large
Load Diff
67
lib/activate/dev_manager.h
Normal file
67
lib/activate/dev_manager.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_DEV_MANAGER_H
|
||||||
|
#define _LVM_DEV_MANAGER_H
|
||||||
|
|
||||||
|
struct logical_volume;
|
||||||
|
struct volume_group;
|
||||||
|
struct cmd_context;
|
||||||
|
struct dev_manager;
|
||||||
|
struct dm_info;
|
||||||
|
struct device;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructor and destructor.
|
||||||
|
*/
|
||||||
|
struct dev_manager *dev_manager_create(struct cmd_context *cmd,
|
||||||
|
const char *vg_name);
|
||||||
|
void dev_manager_destroy(struct dev_manager *dm);
|
||||||
|
void dev_manager_release(void);
|
||||||
|
void dev_manager_exit(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The device handler is responsible for creating all the layered
|
||||||
|
* dm devices, and ensuring that all constraints are maintained
|
||||||
|
* (eg, an origin is created before its snapshot, but is not
|
||||||
|
* unsuspended until the snapshot is also created.)
|
||||||
|
*/
|
||||||
|
int dev_manager_info(struct dm_pool *mem, const char *name,
|
||||||
|
const struct logical_volume *lv,
|
||||||
|
int mknodes, int with_open_count, struct dm_info *info);
|
||||||
|
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||||
|
const struct logical_volume *lv,
|
||||||
|
float *percent);
|
||||||
|
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||||
|
struct logical_volume *lv, int wait,
|
||||||
|
float *percent, uint32_t *event_nr);
|
||||||
|
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv,
|
||||||
|
int lockfs);
|
||||||
|
int 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_deactivate(struct dev_manager *dm, struct logical_volume *lv);
|
||||||
|
|
||||||
|
int dev_manager_lv_mknodes(const struct logical_volume *lv);
|
||||||
|
int dev_manager_lv_rmnodes(const struct logical_volume *lv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put the desired changes into effect.
|
||||||
|
*/
|
||||||
|
int dev_manager_execute(struct dev_manager *dm);
|
||||||
|
|
||||||
|
int dev_manager_device_uses_vg(struct device *dev,
|
||||||
|
struct volume_group *vg);
|
||||||
|
|
||||||
|
#endif
|
||||||
354
lib/activate/fs.c
Normal file
354
lib/activate/fs.c
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "fs.h"
|
||||||
|
#include "toolcontext.h"
|
||||||
|
#include "lvm-string.h"
|
||||||
|
#include "lvm-file.h"
|
||||||
|
#include "memlock.h"
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
static int _mk_dir(const char *dev_dir, const char *vg_name)
|
||||||
|
{
|
||||||
|
char vg_path[PATH_MAX];
|
||||||
|
|
||||||
|
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||||
|
dev_dir, vg_name) == -1) {
|
||||||
|
log_error("Couldn't construct name of volume "
|
||||||
|
"group directory.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir_exists(vg_path))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
log_very_verbose("Creating directory %s", vg_path);
|
||||||
|
if (mkdir(vg_path, 0777)) {
|
||||||
|
log_sys_error("mkdir", vg_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _rm_dir(const char *dev_dir, const char *vg_name)
|
||||||
|
{
|
||||||
|
char vg_path[PATH_MAX];
|
||||||
|
|
||||||
|
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||||
|
dev_dir, vg_name) == -1) {
|
||||||
|
log_error("Couldn't construct name of volume "
|
||||||
|
"group directory.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
|
||||||
|
log_very_verbose("Removing directory %s", vg_path);
|
||||||
|
rmdir(vg_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _rm_blks(const char *dir)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
struct dirent *dirent;
|
||||||
|
struct stat buf;
|
||||||
|
DIR *d;
|
||||||
|
|
||||||
|
if (!(d = opendir(dir))) {
|
||||||
|
log_sys_error("opendir", dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((dirent = readdir(d))) {
|
||||||
|
name = dirent->d_name;
|
||||||
|
|
||||||
|
if (!strcmp(name, ".") || !strcmp(name, ".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
|
||||||
|
log_error("Couldn't create path for %s", name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lstat(path, &buf)) {
|
||||||
|
if (!S_ISBLK(buf.st_mode))
|
||||||
|
continue;
|
||||||
|
log_very_verbose("Removing %s", path);
|
||||||
|
if (unlink(path) < 0)
|
||||||
|
log_sys_error("unlink", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||||
|
const char *lv_name, const char *dev)
|
||||||
|
{
|
||||||
|
char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX];
|
||||||
|
char vg_path[PATH_MAX];
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
|
||||||
|
dev_dir, vg_name) == -1) {
|
||||||
|
log_error("Couldn't create path for volume group dir %s",
|
||||||
|
vg_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
|
||||||
|
lv_name) == -1) {
|
||||||
|
log_error("Couldn't create source pathname for "
|
||||||
|
"logical volume link %s", lv_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dm_snprintf(link_path, sizeof(link_path), "%s/%s",
|
||||||
|
dm_dir(), dev) == -1) {
|
||||||
|
log_error("Couldn't create destination pathname for "
|
||||||
|
"logical volume link for %s", lv_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
|
||||||
|
vg_path) == -1) {
|
||||||
|
log_error("Couldn't create pathname for LVM1 group file for %s",
|
||||||
|
vg_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To reach this point, the VG must have been locked.
|
||||||
|
* As locking fails if the VG is active under LVM1, it's
|
||||||
|
* now safe to remove any LVM1 devices we find here
|
||||||
|
* (as well as any existing LVM2 symlink). */
|
||||||
|
if (!lstat(lvm1_group_path, &buf)) {
|
||||||
|
if (!S_ISCHR(buf.st_mode)) {
|
||||||
|
log_error("Non-LVM1 character device found at %s",
|
||||||
|
lvm1_group_path);
|
||||||
|
} else {
|
||||||
|
_rm_blks(vg_path);
|
||||||
|
|
||||||
|
log_very_verbose("Removing %s", lvm1_group_path);
|
||||||
|
if (unlink(lvm1_group_path) < 0)
|
||||||
|
log_sys_error("unlink", lvm1_group_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lstat(lv_path, &buf)) {
|
||||||
|
if (!S_ISLNK(buf.st_mode) && !S_ISBLK(buf.st_mode)) {
|
||||||
|
log_error("Symbolic link %s not created: file exists",
|
||||||
|
link_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_very_verbose("Removing %s", lv_path);
|
||||||
|
if (unlink(lv_path) < 0) {
|
||||||
|
log_sys_error("unlink", lv_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_very_verbose("Linking %s -> %s", lv_path, link_path);
|
||||||
|
if (symlink(link_path, lv_path) < 0) {
|
||||||
|
log_sys_error("symlink", lv_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
if (!dm_set_selinux_context(lv_path, S_IFLNK)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _rm_link(const char *dev_dir, const char *vg_name,
|
||||||
|
const char *lv_name)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
char lv_path[PATH_MAX];
|
||||||
|
|
||||||
|
if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
|
||||||
|
dev_dir, vg_name, lv_name) == -1) {
|
||||||
|
log_error("Couldn't determine link pathname.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
|
||||||
|
if (errno == ENOENT)
|
||||||
|
return 1;
|
||||||
|
log_error("%s not symbolic link - not removing", lv_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_very_verbose("Removing link %s", lv_path);
|
||||||
|
if (unlink(lv_path) < 0) {
|
||||||
|
log_sys_error("unlink", lv_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FS_ADD,
|
||||||
|
FS_DEL,
|
||||||
|
FS_RENAME
|
||||||
|
} fs_op_t;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case FS_ADD:
|
||||||
|
if (!_mk_dir(dev_dir, vg_name) ||
|
||||||
|
!_mk_link(dev_dir, vg_name, lv_name, dev)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FS_DEL:
|
||||||
|
if (!_rm_link(dev_dir, vg_name, lv_name) ||
|
||||||
|
!_rm_dir(dev_dir, vg_name)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
/* FIXME Use rename() */
|
||||||
|
case FS_RENAME:
|
||||||
|
if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
if (!_mk_link(dev_dir, vg_name, lv_name, dev))
|
||||||
|
stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LIST_INIT(_fs_ops);
|
||||||
|
|
||||||
|
struct fs_op_parms {
|
||||||
|
struct list list;
|
||||||
|
fs_op_t type;
|
||||||
|
char *dev_dir;
|
||||||
|
char *vg_name;
|
||||||
|
char *lv_name;
|
||||||
|
char *dev;
|
||||||
|
char *old_lv_name;
|
||||||
|
char names[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _store_str(char **pos, char **ptr, const char *str)
|
||||||
|
{
|
||||||
|
strcpy(*pos, str);
|
||||||
|
*ptr = *pos;
|
||||||
|
*pos += strlen(*ptr) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct fs_op_parms *fsp;
|
||||||
|
size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) +
|
||||||
|
strlen(dev) + strlen(old_lv_name) + 5;
|
||||||
|
char *pos;
|
||||||
|
|
||||||
|
if (!(fsp = dm_malloc(sizeof(*fsp) + len))) {
|
||||||
|
log_error("No space to stack fs operation");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = fsp->names;
|
||||||
|
fsp->type = type;
|
||||||
|
|
||||||
|
_store_str(&pos, &fsp->dev_dir, dev_dir);
|
||||||
|
_store_str(&pos, &fsp->vg_name, vg_name);
|
||||||
|
_store_str(&pos, &fsp->lv_name, lv_name);
|
||||||
|
_store_str(&pos, &fsp->dev, dev);
|
||||||
|
_store_str(&pos, &fsp->old_lv_name, old_lv_name);
|
||||||
|
|
||||||
|
list_add(&_fs_ops, &fsp->list);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _pop_fs_ops(void)
|
||||||
|
{
|
||||||
|
struct list *fsph, *fspht;
|
||||||
|
struct fs_op_parms *fsp;
|
||||||
|
|
||||||
|
list_iterate_safe(fsph, fspht, &_fs_ops) {
|
||||||
|
fsp = list_item(fsph, struct fs_op_parms);
|
||||||
|
_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
|
||||||
|
fsp->dev, fsp->old_lv_name);
|
||||||
|
list_del(&fsp->list);
|
||||||
|
dm_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)
|
||||||
|
{
|
||||||
|
if (memlock()) {
|
||||||
|
if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
|
||||||
|
old_lv_name)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _do_fs_op(type, dev_dir, vg_name, lv_name, dev, old_lv_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_del_lv(const struct logical_volume *lv)
|
||||||
|
{
|
||||||
|
return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||||
|
"", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_rename_lv(struct logical_volume *lv,
|
||||||
|
const char *dev, const char *old_name)
|
||||||
|
{
|
||||||
|
return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
|
||||||
|
dev, old_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs_unlock(void)
|
||||||
|
{
|
||||||
|
if (!memlock()) {
|
||||||
|
dm_lib_release();
|
||||||
|
_pop_fs_ops();
|
||||||
|
}
|
||||||
|
}
|
||||||
32
lib/activate/fs.h
Normal file
32
lib/activate/fs.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_FS_H
|
||||||
|
#define _LVM_FS_H
|
||||||
|
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These calls, private to the activate unit, set
|
||||||
|
* up the volume group directory in /dev and the
|
||||||
|
* symbolic links to the dm device.
|
||||||
|
*/
|
||||||
|
int fs_add_lv(const struct logical_volume *lv, const char *dev);
|
||||||
|
int fs_del_lv(const struct logical_volume *lv);
|
||||||
|
int fs_rename_lv(struct logical_volume *lv,
|
||||||
|
const char *dev, const char *old_name);
|
||||||
|
void fs_unlock(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
34
lib/activate/targets.h
Normal file
34
lib/activate/targets.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_TARGETS_H
|
||||||
|
#define _LVM_TARGETS_H
|
||||||
|
|
||||||
|
struct dev_manager;
|
||||||
|
struct lv_segment;
|
||||||
|
|
||||||
|
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||||
|
char *params, size_t paramsize, int *pos,
|
||||||
|
int start_area, int areas);
|
||||||
|
|
||||||
|
int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||||
|
struct dm_tree_node *node, uint32_t start_area, uint32_t areas);
|
||||||
|
|
||||||
|
int build_dev_string(struct dev_manager *dm, char *dlid, char *devbuf,
|
||||||
|
size_t bufsize, const char *desc);
|
||||||
|
|
||||||
|
char *build_dlid(struct dev_manager *dm, const char *lvid, const char *layer);
|
||||||
|
|
||||||
|
#endif
|
||||||
901
lib/cache/lvmcache.c
vendored
Normal file
901
lib/cache/lvmcache.c
vendored
Normal file
@@ -0,0 +1,901 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "lvmcache.h"
|
||||||
|
#include "toolcontext.h"
|
||||||
|
#include "dev-cache.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "memlock.h"
|
||||||
|
#include "str_list.h"
|
||||||
|
|
||||||
|
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 int _has_scanned = 0;
|
||||||
|
static int _vgs_locked = 0;
|
||||||
|
|
||||||
|
int lvmcache_init(void)
|
||||||
|
{
|
||||||
|
list_init(&_vginfos);
|
||||||
|
|
||||||
|
if (!(_vgname_hash = dm_hash_create(128)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(_vgid_hash = dm_hash_create(128)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(_pvid_hash = dm_hash_create(128)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(_lock_hash = dm_hash_create(128)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lvmcache_lock_vgname(const char *vgname, int read_only __attribute((unused)))
|
||||||
|
{
|
||||||
|
if (!_lock_hash && !lvmcache_init()) {
|
||||||
|
log_error("Internal cache initialisation failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
|
||||||
|
log_error("Cache locking failure for %s", vgname);
|
||||||
|
|
||||||
|
_vgs_locked++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vgname_is_locked(const char *vgname)
|
||||||
|
{
|
||||||
|
if (!_lock_hash)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return dm_hash_lookup(_lock_hash, vgname) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lvmcache_unlock_vgname(const char *vgname)
|
||||||
|
{
|
||||||
|
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
|
||||||
|
dm_hash_remove(_lock_hash, vgname);
|
||||||
|
|
||||||
|
/* FIXME Do this per-VG */
|
||||||
|
if (!--_vgs_locked)
|
||||||
|
dev_close_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
int vgs_locked(void)
|
||||||
|
{
|
||||||
|
return _vgs_locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If vgid supplied, require a match. */
|
||||||
|
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid)
|
||||||
|
{
|
||||||
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
|
||||||
|
if (!_vgname_hash)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (vgid)
|
||||||
|
do
|
||||||
|
if (!strncmp(vgid, vginfo->vgid, ID_LEN))
|
||||||
|
return vginfo;
|
||||||
|
while ((vginfo = vginfo->next));
|
||||||
|
|
||||||
|
return vginfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 device_list *devl;
|
||||||
|
char vgid_found[ID_LEN + 1] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
if (!(devl = dm_malloc(sizeof(*devl)))) {
|
||||||
|
log_error("device_list element allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
devl->dev = info->dev;
|
||||||
|
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);
|
||||||
|
label_read(devl->dev, &label);
|
||||||
|
list_del(&devl->list);
|
||||||
|
dm_free(devl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If vginfo changed, caller needs to rescan */
|
||||||
|
if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) ||
|
||||||
|
strncmp(vginfo->vgid, vgid_found, ID_LEN))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return vginfo->fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
|
||||||
|
{
|
||||||
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
char id[ID_LEN + 1] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (!_vgid_hash || !vgid)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* vgid not necessarily NULL-terminated */
|
||||||
|
strncpy(&id[0], vgid, ID_LEN);
|
||||||
|
id[ID_LEN] = '\0';
|
||||||
|
|
||||||
|
if (!(vginfo = dm_hash_lookup(_vgid_hash, id)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return vginfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid)
|
||||||
|
{
|
||||||
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
const char *vgname = NULL;
|
||||||
|
|
||||||
|
if (!*vgid)
|
||||||
|
vgname = ORPHAN;
|
||||||
|
|
||||||
|
if ((vginfo = vginfo_from_vgid(vgid)))
|
||||||
|
vgname = vginfo->vgname;
|
||||||
|
|
||||||
|
if (mem && vgname)
|
||||||
|
return dm_pool_strdup(mem, vgname);
|
||||||
|
|
||||||
|
return vgname;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lvmcache_info *info_from_pvid(const char *pvid)
|
||||||
|
{
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
char id[ID_LEN + 1] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (!_pvid_hash || !pvid)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
strncpy(&id[0], pvid, ID_LEN);
|
||||||
|
id[ID_LEN] = '\0';
|
||||||
|
|
||||||
|
if (!(info = dm_hash_lookup(_pvid_hash, id)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _rescan_entry(struct lvmcache_info *info)
|
||||||
|
{
|
||||||
|
struct label *label;
|
||||||
|
|
||||||
|
if (info->status & CACHE_INVALID)
|
||||||
|
label_read(info->dev, &label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _scan_invalid(void)
|
||||||
|
{
|
||||||
|
dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _rescan_entry);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
||||||
|
{
|
||||||
|
struct label *label;
|
||||||
|
struct dev_iter *iter;
|
||||||
|
struct device *dev;
|
||||||
|
struct format_type *fmt;
|
||||||
|
|
||||||
|
static int _scanning_in_progress = 0;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
/* Avoid recursion when a PVID can't be found! */
|
||||||
|
if (_scanning_in_progress)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_scanning_in_progress = 1;
|
||||||
|
|
||||||
|
if (!_vgname_hash && !lvmcache_init()) {
|
||||||
|
log_error("Internal cache initialisation failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_has_scanned && !full_scan) {
|
||||||
|
r = _scan_invalid();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1 : 0))) {
|
||||||
|
log_error("dev_iter creation failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((dev = dev_iter_get(iter)))
|
||||||
|
label_read(dev, &label);
|
||||||
|
|
||||||
|
dev_iter_destroy(iter);
|
||||||
|
|
||||||
|
_has_scanned = 1;
|
||||||
|
|
||||||
|
/* Perform any format-specific scanning e.g. text files */
|
||||||
|
list_iterate_items(fmt, &cmd->formats) {
|
||||||
|
if (fmt->ops->scan && !fmt->ops->scan(fmt))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
_scanning_in_progress = 0;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan)
|
||||||
|
{
|
||||||
|
struct list *vgids;
|
||||||
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
|
||||||
|
lvmcache_label_scan(cmd, full_scan);
|
||||||
|
|
||||||
|
if (!(vgids = str_list_create(cmd->mem))) {
|
||||||
|
log_error("vgids list allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_iterate_items(vginfo, &_vginfos) {
|
||||||
|
if (!str_list_add(cmd->mem, vgids,
|
||||||
|
dm_pool_strdup(cmd->mem, vginfo->vgid))) {
|
||||||
|
log_error("strlist allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vgids;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
||||||
|
{
|
||||||
|
struct 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");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_iterate_items(vginfo, &_vginfos) {
|
||||||
|
if (!str_list_add(cmd->mem, vgnames,
|
||||||
|
dm_pool_strdup(cmd->mem, vginfo->vgname))) {
|
||||||
|
log_error("strlist allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vgnames;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||||
|
const char *vgid)
|
||||||
|
{
|
||||||
|
struct list *pvids;
|
||||||
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
|
if (!(pvids = str_list_create(cmd->mem))) {
|
||||||
|
log_error("pvids list allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(vginfo = vginfo_from_vgname(vgname, vgid)))
|
||||||
|
return pvids;
|
||||||
|
|
||||||
|
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");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pvids;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
||||||
|
{
|
||||||
|
struct label *label;
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
|
/* Already cached ? */
|
||||||
|
if ((info = info_from_pvid((char *) pvid))) {
|
||||||
|
if (label_read(info->dev, &label)) {
|
||||||
|
info = (struct lvmcache_info *) label->info;
|
||||||
|
if (id_equal(pvid, (struct id *) &info->dev->pvid))
|
||||||
|
return info->dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lvmcache_label_scan(cmd, 0);
|
||||||
|
|
||||||
|
/* Try again */
|
||||||
|
if ((info = info_from_pvid((char *) pvid))) {
|
||||||
|
if (label_read(info->dev, &label)) {
|
||||||
|
info = (struct lvmcache_info *) label->info;
|
||||||
|
if (id_equal(pvid, (struct id *) &info->dev->pvid))
|
||||||
|
return info->dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memlock())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
lvmcache_label_scan(cmd, 2);
|
||||||
|
|
||||||
|
/* Try again */
|
||||||
|
if ((info = info_from_pvid((char *) pvid))) {
|
||||||
|
if (label_read(info->dev, &label)) {
|
||||||
|
info = (struct lvmcache_info *) label->info;
|
||||||
|
if (id_equal(pvid, (struct id *) &info->dev->pvid))
|
||||||
|
return info->dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _drop_vginfo(struct lvmcache_info *info)
|
||||||
|
{
|
||||||
|
if (!list_empty(&info->list)) {
|
||||||
|
list_del(&info->list);
|
||||||
|
list_init(&info->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->vginfo && list_empty(&info->vginfo->infos)) {
|
||||||
|
dm_hash_remove(_vgname_hash, info->vginfo->vgname);
|
||||||
|
if (info->vginfo->next) {
|
||||||
|
if (!dm_hash_insert(_vgname_hash, info->vginfo->vgname, info->vginfo->next)) {
|
||||||
|
log_error("vg hash re-insertion failed: %s",
|
||||||
|
info->vginfo->vgname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->vginfo->vgname)
|
||||||
|
dm_free(info->vginfo->vgname);
|
||||||
|
if (info->vginfo->creation_host)
|
||||||
|
dm_free(info->vginfo->creation_host);
|
||||||
|
if (*info->vginfo->vgid)
|
||||||
|
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||||
|
list_del(&info->vginfo->list);
|
||||||
|
dm_free(info->vginfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
info->vginfo = NULL;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unused
|
||||||
|
void lvmcache_del(struct lvmcache_info *info)
|
||||||
|
{
|
||||||
|
if (info->dev->pvid[0] && _pvid_hash)
|
||||||
|
dm_hash_remove(_pvid_hash, info->dev->pvid);
|
||||||
|
|
||||||
|
_drop_vginfo(info);
|
||||||
|
|
||||||
|
info->label->labeller->ops->destroy_label(info->label->labeller,
|
||||||
|
info->label);
|
||||||
|
dm_free(info);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} */
|
||||||
|
|
||||||
|
static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
|
||||||
|
{
|
||||||
|
if (!strcmp(info->dev->pvid, pvid))
|
||||||
|
return 1;
|
||||||
|
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);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
|
||||||
|
{
|
||||||
|
if (!vgid || !info->vginfo ||
|
||||||
|
!strncmp(info->vginfo->vgid, vgid, ID_LEN))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (info->vginfo && *info->vginfo->vgid)
|
||||||
|
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||||
|
if (!vgid) {
|
||||||
|
log_debug("lvmcache: %s: clearing VGID", dev_name(info->dev));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(info->vginfo->vgid, vgid, ID_LEN);
|
||||||
|
info->vginfo->vgid[ID_LEN] = '\0';
|
||||||
|
if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
|
||||||
|
log_error("_lvmcache_update: vgid hash insertion failed: %s",
|
||||||
|
info->vginfo->vgid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev),
|
||||||
|
info->vginfo->vgname, info->vginfo->vgid);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
|
||||||
|
uint32_t vgstatus, const char *creation_host,
|
||||||
|
struct lvmcache_vginfo *primary_vginfo)
|
||||||
|
{
|
||||||
|
struct lvmcache_vginfo *last_vginfo = primary_vginfo;
|
||||||
|
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)))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
|
||||||
|
sizeof(uuid_primary)))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If Primary not exported, new exported => keep
|
||||||
|
* Else Primary exported, new not exported => change
|
||||||
|
* Else Primary has hostname for this machine => keep
|
||||||
|
* Else Primary has no hostname, new has one => change
|
||||||
|
* Else New has hostname for this machine => change
|
||||||
|
* Else Keep primary.
|
||||||
|
*/
|
||||||
|
if (!(primary_vginfo->status & EXPORTED_VG) &&
|
||||||
|
(vgstatus & EXPORTED_VG))
|
||||||
|
log_error("WARNING: Duplicate VG name %s: "
|
||||||
|
"Existing %s takes precedence over "
|
||||||
|
"exported %s", new_vginfo->vgname,
|
||||||
|
uuid_primary, uuid_new);
|
||||||
|
else if ((primary_vginfo->status & EXPORTED_VG) &&
|
||||||
|
!(vgstatus & EXPORTED_VG)) {
|
||||||
|
log_error("WARNING: Duplicate VG name %s: "
|
||||||
|
"%s takes precedence over exported %s",
|
||||||
|
new_vginfo->vgname, uuid_new,
|
||||||
|
uuid_primary);
|
||||||
|
use_new = 1;
|
||||||
|
} else if (primary_vginfo->creation_host &&
|
||||||
|
!strcmp(primary_vginfo->creation_host,
|
||||||
|
primary_vginfo->fmt->cmd->hostname))
|
||||||
|
log_error("WARNING: Duplicate VG name %s: "
|
||||||
|
"Existing %s (created here) takes precedence "
|
||||||
|
"over %s", new_vginfo->vgname, uuid_primary,
|
||||||
|
uuid_new);
|
||||||
|
else if (!primary_vginfo->creation_host && creation_host) {
|
||||||
|
log_error("WARNING: Duplicate VG name %s: "
|
||||||
|
"%s (with creation_host) takes precedence over %s",
|
||||||
|
new_vginfo->vgname, uuid_new,
|
||||||
|
uuid_primary);
|
||||||
|
use_new = 1;
|
||||||
|
} else if (creation_host &&
|
||||||
|
!strcmp(creation_host,
|
||||||
|
primary_vginfo->fmt->cmd->hostname)) {
|
||||||
|
log_error("WARNING: Duplicate VG name %s: "
|
||||||
|
"%s (created here) takes precedence over %s",
|
||||||
|
new_vginfo->vgname, uuid_new,
|
||||||
|
uuid_primary);
|
||||||
|
use_new = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!use_new) {
|
||||||
|
while (last_vginfo->next)
|
||||||
|
last_vginfo = last_vginfo->next;
|
||||||
|
last_vginfo->next = new_vginfo;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
|
||||||
|
log_error("cache_update: vg hash insertion failed: %s",
|
||||||
|
new_vginfo->vgname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primary_vginfo)
|
||||||
|
new_vginfo->next = primary_vginfo;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _lvmcache_update_vgname(struct lvmcache_info *info,
|
||||||
|
const char *vgname, const char *vgid,
|
||||||
|
uint32_t vgstatus, const char *creation_host)
|
||||||
|
{
|
||||||
|
struct lvmcache_vginfo *vginfo, *primary_vginfo;
|
||||||
|
// struct lvmcache_vginfo *old_vginfo, *next;
|
||||||
|
|
||||||
|
/* If vgname is NULL and we don't already have a vgname,
|
||||||
|
* assume ORPHAN - we want every entry to have a vginfo
|
||||||
|
* attached for scanning reasons.
|
||||||
|
*/
|
||||||
|
if (!vgname && !info->vginfo) {
|
||||||
|
vgname = ORPHAN;
|
||||||
|
vgid = ORPHAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Remove existing vginfo entry */
|
||||||
|
_drop_vginfo(info);
|
||||||
|
|
||||||
|
/* Get existing vginfo or create new one */
|
||||||
|
if (!(vginfo = vginfo_from_vgname(vgname, vgid))) {
|
||||||
|
/*** FIXME - vginfo ends up duplicated instead of renamed.
|
||||||
|
// Renaming? This lookup fails.
|
||||||
|
if ((vginfo = vginfo_from_vgid(vgid))) {
|
||||||
|
next = vginfo->next;
|
||||||
|
old_vginfo = vginfo_from_vgname(vginfo->vgname, NULL);
|
||||||
|
if (old_vginfo == vginfo) {
|
||||||
|
dm_hash_remove(_vgname_hash, old_vginfo->vgname);
|
||||||
|
if (old_vginfo->next) {
|
||||||
|
if (!dm_hash_insert(_vgname_hash, old_vginfo->vgname, old_vginfo->next)) {
|
||||||
|
log_error("vg hash re-insertion failed: %s",
|
||||||
|
old_vginfo->vgname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else do {
|
||||||
|
if (old_vginfo->next == vginfo) {
|
||||||
|
old_vginfo->next = vginfo->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((old_vginfo = old_vginfo->next));
|
||||||
|
vginfo->next = NULL;
|
||||||
|
|
||||||
|
dm_free(vginfo->vgname);
|
||||||
|
if (!(vginfo->vgname = dm_strdup(vgname))) {
|
||||||
|
log_error("cache vgname alloc failed for %s", vgname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename so can assume new name does not already exist
|
||||||
|
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo->next)) {
|
||||||
|
log_error("vg hash re-insertion failed: %s",
|
||||||
|
vginfo->vgname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
***/
|
||||||
|
if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
|
||||||
|
log_error("lvmcache_update_vgname: list alloc failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(vginfo, 0, sizeof(*vginfo));
|
||||||
|
if (!(vginfo->vgname = dm_strdup(vgname))) {
|
||||||
|
dm_free(vginfo);
|
||||||
|
log_error("cache vgname alloc failed for %s", vgname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
list_init(&vginfo->infos);
|
||||||
|
primary_vginfo = vginfo_from_vgname(vgname, NULL);
|
||||||
|
if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host,
|
||||||
|
primary_vginfo)) {
|
||||||
|
dm_free(vginfo->vgname);
|
||||||
|
dm_free(vginfo);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Ensure orphans appear last on list_iterate */
|
||||||
|
if (!*vgname)
|
||||||
|
list_add(&_vginfos, &vginfo->list);
|
||||||
|
else
|
||||||
|
list_add_h(&_vginfos, &vginfo->list);
|
||||||
|
/***
|
||||||
|
}
|
||||||
|
***/
|
||||||
|
}
|
||||||
|
|
||||||
|
info->vginfo = vginfo;
|
||||||
|
list_add(&vginfo->infos, &info->list);
|
||||||
|
|
||||||
|
/* FIXME Check consistency of list! */
|
||||||
|
vginfo->fmt = info->fmt;
|
||||||
|
|
||||||
|
log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev),
|
||||||
|
*vgname ? "in VG " : "orphaned", vgname,
|
||||||
|
vginfo->vgid[0] ? " (" : "",
|
||||||
|
vginfo->vgid[0] ? vginfo->vgid : "",
|
||||||
|
vginfo->vgid[0] ? ")" : "");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus,
|
||||||
|
const char *creation_host)
|
||||||
|
{
|
||||||
|
if (!info || !info->vginfo)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG))
|
||||||
|
log_debug("lvmcache: %s: VG %s %s exported",
|
||||||
|
dev_name(info->dev), info->vginfo->vgname,
|
||||||
|
vgstatus & EXPORTED_VG ? "now" : "no longer");
|
||||||
|
|
||||||
|
info->vginfo->status = vgstatus;
|
||||||
|
|
||||||
|
if (!creation_host)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (info->vginfo->creation_host && !strcmp(creation_host,
|
||||||
|
info->vginfo->creation_host))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (info->vginfo->creation_host)
|
||||||
|
dm_free(info->vginfo->creation_host);
|
||||||
|
|
||||||
|
if (!(info->vginfo->creation_host = dm_strdup(creation_host))) {
|
||||||
|
log_error("cache creation host alloc failed for %s",
|
||||||
|
creation_host);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("lvmcache: %s: VG %s: Set creation host to %s.",
|
||||||
|
dev_name(info->dev), info->vginfo->vgname, creation_host);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||||
|
const char *vgname, const char *vgid,
|
||||||
|
uint32_t vgstatus, const char *creation_host)
|
||||||
|
{
|
||||||
|
if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus,
|
||||||
|
creation_host) ||
|
||||||
|
!_lvmcache_update_vgid(info, vgid) ||
|
||||||
|
!_lvmcache_update_vgstatus(info, vgstatus, creation_host))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lvmcache_update_vg(struct volume_group *vg)
|
||||||
|
{
|
||||||
|
struct pv_list *pvl;
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||||
|
|
||||||
|
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)) &&
|
||||||
|
!lvmcache_update_vgname_and_id(info, vg->name,
|
||||||
|
(char *) &vg->id,
|
||||||
|
vg->status, NULL))
|
||||||
|
return_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||||
|
struct device *dev,
|
||||||
|
const char *vgname, const char *vgid,
|
||||||
|
uint32_t vgstatus)
|
||||||
|
{
|
||||||
|
struct label *label;
|
||||||
|
struct lvmcache_info *existing, *info;
|
||||||
|
char pvid_s[ID_LEN + 1] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (!_vgname_hash && !lvmcache_init()) {
|
||||||
|
log_error("Internal cache initialisation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(pvid_s, pvid, sizeof(pvid_s));
|
||||||
|
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||||
|
|
||||||
|
if (!(existing = info_from_pvid(pvid_s)) &&
|
||||||
|
!(existing = info_from_pvid(dev->pvid))) {
|
||||||
|
if (!(label = label_create(labeller))) {
|
||||||
|
stack;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(info = dm_malloc(sizeof(*info)))) {
|
||||||
|
log_error("lvmcache_info allocation failed");
|
||||||
|
label_destroy(label);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(info, 0, sizeof(*info));
|
||||||
|
|
||||||
|
label->info = info;
|
||||||
|
info->label = label;
|
||||||
|
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()) {
|
||||||
|
log_very_verbose("Ignoring duplicate PV %s on "
|
||||||
|
"%s - using md %s",
|
||||||
|
pvid, dev_name(dev),
|
||||||
|
dev_name(existing->dev));
|
||||||
|
return NULL;
|
||||||
|
} else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||||
|
!dm_is_dm_major(MAJOR(dev->dev))) {
|
||||||
|
log_very_verbose("Ignoring duplicate PV %s on "
|
||||||
|
"%s - using dm %s",
|
||||||
|
pvid, dev_name(dev),
|
||||||
|
dev_name(existing->dev));
|
||||||
|
return NULL;
|
||||||
|
} else if (MAJOR(existing->dev->dev) != md_major() &&
|
||||||
|
MAJOR(dev->dev) == md_major())
|
||||||
|
log_very_verbose("Duplicate PV %s on %s - "
|
||||||
|
"using md %s", pvid,
|
||||||
|
dev_name(existing->dev),
|
||||||
|
dev_name(dev));
|
||||||
|
else if (!dm_is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||||
|
dm_is_dm_major(MAJOR(dev->dev)))
|
||||||
|
log_very_verbose("Duplicate PV %s on %s - "
|
||||||
|
"using dm %s", pvid,
|
||||||
|
dev_name(existing->dev),
|
||||||
|
dev_name(dev));
|
||||||
|
/* FIXME If both dm, check dependencies */
|
||||||
|
//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
|
||||||
|
//dm_is_dm_major(MAJOR(dev->dev)))
|
||||||
|
//
|
||||||
|
else
|
||||||
|
log_error("Found duplicate PV %s: using %s not "
|
||||||
|
"%s", pvid, dev_name(dev),
|
||||||
|
dev_name(existing->dev));
|
||||||
|
}
|
||||||
|
/* Switch over to new preferred device */
|
||||||
|
existing->dev = dev;
|
||||||
|
info = existing;
|
||||||
|
/* Has labeller changed? */
|
||||||
|
if (info->label->labeller != labeller) {
|
||||||
|
label_destroy(info->label);
|
||||||
|
if (!(info->label = label_create(labeller))) {
|
||||||
|
/* FIXME leaves info without label! */
|
||||||
|
stack;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
info->label->info = info;
|
||||||
|
}
|
||||||
|
label = info->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->fmt = (const struct format_type *) labeller->private;
|
||||||
|
info->status |= CACHE_INVALID;
|
||||||
|
|
||||||
|
if (!_lvmcache_update_pvid(info, pvid_s)) {
|
||||||
|
if (!existing) {
|
||||||
|
dm_free(info);
|
||||||
|
label_destroy(label);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) {
|
||||||
|
if (!existing) {
|
||||||
|
dm_hash_remove(_pvid_hash, pvid_s);
|
||||||
|
strcpy(info->dev->pvid, "");
|
||||||
|
dm_free(info);
|
||||||
|
label_destroy(label);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _lvmcache_destroy_entry(struct lvmcache_info *info)
|
||||||
|
{
|
||||||
|
if (!list_empty(&info->list))
|
||||||
|
list_del(&info->list);
|
||||||
|
strcpy(info->dev->pvid, "");
|
||||||
|
label_destroy(info->label);
|
||||||
|
dm_free(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
|
||||||
|
{
|
||||||
|
struct lvmcache_vginfo *next;
|
||||||
|
|
||||||
|
do {
|
||||||
|
next = vginfo->next;
|
||||||
|
if (vginfo->vgname)
|
||||||
|
dm_free(vginfo->vgname);
|
||||||
|
if (vginfo->creation_host)
|
||||||
|
dm_free(vginfo->creation_host);
|
||||||
|
dm_free(vginfo);
|
||||||
|
} while ((vginfo = next));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _lvmcache_destroy_lockname(int present __attribute((unused)))
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
}
|
||||||
|
|
||||||
|
void lvmcache_destroy(void)
|
||||||
|
{
|
||||||
|
log_verbose("Wiping internal VG cache");
|
||||||
|
|
||||||
|
_has_scanned = 0;
|
||||||
|
|
||||||
|
if (_vgid_hash) {
|
||||||
|
dm_hash_destroy(_vgid_hash);
|
||||||
|
_vgid_hash = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pvid_hash) {
|
||||||
|
dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_entry);
|
||||||
|
dm_hash_destroy(_pvid_hash);
|
||||||
|
_pvid_hash = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_vgname_hash) {
|
||||||
|
dm_hash_iter(_vgname_hash,
|
||||||
|
(dm_hash_iterate_fn) _lvmcache_destroy_vgnamelist);
|
||||||
|
dm_hash_destroy(_vgname_hash);
|
||||||
|
_vgname_hash = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lock_hash) {
|
||||||
|
dm_hash_iter(_lock_hash, (dm_hash_iterate_fn) _lvmcache_destroy_lockname);
|
||||||
|
dm_hash_destroy(_lock_hash);
|
||||||
|
_lock_hash = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_init(&_vginfos);
|
||||||
|
}
|
||||||
108
lib/cache/lvmcache.h
vendored
Normal file
108
lib/cache/lvmcache.h
vendored
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_CACHE_H
|
||||||
|
#define _LVM_CACHE_H
|
||||||
|
|
||||||
|
#include "dev-cache.h"
|
||||||
|
#include "uuid.h"
|
||||||
|
#include "label.h"
|
||||||
|
|
||||||
|
#define ORPHAN ""
|
||||||
|
|
||||||
|
#define CACHE_INVALID 0x00000001
|
||||||
|
#define CACHE_LOCKED 0x00000002
|
||||||
|
|
||||||
|
/* LVM specific per-volume info */
|
||||||
|
/* Eventual replacement for struct physical_volume perhaps? */
|
||||||
|
|
||||||
|
struct cmd_context;
|
||||||
|
struct format_type;
|
||||||
|
struct volume_group;
|
||||||
|
|
||||||
|
/* One per VG */
|
||||||
|
struct lvmcache_vginfo {
|
||||||
|
struct list list; /* Join these vginfos together */
|
||||||
|
struct list infos; /* List head for lvmcache_infos */
|
||||||
|
const struct format_type *fmt;
|
||||||
|
char *vgname; /* "" == orphan */
|
||||||
|
uint32_t status;
|
||||||
|
char vgid[ID_LEN + 1];
|
||||||
|
char _padding[7];
|
||||||
|
struct lvmcache_vginfo *next; /* Another VG with same name? */
|
||||||
|
char *creation_host;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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 lvmcache_vginfo *vginfo; /* NULL == unknown */
|
||||||
|
struct label *label;
|
||||||
|
const struct format_type *fmt;
|
||||||
|
struct device *dev;
|
||||||
|
uint64_t device_size; /* Bytes */
|
||||||
|
uint32_t status;
|
||||||
|
};
|
||||||
|
|
||||||
|
int lvmcache_init(void);
|
||||||
|
void lvmcache_destroy(void);
|
||||||
|
|
||||||
|
/* Set full_scan to 1 to reread every filtered device label or
|
||||||
|
* 2 to rescan /dev for new devices */
|
||||||
|
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
|
||||||
|
|
||||||
|
/* Add/delete a device */
|
||||||
|
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
||||||
|
struct device *dev,
|
||||||
|
const char *vgname, const char *vgid,
|
||||||
|
uint32_t vgstatus);
|
||||||
|
void lvmcache_del(struct lvmcache_info *info);
|
||||||
|
|
||||||
|
/* Update things */
|
||||||
|
int lvmcache_update_vgname_and_id(struct lvmcache_info *info,
|
||||||
|
const char *vgname, const char *vgid,
|
||||||
|
uint32_t vgstatus, const char *hostname);
|
||||||
|
int lvmcache_update_vg(struct volume_group *vg);
|
||||||
|
|
||||||
|
void lvmcache_lock_vgname(const char *vgname, int read_only);
|
||||||
|
void lvmcache_unlock_vgname(const char *vgname);
|
||||||
|
|
||||||
|
/* Queries */
|
||||||
|
const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid);
|
||||||
|
struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname,
|
||||||
|
const char *vgid);
|
||||||
|
struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
|
||||||
|
struct lvmcache_info *info_from_pvid(const char *pvid);
|
||||||
|
const char *vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||||
|
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
|
||||||
|
int vgs_locked(void);
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* Returns list of struct str_lists containing pool-allocated copy of pvids */
|
||||||
|
struct list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
|
||||||
|
const char *vgid);
|
||||||
|
|
||||||
|
#endif
|
||||||
24
lib/commands/errors.h
Normal file
24
lib/commands/errors.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_ERRORS_H
|
||||||
|
#define _LVM_ERRORS_H
|
||||||
|
|
||||||
|
#define ECMD_PROCESSED 1
|
||||||
|
#define ENO_SUCH_CMD 2
|
||||||
|
#define EINVALID_CMD_LINE 3
|
||||||
|
#define ECMD_FAILED 5
|
||||||
|
|
||||||
|
#endif
|
||||||
1131
lib/commands/toolcontext.c
Normal file
1131
lib/commands/toolcontext.c
Normal file
File diff suppressed because it is too large
Load Diff
97
lib/commands/toolcontext.h
Normal file
97
lib/commands/toolcontext.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_TOOLCONTEXT_H
|
||||||
|
#define _LVM_TOOLCONTEXT_H
|
||||||
|
|
||||||
|
#include "dev-cache.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Config options that can be changed while commands are processed
|
||||||
|
*/
|
||||||
|
struct config_info {
|
||||||
|
int debug;
|
||||||
|
int verbose;
|
||||||
|
int test;
|
||||||
|
int syslog;
|
||||||
|
int activation;
|
||||||
|
int suffix;
|
||||||
|
int archive; /* should we archive ? */
|
||||||
|
int backup; /* should we backup ? */
|
||||||
|
const char *msg_prefix;
|
||||||
|
struct format_type *fmt;
|
||||||
|
uint64_t unit_factor;
|
||||||
|
int cmd_name; /* Show command name? */
|
||||||
|
mode_t umask;
|
||||||
|
char unit_type;
|
||||||
|
char _padding[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct config_tree;
|
||||||
|
struct archive_params;
|
||||||
|
struct backup_params;
|
||||||
|
|
||||||
|
/* FIXME Split into tool & library contexts */
|
||||||
|
/* command-instance-related variables needed by library */
|
||||||
|
struct cmd_context {
|
||||||
|
struct dm_pool *libmem; /* For permanent config data */
|
||||||
|
struct dm_pool *mem; /* Transient: Cleared between each command */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
const char *hostname;
|
||||||
|
const char *kernel_vsn;
|
||||||
|
|
||||||
|
char *cmd_line;
|
||||||
|
struct command *command;
|
||||||
|
struct arg *args;
|
||||||
|
char **argv;
|
||||||
|
unsigned is_static; /* Static binary? */
|
||||||
|
unsigned is_long_lived; /* Optimises persistent_filter handling */
|
||||||
|
|
||||||
|
struct dev_filter *filter;
|
||||||
|
int dump_filter; /* Dump filter when exiting? */
|
||||||
|
|
||||||
|
struct list config_files;
|
||||||
|
int config_valid;
|
||||||
|
struct config_tree *cft;
|
||||||
|
struct config_tree *cft_override;
|
||||||
|
struct config_info default_settings;
|
||||||
|
struct config_info current_settings;
|
||||||
|
|
||||||
|
struct archive_params *archive_params;
|
||||||
|
struct backup_params *backup_params;
|
||||||
|
|
||||||
|
/* List of defined tags */
|
||||||
|
struct list tags;
|
||||||
|
int hosttags;
|
||||||
|
|
||||||
|
char sys_dir[PATH_MAX];
|
||||||
|
char dev_dir[PATH_MAX];
|
||||||
|
char proc_dir[PATH_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
|
||||||
|
void destroy_toolcontext(struct cmd_context *cmd);
|
||||||
|
int refresh_toolcontext(struct cmd_context *cmd);
|
||||||
|
int config_files_changed(struct cmd_context *cmd);
|
||||||
|
|
||||||
|
#endif
|
||||||
1156
lib/config/config.c
Normal file
1156
lib/config/config.c
Normal file
File diff suppressed because it is too large
Load Diff
111
lib/config/config.h
Normal file
111
lib/config/config.h
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_CONFIG_H
|
||||||
|
#define _LVM_CONFIG_H
|
||||||
|
|
||||||
|
#include "lvm-types.h"
|
||||||
|
|
||||||
|
struct device;
|
||||||
|
struct cmd_context;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CFG_STRING,
|
||||||
|
CFG_FLOAT,
|
||||||
|
CFG_INT,
|
||||||
|
CFG_EMPTY_ARRAY
|
||||||
|
};
|
||||||
|
|
||||||
|
struct config_value {
|
||||||
|
int type;
|
||||||
|
union {
|
||||||
|
int i;
|
||||||
|
float r;
|
||||||
|
char *str;
|
||||||
|
} v;
|
||||||
|
struct config_value *next; /* for arrays */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct config_node {
|
||||||
|
char *key;
|
||||||
|
struct config_node *sib, *child;
|
||||||
|
struct config_value *v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct config_tree {
|
||||||
|
struct config_node *root;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct config_tree_list {
|
||||||
|
struct 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);
|
||||||
|
void destroy_config_tree(struct config_tree *cft);
|
||||||
|
|
||||||
|
typedef uint32_t (*checksum_fn_t) (uint32_t initial, const void *buf, uint32_t size);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int read_config_file(struct config_tree *cft);
|
||||||
|
int write_config_file(struct config_tree *cft, const char *file,
|
||||||
|
int argc, char **argv);
|
||||||
|
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,
|
||||||
|
struct config_tree *newdata);
|
||||||
|
|
||||||
|
struct config_node *find_config_node(const struct config_node *cn,
|
||||||
|
const char *path);
|
||||||
|
const char *find_config_str(const struct config_node *cn, const char *path,
|
||||||
|
const char *fail);
|
||||||
|
int find_config_int(const struct config_node *cn, const char *path, int fail);
|
||||||
|
float find_config_float(const struct config_node *cn, const char *path,
|
||||||
|
float fail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These versions check an override tree, if present, first.
|
||||||
|
*/
|
||||||
|
struct config_node *find_config_tree_node(struct cmd_context *cmd,
|
||||||
|
const char *path);
|
||||||
|
const char *find_config_tree_str(struct cmd_context *cmd,
|
||||||
|
const char *path, const char *fail);
|
||||||
|
int find_config_tree_int(struct cmd_context *cmd, const char *path,
|
||||||
|
int fail);
|
||||||
|
float find_config_tree_float(struct cmd_context *cmd, const char *path,
|
||||||
|
float fail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Understands (0, ~0), (y, n), (yes, no), (on,
|
||||||
|
* off), (true, false).
|
||||||
|
*/
|
||||||
|
int find_config_bool(const struct config_node *cn, const char *path, int fail);
|
||||||
|
int find_config_tree_bool(struct cmd_context *cmd, const char *path, int fail);
|
||||||
|
|
||||||
|
int get_config_uint32(const struct config_node *cn, const char *path,
|
||||||
|
uint32_t *result);
|
||||||
|
|
||||||
|
int get_config_uint64(const struct config_node *cn, const char *path,
|
||||||
|
uint64_t *result);
|
||||||
|
|
||||||
|
int get_config_str(const struct config_node *cn, const char *path,
|
||||||
|
char **result);
|
||||||
|
|
||||||
|
#endif
|
||||||
122
lib/config/defaults.h
Normal file
122
lib/config/defaults.h
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_DEFAULTS_H
|
||||||
|
#define _LVM_DEFAULTS_H
|
||||||
|
|
||||||
|
#define DEFAULT_ARCHIVE_ENABLED 1
|
||||||
|
#define DEFAULT_BACKUP_ENABLED 1
|
||||||
|
|
||||||
|
#define DEFAULT_ARCHIVE_SUBDIR "archive"
|
||||||
|
#define DEFAULT_BACKUP_SUBDIR "backup"
|
||||||
|
#define DEFAULT_CACHE_SUBDIR "cache"
|
||||||
|
#define DEFAULT_CACHE_FILE_PREFIX ""
|
||||||
|
|
||||||
|
#define DEFAULT_ARCHIVE_DAYS 30
|
||||||
|
#define DEFAULT_ARCHIVE_NUMBER 10
|
||||||
|
|
||||||
|
#define DEFAULT_SYS_DIR "/etc/lvm"
|
||||||
|
#define DEFAULT_DEV_DIR "/dev"
|
||||||
|
#define DEFAULT_PROC_DIR "/proc"
|
||||||
|
#define DEFAULT_SYSFS_SCAN 1
|
||||||
|
#define DEFAULT_MD_COMPONENT_DETECTION 1
|
||||||
|
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 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_MIRROR_LOG_FAULT_POLICY "allocate"
|
||||||
|
#define DEFAULT_MIRROR_DEV_FAULT_POLICY "remove"
|
||||||
|
#define DEFAULT_DMEVENTD_MIRROR_LIB "libdevmapper-event-lvm2mirror.so"
|
||||||
|
#define DEFAULT_DMEVENTD_MONITOR 1
|
||||||
|
|
||||||
|
#define DEFAULT_UMASK 0077
|
||||||
|
|
||||||
|
#ifdef LVM1_FALLBACK
|
||||||
|
# define DEFAULT_FALLBACK_TO_LVM1 1
|
||||||
|
#else
|
||||||
|
# define DEFAULT_FALLBACK_TO_LVM1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LVM1_SUPPORT
|
||||||
|
# define DEFAULT_FORMAT "lvm1"
|
||||||
|
#else
|
||||||
|
# define DEFAULT_FORMAT "lvm2"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_STRIPESIZE 64 /* KB */
|
||||||
|
#define DEFAULT_PVMETADATASIZE 255
|
||||||
|
#define DEFAULT_PVMETADATACOPIES 1
|
||||||
|
#define DEFAULT_LABELSECTOR UINT64_C(1)
|
||||||
|
|
||||||
|
#define DEFAULT_MSG_PREFIX " "
|
||||||
|
#define DEFAULT_CMD_NAME 0
|
||||||
|
#define DEFAULT_OVERWRITE 0
|
||||||
|
|
||||||
|
#ifndef DEFAULT_LOG_FACILITY
|
||||||
|
# define DEFAULT_LOG_FACILITY LOG_USER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_SYSLOG 1
|
||||||
|
#define DEFAULT_VERBOSE 0
|
||||||
|
#define DEFAULT_LOGLEVEL 0
|
||||||
|
#define DEFAULT_INDENT 1
|
||||||
|
#define DEFAULT_UNITS "h"
|
||||||
|
#define DEFAULT_SUFFIX 1
|
||||||
|
#define DEFAULT_HOSTTAGS 0
|
||||||
|
|
||||||
|
#ifdef DEVMAPPER_SUPPORT
|
||||||
|
# define DEFAULT_ACTIVATION 1
|
||||||
|
# define DEFAULT_RESERVED_MEMORY 8192
|
||||||
|
# define DEFAULT_RESERVED_STACK 256
|
||||||
|
# define DEFAULT_PROCESS_PRIORITY -18
|
||||||
|
#else
|
||||||
|
# define DEFAULT_ACTIVATION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_STRIPE_FILLER "/dev/ioerror"
|
||||||
|
#define DEFAULT_MIRROR_REGION_SIZE 512 /* KB */
|
||||||
|
#define DEFAULT_INTERVAL 15
|
||||||
|
|
||||||
|
#ifdef READLINE_SUPPORT
|
||||||
|
# define DEFAULT_MAX_HISTORY 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_REP_ALIGNED 1
|
||||||
|
#define DEFAULT_REP_BUFFERED 1
|
||||||
|
#define DEFAULT_REP_HEADINGS 1
|
||||||
|
#define DEFAULT_REP_SEPARATOR " "
|
||||||
|
|
||||||
|
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,mirror_log,copy_percent"
|
||||||
|
#define DEFAULT_VGS_COLS "vg_name,pv_count,lv_count,snap_count,vg_attr,vg_size,vg_free"
|
||||||
|
#define DEFAULT_PVS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free"
|
||||||
|
#define DEFAULT_SEGS_COLS "lv_name,vg_name,lv_attr,stripes,segtype,seg_size"
|
||||||
|
#define DEFAULT_PVSEGS_COLS "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
|
||||||
|
|
||||||
|
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,lv_uuid"
|
||||||
|
#define DEFAULT_VGS_COLS_VERB "vg_name,vg_attr,vg_extent_size,pv_count,lv_count,snap_count,vg_size,vg_free,vg_uuid"
|
||||||
|
#define DEFAULT_PVS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,dev_size,pv_uuid"
|
||||||
|
#define DEFAULT_SEGS_COLS_VERB "lv_name,vg_name,lv_attr,seg_start,seg_size,stripes,segtype,stripesize,chunksize"
|
||||||
|
#define DEFAULT_PVSEGS_COLS_VERB "pv_name,vg_name,pv_fmt,pv_attr,pv_size,pv_free,pvseg_start,pvseg_size"
|
||||||
|
|
||||||
|
#define DEFAULT_LVS_SORT "vg_name,lv_name"
|
||||||
|
#define DEFAULT_VGS_SORT "vg_name"
|
||||||
|
#define DEFAULT_PVS_SORT "pv_name"
|
||||||
|
#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
|
||||||
|
#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
|
||||||
|
|
||||||
|
#endif /* _LVM_DEFAULTS_H */
|
||||||
138
lib/datastruct/btree.c
Normal file
138
lib/datastruct/btree.c
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "btree.h"
|
||||||
|
|
||||||
|
struct node {
|
||||||
|
uint32_t key;
|
||||||
|
struct node *l, *r, *p;
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct btree {
|
||||||
|
struct dm_pool *mem;
|
||||||
|
struct node *root;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct btree *btree_create(struct dm_pool *mem)
|
||||||
|
{
|
||||||
|
struct btree *t = dm_pool_alloc(mem, sizeof(*t));
|
||||||
|
|
||||||
|
if (t) {
|
||||||
|
t->mem = mem;
|
||||||
|
t->root = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shuffle the bits in a key, to try and remove
|
||||||
|
* any ordering.
|
||||||
|
*/
|
||||||
|
static uint32_t _shuffle(uint32_t k)
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
return ((k & 0xff) << 24 |
|
||||||
|
(k & 0xff00) << 8 |
|
||||||
|
(k & 0xff0000) >> 8 | (k & 0xff000000) >> 24);
|
||||||
|
#else
|
||||||
|
return k;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct node **_lookup(struct node **c, uint32_t key, struct node **p)
|
||||||
|
{
|
||||||
|
*p = NULL;
|
||||||
|
while (*c) {
|
||||||
|
*p = *c;
|
||||||
|
if ((*c)->key == key)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (key < (*c)->key)
|
||||||
|
c = &(*c)->l;
|
||||||
|
|
||||||
|
else
|
||||||
|
c = &(*c)->r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *btree_lookup(struct btree *t, uint32_t k)
|
||||||
|
{
|
||||||
|
uint32_t key = _shuffle(k);
|
||||||
|
struct node *p, **c = _lookup(&t->root, key, &p);
|
||||||
|
return (*c) ? (*c)->data : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int btree_insert(struct btree *t, uint32_t k, void *data)
|
||||||
|
{
|
||||||
|
uint32_t key = _shuffle(k);
|
||||||
|
struct node *p, **c = _lookup(&t->root, key, &p), *n;
|
||||||
|
|
||||||
|
if (!*c) {
|
||||||
|
if (!(n = dm_pool_alloc(t->mem, sizeof(*n)))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
n->key = key;
|
||||||
|
n->data = data;
|
||||||
|
n->l = n->r = NULL;
|
||||||
|
n->p = p;
|
||||||
|
|
||||||
|
*c = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *btree_get_data(struct btree_iter *it)
|
||||||
|
{
|
||||||
|
return ((struct node *) it)->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct node *_left(struct node *n)
|
||||||
|
{
|
||||||
|
while (n->l)
|
||||||
|
n = n->l;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct btree_iter *btree_first(struct btree *t)
|
||||||
|
{
|
||||||
|
if (!t->root)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (struct btree_iter *) _left(t->root);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct btree_iter *btree_next(struct btree_iter *it)
|
||||||
|
{
|
||||||
|
struct node *n = (struct node *) it;
|
||||||
|
uint32_t k = n->key;
|
||||||
|
|
||||||
|
if (n->r)
|
||||||
|
return (struct btree_iter *) _left(n->r);
|
||||||
|
|
||||||
|
do
|
||||||
|
n = n->p;
|
||||||
|
while (n && k > n->key);
|
||||||
|
|
||||||
|
return (struct btree_iter *) n;
|
||||||
|
}
|
||||||
32
lib/datastruct/btree.h
Normal file
32
lib/datastruct/btree.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_BTREE_H
|
||||||
|
#define _LVM_BTREE_H
|
||||||
|
|
||||||
|
struct btree;
|
||||||
|
|
||||||
|
struct btree *btree_create(struct dm_pool *mem);
|
||||||
|
|
||||||
|
void *btree_lookup(struct btree *t, uint32_t k);
|
||||||
|
int btree_insert(struct btree *t, uint32_t k, void *data);
|
||||||
|
|
||||||
|
struct btree_iter;
|
||||||
|
void *btree_get_data(struct btree_iter *it);
|
||||||
|
|
||||||
|
struct btree_iter *btree_first(struct btree *t);
|
||||||
|
struct btree_iter *btree_next(struct btree_iter *it);
|
||||||
|
|
||||||
|
#endif
|
||||||
136
lib/datastruct/list.c
Normal file
136
lib/datastruct/list.c
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the list empty?
|
||||||
|
*/
|
||||||
|
int list_empty(struct list *head)
|
||||||
|
{
|
||||||
|
return head->n == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the first element of the list?
|
||||||
|
*/
|
||||||
|
int list_start(struct list *head, struct list *elem)
|
||||||
|
{
|
||||||
|
return elem->p == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the last element of the list?
|
||||||
|
*/
|
||||||
|
int list_end(struct list *head, struct list *elem)
|
||||||
|
{
|
||||||
|
return elem->n == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return first element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
struct list *list_first(struct list *head)
|
||||||
|
{
|
||||||
|
return (list_empty(head) ? NULL : head->n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return last element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
struct list *list_last(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(struct list *head, 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(struct list *head, 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;
|
||||||
|
}
|
||||||
203
lib/datastruct/list.h
Normal file
203
lib/datastruct/list.h
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the list empty?
|
||||||
|
*/
|
||||||
|
int list_empty(struct list *head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the first element of the list?
|
||||||
|
*/
|
||||||
|
int list_start(struct list *head, struct list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the last element of the list?
|
||||||
|
*/
|
||||||
|
int list_end(struct list *head, struct list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return first element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
struct list *list_first(struct list *head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return last element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
struct list *list_last(struct list *head);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the previous element of the list, or NULL if we've reached the start.
|
||||||
|
*/
|
||||||
|
struct list *list_prev(struct list *head, struct list *elem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the next element of the list, or NULL if we've reached the end.
|
||||||
|
*/
|
||||||
|
struct list *list_next(struct list *head, 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
|
||||||
32
lib/datastruct/lvm-types.h
Normal file
32
lib/datastruct/lvm-types.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
struct str_list {
|
||||||
|
struct list list;
|
||||||
|
const char *str;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
128
lib/datastruct/str_list.c
Normal file
128
lib/datastruct/str_list.c
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "str_list.h"
|
||||||
|
|
||||||
|
struct list *str_list_create(struct dm_pool *mem)
|
||||||
|
{
|
||||||
|
struct list *sl;
|
||||||
|
|
||||||
|
if (!(sl = dm_pool_alloc(mem, sizeof(struct list)))) {
|
||||||
|
stack;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_init(sl);
|
||||||
|
|
||||||
|
return sl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str)
|
||||||
|
{
|
||||||
|
struct str_list *sln;
|
||||||
|
|
||||||
|
if (!str) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Already in list? */
|
||||||
|
if (str_list_match_item(sll, str))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!(sln = dm_pool_alloc(mem, sizeof(*sln)))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sln->str = str;
|
||||||
|
list_add(sll, &sln->list);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_list_del(struct list *sll, const char *str)
|
||||||
|
{
|
||||||
|
struct list *slh, *slht;
|
||||||
|
|
||||||
|
list_iterate_safe(slh, slht, sll) {
|
||||||
|
if (!strcmp(str, list_item(slh, struct str_list)->str))
|
||||||
|
list_del(slh);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold)
|
||||||
|
{
|
||||||
|
struct str_list *sl;
|
||||||
|
|
||||||
|
list_init(sllnew);
|
||||||
|
|
||||||
|
list_iterate_items(sl, sllold) {
|
||||||
|
if (!str_list_add(mem, sllnew, strdup(sl->str))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is item on list?
|
||||||
|
*/
|
||||||
|
int str_list_match_item(struct list *sll, const char *str)
|
||||||
|
{
|
||||||
|
struct str_list *sl;
|
||||||
|
|
||||||
|
list_iterate_items(sl, sll)
|
||||||
|
if (!strcmp(str, sl->str))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is at least one item on both lists?
|
||||||
|
*/
|
||||||
|
int str_list_match_list(struct list *sll, struct list *sll2)
|
||||||
|
{
|
||||||
|
struct str_list *sl;
|
||||||
|
|
||||||
|
list_iterate_items(sl, sll)
|
||||||
|
if (str_list_match_item(sll2, sl->str))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do both lists contain the same set of items?
|
||||||
|
*/
|
||||||
|
int str_list_lists_equal(struct list *sll, struct list *sll2)
|
||||||
|
{
|
||||||
|
struct str_list *sl;
|
||||||
|
|
||||||
|
if (list_size(sll) != list_size(sll2))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
list_iterate_items(sl, sll)
|
||||||
|
if (!str_list_match_item(sll2, sl->str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
27
lib/datastruct/str_list.h
Normal file
27
lib/datastruct/str_list.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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(struct list *sll, const char *str);
|
||||||
|
int str_list_match_list(struct list *sll, struct list *sll2);
|
||||||
|
int str_list_lists_equal(struct list *sll, struct list *sll2);
|
||||||
|
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold);
|
||||||
|
|
||||||
|
#endif
|
||||||
694
lib/device/dev-cache.c
Normal file
694
lib/device/dev-cache.c
Normal file
@@ -0,0 +1,694 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "dev-cache.h"
|
||||||
|
#include "lvm-types.h"
|
||||||
|
#include "btree.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "filter-persistent.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
struct dev_iter {
|
||||||
|
struct btree_iter *current;
|
||||||
|
struct dev_filter *filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dir_list {
|
||||||
|
struct list list;
|
||||||
|
char dir[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
struct dm_pool *mem;
|
||||||
|
struct dm_hash_table *names;
|
||||||
|
struct btree *devices;
|
||||||
|
|
||||||
|
int has_scanned;
|
||||||
|
struct list dirs;
|
||||||
|
struct list files;
|
||||||
|
|
||||||
|
} _cache;
|
||||||
|
|
||||||
|
#define _alloc(x) dm_pool_zalloc(_cache.mem, (x))
|
||||||
|
#define _free(x) dm_pool_free(_cache.mem, (x))
|
||||||
|
#define _strdup(x) dm_pool_strdup(_cache.mem, (x))
|
||||||
|
|
||||||
|
static int _insert(const char *path, int rec);
|
||||||
|
|
||||||
|
struct device *dev_create_file(const char *filename, struct device *dev,
|
||||||
|
struct str_list *alias, int use_malloc)
|
||||||
|
{
|
||||||
|
int allocate = !dev;
|
||||||
|
|
||||||
|
if (allocate) {
|
||||||
|
if (use_malloc) {
|
||||||
|
if (!(dev = dm_malloc(sizeof(*dev)))) {
|
||||||
|
log_error("struct device allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(alias = dm_malloc(sizeof(*alias)))) {
|
||||||
|
log_error("struct str_list allocation failed");
|
||||||
|
dm_free(dev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(alias->str = dm_strdup(filename))) {
|
||||||
|
log_error("filename strdup failed");
|
||||||
|
dm_free(dev);
|
||||||
|
dm_free(alias);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dev->flags = DEV_ALLOCED;
|
||||||
|
} else {
|
||||||
|
if (!(dev = _alloc(sizeof(*dev)))) {
|
||||||
|
log_error("struct device allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(alias = _alloc(sizeof(*alias)))) {
|
||||||
|
log_error("struct str_list allocation failed");
|
||||||
|
_free(dev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(alias->str = _strdup(filename))) {
|
||||||
|
log_error("filename strdup failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!(alias->str = dm_strdup(filename))) {
|
||||||
|
log_error("filename strdup failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->flags |= DEV_REGULAR;
|
||||||
|
list_init(&dev->aliases);
|
||||||
|
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;
|
||||||
|
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||||
|
list_init(&dev->open_list);
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct device *_dev_create(dev_t d)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
if (!(dev = _alloc(sizeof(*dev)))) {
|
||||||
|
log_error("struct device allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dev->flags = 0;
|
||||||
|
list_init(&dev->aliases);
|
||||||
|
dev->dev = d;
|
||||||
|
dev->fd = -1;
|
||||||
|
dev->open_count = 0;
|
||||||
|
dev->block_size = -1;
|
||||||
|
dev->end = UINT64_C(0);
|
||||||
|
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||||
|
list_init(&dev->open_list);
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return 1 if we prefer path1 else return 0 */
|
||||||
|
static int _compare_paths(const char *path0, const char *path1)
|
||||||
|
{
|
||||||
|
int slash0 = 0, slash1 = 0;
|
||||||
|
const char *p;
|
||||||
|
char p0[PATH_MAX], p1[PATH_MAX];
|
||||||
|
char *s0, *s1;
|
||||||
|
struct stat stat0, stat1;
|
||||||
|
|
||||||
|
/* Return the path with fewer slashes */
|
||||||
|
for (p = path0; p++; p = (const char *) strchr(p, '/'))
|
||||||
|
slash0++;
|
||||||
|
|
||||||
|
for (p = path1; p++; p = (const char *) strchr(p, '/'))
|
||||||
|
slash1++;
|
||||||
|
|
||||||
|
if (slash0 < slash1)
|
||||||
|
return 0;
|
||||||
|
if (slash1 < slash0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
strncpy(p0, path0, PATH_MAX);
|
||||||
|
strncpy(p1, path1, PATH_MAX);
|
||||||
|
s0 = &p0[0] + 1;
|
||||||
|
s1 = &p1[0] + 1;
|
||||||
|
|
||||||
|
/* We prefer symlinks - they exist for a reason!
|
||||||
|
* So we prefer a shorter path before the first symlink in the name.
|
||||||
|
* FIXME Configuration option to invert this? */
|
||||||
|
while (s0) {
|
||||||
|
s0 = strchr(s0, '/');
|
||||||
|
s1 = strchr(s1, '/');
|
||||||
|
if (s0) {
|
||||||
|
*s0 = '\0';
|
||||||
|
*s1 = '\0';
|
||||||
|
}
|
||||||
|
if (lstat(p0, &stat0)) {
|
||||||
|
log_sys_error("lstat", p0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lstat(p1, &stat1)) {
|
||||||
|
log_sys_error("lstat", p1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (S_ISLNK(stat0.st_mode) && !S_ISLNK(stat1.st_mode))
|
||||||
|
return 0;
|
||||||
|
if (!S_ISLNK(stat0.st_mode) && S_ISLNK(stat1.st_mode))
|
||||||
|
return 1;
|
||||||
|
if (s0) {
|
||||||
|
*s0++ = '/';
|
||||||
|
*s1++ = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ASCII comparison */
|
||||||
|
if (strcmp(path0, path1) < 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _add_alias(struct device *dev, const char *path)
|
||||||
|
{
|
||||||
|
struct str_list *sl = _alloc(sizeof(*sl));
|
||||||
|
struct str_list *strl;
|
||||||
|
const char *oldpath;
|
||||||
|
int prefer_old = 1;
|
||||||
|
|
||||||
|
if (!sl) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is name already there? */
|
||||||
|
list_iterate_items(strl, &dev->aliases) {
|
||||||
|
if (!strcmp(strl->str, path)) {
|
||||||
|
log_debug("%s: Already in device cache", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(sl->str = dm_pool_strdup(_cache.mem, path))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!list_empty(&dev->aliases)) {
|
||||||
|
oldpath = 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)");
|
||||||
|
|
||||||
|
} else
|
||||||
|
log_debug("%s: Added to device cache", path);
|
||||||
|
|
||||||
|
if (prefer_old)
|
||||||
|
list_add(&dev->aliases, &sl->list);
|
||||||
|
else
|
||||||
|
list_add_h(&dev->aliases, &sl->list);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Either creates a new dev, or adds an alias to
|
||||||
|
* an existing dev.
|
||||||
|
*/
|
||||||
|
static int _insert_dev(const char *path, dev_t d)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
static dev_t loopfile_count = 0;
|
||||||
|
int loopfile = 0;
|
||||||
|
|
||||||
|
/* Generate pretend device numbers for loopfiles */
|
||||||
|
if (!d) {
|
||||||
|
if (dm_hash_lookup(_cache.names, path))
|
||||||
|
return 1;
|
||||||
|
d = ++loopfile_count;
|
||||||
|
loopfile = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is this device already registered ? */
|
||||||
|
if (!(dev = (struct device *) btree_lookup(_cache.devices,
|
||||||
|
(uint32_t) d))) {
|
||||||
|
/* create new device */
|
||||||
|
if (loopfile) {
|
||||||
|
if (!(dev = dev_create_file(path, NULL, NULL, 0))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (!(dev = _dev_create(d))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(btree_insert(_cache.devices, (uint32_t) d, dev))) {
|
||||||
|
log_err("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.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dm_hash_insert(_cache.names, path, dev)) {
|
||||||
|
log_err("Couldn't add name to hash in dev cache.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *_join(const char *dir, const char *name)
|
||||||
|
{
|
||||||
|
size_t len = strlen(dir) + strlen(name) + 2;
|
||||||
|
char *r = dm_malloc(len);
|
||||||
|
if (r)
|
||||||
|
snprintf(r, len, "%s/%s", dir, name);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get rid of extra slashes in the path string.
|
||||||
|
*/
|
||||||
|
static void _collapse_slashes(char *str)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
int was_slash = 0;
|
||||||
|
|
||||||
|
for (ptr = str; *ptr; ptr++) {
|
||||||
|
if (*ptr == '/') {
|
||||||
|
if (was_slash)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
was_slash = 1;
|
||||||
|
} else
|
||||||
|
was_slash = 0;
|
||||||
|
*str++ = *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
*str = *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _insert_dir(const char *dir)
|
||||||
|
{
|
||||||
|
int n, dirent_count, r = 1;
|
||||||
|
struct dirent **dirent;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
dirent_count = scandir(dir, &dirent, NULL, alphasort);
|
||||||
|
if (dirent_count > 0) {
|
||||||
|
for (n = 0; n < dirent_count; n++) {
|
||||||
|
if (dirent[n]->d_name[0] == '.') {
|
||||||
|
free(dirent[n]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(path = _join(dir, dirent[n]->d_name))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_collapse_slashes(path);
|
||||||
|
r &= _insert(path, 1);
|
||||||
|
dm_free(path);
|
||||||
|
|
||||||
|
free(dirent[n]);
|
||||||
|
}
|
||||||
|
free(dirent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _insert_file(const char *path)
|
||||||
|
{
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
if (stat(path, &info) < 0) {
|
||||||
|
log_sys_very_verbose("stat", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISREG(info.st_mode)) {
|
||||||
|
log_debug("%s: Not a regular file", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_insert_dev(path, 0)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _insert(const char *path, int rec)
|
||||||
|
{
|
||||||
|
struct stat info;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
if (stat(path, &info) < 0) {
|
||||||
|
log_sys_very_verbose("stat", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(info.st_mode)) { /* add a directory */
|
||||||
|
/* check it's not a symbolic link */
|
||||||
|
if (lstat(path, &info) < 0) {
|
||||||
|
log_sys_very_verbose("lstat", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISLNK(info.st_mode)) {
|
||||||
|
log_debug("%s: Symbolic link to directory", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec)
|
||||||
|
r = _insert_dir(path);
|
||||||
|
|
||||||
|
} else { /* add a device */
|
||||||
|
if (!S_ISBLK(info.st_mode)) {
|
||||||
|
log_debug("%s: Not a block device", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_insert_dev(path, info.st_rdev)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _full_scan(int dev_scan)
|
||||||
|
{
|
||||||
|
struct dir_list *dl;
|
||||||
|
|
||||||
|
if (_cache.has_scanned && !dev_scan)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_iterate_items(dl, &_cache.dirs)
|
||||||
|
_insert_dir(dl->dir);
|
||||||
|
|
||||||
|
list_iterate_items(dl, &_cache.files)
|
||||||
|
_insert_file(dl->dir);
|
||||||
|
|
||||||
|
_cache.has_scanned = 1;
|
||||||
|
init_full_scan_done(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_cache_has_scanned(void)
|
||||||
|
{
|
||||||
|
return _cache.has_scanned;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dev_cache_scan(int do_scan)
|
||||||
|
{
|
||||||
|
if (!do_scan)
|
||||||
|
_cache.has_scanned = 1;
|
||||||
|
else
|
||||||
|
_full_scan(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_cache_init(void)
|
||||||
|
{
|
||||||
|
_cache.names = NULL;
|
||||||
|
_cache.has_scanned = 0;
|
||||||
|
|
||||||
|
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(_cache.names = dm_hash_create(128))) {
|
||||||
|
stack;
|
||||||
|
dm_pool_destroy(_cache.mem);
|
||||||
|
_cache.mem = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(_cache.devices = btree_create(_cache.mem))) {
|
||||||
|
log_err("Couldn't create binary tree for dev-cache.");
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_init(&_cache.dirs);
|
||||||
|
list_init(&_cache.files);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
dev_cache_exit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _check_closed(struct device *dev)
|
||||||
|
{
|
||||||
|
if (dev->fd >= 0)
|
||||||
|
log_err("Device '%s' has been left open.", dev_name(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _check_for_open_devices(void)
|
||||||
|
{
|
||||||
|
dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dev_cache_exit(void)
|
||||||
|
{
|
||||||
|
if (_cache.names)
|
||||||
|
_check_for_open_devices();
|
||||||
|
|
||||||
|
if (_cache.mem) {
|
||||||
|
dm_pool_destroy(_cache.mem);
|
||||||
|
_cache.mem = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cache.names) {
|
||||||
|
dm_hash_destroy(_cache.names);
|
||||||
|
_cache.names = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cache.devices = NULL;
|
||||||
|
_cache.has_scanned = 0;
|
||||||
|
list_init(&_cache.dirs);
|
||||||
|
list_init(&_cache.files);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_cache_add_dir(const char *path)
|
||||||
|
{
|
||||||
|
struct dir_list *dl;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (stat(path, &st)) {
|
||||||
|
log_error("Ignoring %s: %s", path, strerror(errno));
|
||||||
|
/* But don't fail */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISDIR(st.st_mode)) {
|
||||||
|
log_error("Ignoring %s: Not a directory", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) {
|
||||||
|
log_error("dir_list allocation failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dl->dir, path);
|
||||||
|
list_add(&_cache.dirs, &dl->list);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_cache_add_loopfile(const char *path)
|
||||||
|
{
|
||||||
|
struct dir_list *dl;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (stat(path, &st)) {
|
||||||
|
log_error("Ignoring %s: %s", path, strerror(errno));
|
||||||
|
/* But don't fail */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode)) {
|
||||||
|
log_error("Ignoring %s: Not a regular file", path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) {
|
||||||
|
log_error("dir_list allocation failed for file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(dl->dir, path);
|
||||||
|
list_add(&_cache.files, &dl->list);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check cached device name is still valid before returning it */
|
||||||
|
/* This should be a rare occurrence */
|
||||||
|
/* set quiet if the cache is expected to be out-of-date */
|
||||||
|
/* FIXME Make rest of code pass/cache struct device instead of dev_name */
|
||||||
|
const char *dev_name_confirmed(struct device *dev, int quiet)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
const char *name;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((dev->flags & DEV_REGULAR))
|
||||||
|
return dev_name(dev);
|
||||||
|
|
||||||
|
while ((r = stat(name = list_item(dev->aliases.n,
|
||||||
|
struct str_list)->str, &buf)) ||
|
||||||
|
(buf.st_rdev != dev->dev)) {
|
||||||
|
if (r < 0) {
|
||||||
|
if (quiet)
|
||||||
|
log_sys_debug("stat", name);
|
||||||
|
else
|
||||||
|
log_sys_error("stat", name);
|
||||||
|
}
|
||||||
|
if (quiet)
|
||||||
|
log_debug("Path %s no longer valid for device(%d,%d)",
|
||||||
|
name, (int) MAJOR(dev->dev),
|
||||||
|
(int) MINOR(dev->dev));
|
||||||
|
else
|
||||||
|
log_error("Path %s no longer valid for device(%d,%d)",
|
||||||
|
name, (int) MAJOR(dev->dev),
|
||||||
|
(int) MINOR(dev->dev));
|
||||||
|
|
||||||
|
/* Remove the incorrect hash entry */
|
||||||
|
dm_hash_remove(_cache.names, name);
|
||||||
|
|
||||||
|
/* 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 (!r)
|
||||||
|
_insert(name, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error("Aborting - please provide new pathname for what "
|
||||||
|
"used to be %s", name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dev_name(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||||
|
|
||||||
|
if (d && (d->flags & DEV_REGULAR))
|
||||||
|
return d;
|
||||||
|
|
||||||
|
/* If the entry's wrong, remove it */
|
||||||
|
if (d && (stat(name, &buf) || (buf.st_rdev != d->dev))) {
|
||||||
|
dm_hash_remove(_cache.names, name);
|
||||||
|
d = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
_insert(name, 0);
|
||||||
|
d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||||
|
if (!d) {
|
||||||
|
_full_scan(0);
|
||||||
|
d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (d && (!f || (d->flags & DEV_REGULAR) ||
|
||||||
|
f->passes_filter(f, d))) ? d : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
|
||||||
|
{
|
||||||
|
struct dev_iter *di = dm_malloc(sizeof(*di));
|
||||||
|
|
||||||
|
if (!di) {
|
||||||
|
log_error("dev_iter allocation failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev_scan && !trust_cache()) {
|
||||||
|
/* Flag gets reset between each command */
|
||||||
|
if (!full_scan_done())
|
||||||
|
persistent_filter_wipe(f); /* Calls _full_scan(1) */
|
||||||
|
} else
|
||||||
|
_full_scan(0);
|
||||||
|
|
||||||
|
di->current = btree_first(_cache.devices);
|
||||||
|
di->filter = f;
|
||||||
|
|
||||||
|
return di;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dev_iter_destroy(struct dev_iter *iter)
|
||||||
|
{
|
||||||
|
dm_free(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct device *_iter_next(struct dev_iter *iter)
|
||||||
|
{
|
||||||
|
struct device *d = btree_get_data(iter->current);
|
||||||
|
iter->current = btree_next(iter->current);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device *dev_iter_get(struct dev_iter *iter)
|
||||||
|
{
|
||||||
|
while (iter->current) {
|
||||||
|
struct device *d = _iter_next(iter);
|
||||||
|
if (!iter->filter || (d->flags & DEV_REGULAR) ||
|
||||||
|
iter->filter->passes_filter(iter->filter, d))
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_fd(struct device *dev)
|
||||||
|
{
|
||||||
|
return dev->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *dev_name(const struct device *dev)
|
||||||
|
{
|
||||||
|
return (dev) ? list_item(dev->aliases.n, struct str_list)->str :
|
||||||
|
"unknown device";
|
||||||
|
}
|
||||||
52
lib/device/dev-cache.h
Normal file
52
lib/device/dev-cache.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_DEV_CACHE_H
|
||||||
|
#define _LVM_DEV_CACHE_H
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* predicate for devices.
|
||||||
|
*/
|
||||||
|
struct dev_filter {
|
||||||
|
int (*passes_filter) (struct dev_filter * f, struct device * dev);
|
||||||
|
void (*destroy) (struct dev_filter * f);
|
||||||
|
void *private;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The global device cache.
|
||||||
|
*/
|
||||||
|
int dev_cache_init(void);
|
||||||
|
void dev_cache_exit(void);
|
||||||
|
|
||||||
|
/* Trigger(1) or avoid(0) a scan */
|
||||||
|
void dev_cache_scan(int do_scan);
|
||||||
|
int dev_cache_has_scanned(void);
|
||||||
|
|
||||||
|
int dev_cache_add_dir(const char *path);
|
||||||
|
int dev_cache_add_loopfile(const char *path);
|
||||||
|
struct device *dev_cache_get(const char *name, struct dev_filter *f);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Object for iterating through the cache.
|
||||||
|
*/
|
||||||
|
struct dev_iter;
|
||||||
|
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
|
||||||
|
void dev_iter_destroy(struct dev_iter *iter);
|
||||||
|
struct device *dev_iter_get(struct dev_iter *iter);
|
||||||
|
|
||||||
|
#endif
|
||||||
645
lib/device/dev-io.c
Normal file
645
lib/device/dev-io.c
Normal file
@@ -0,0 +1,645 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "lvm-types.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
#include "lvmcache.h"
|
||||||
|
#include "memlock.h"
|
||||||
|
#include "locking.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#ifdef linux
|
||||||
|
# define u64 uint64_t /* Missing without __KERNEL__ */
|
||||||
|
# undef WNOHANG /* Avoid redefinition */
|
||||||
|
# undef WUNTRACED /* Avoid redefinition */
|
||||||
|
# include <linux/fs.h> /* For block ioctl definitions */
|
||||||
|
# define BLKSIZE_SHIFT SECTOR_SHIFT
|
||||||
|
# ifndef BLKGETSIZE64 /* fs.h out-of-date */
|
||||||
|
# define BLKGETSIZE64 _IOR(0x12, 114, size_t)
|
||||||
|
# endif /* BLKGETSIZE64 */
|
||||||
|
#else
|
||||||
|
# include <sys/disk.h>
|
||||||
|
# define BLKBSZGET DKIOCGETBLOCKSIZE
|
||||||
|
# define BLKSSZGET DKIOCGETBLOCKSIZE
|
||||||
|
# define BLKGETSIZE64 DKIOCGETBLOCKCOUNT
|
||||||
|
# define BLKFLSBUF DKIOCSYNCHRONIZECACHE
|
||||||
|
# define BLKSIZE_SHIFT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef O_DIRECT_SUPPORT
|
||||||
|
# ifndef O_DIRECT
|
||||||
|
# error O_DIRECT support configured but O_DIRECT definition not found in headers
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static LIST_INIT(_open_devices);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------
|
||||||
|
* The standard io loop that keeps submitting an io until it's
|
||||||
|
* all gone.
|
||||||
|
*---------------------------------------------------------------*/
|
||||||
|
static int _io(struct device_area *where, void *buffer, int should_write)
|
||||||
|
{
|
||||||
|
int fd = dev_fd(where->dev);
|
||||||
|
ssize_t n = 0;
|
||||||
|
size_t total = 0;
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
log_error("Attempt to read an unopened device (%s).",
|
||||||
|
dev_name(where->dev));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip all writes in test mode.
|
||||||
|
*/
|
||||||
|
if (should_write && test_mode())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (where->size > SSIZE_MAX) {
|
||||||
|
log_error("Read size too large: %" PRIu64, where->size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
|
||||||
|
log_error("%s: lseek %" PRIu64 " failed: %s",
|
||||||
|
dev_name(where->dev), (uint64_t) where->start,
|
||||||
|
strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (total < (size_t) where->size) {
|
||||||
|
do
|
||||||
|
n = should_write ?
|
||||||
|
write(fd, buffer, (size_t) where->size - total) :
|
||||||
|
read(fd, buffer, (size_t) where->size - total);
|
||||||
|
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
log_error("%s: %s failed after %" PRIu64 " of %" PRIu64
|
||||||
|
" at %" PRIu64 ": %s", dev_name(where->dev),
|
||||||
|
should_write ? "write" : "read",
|
||||||
|
(uint64_t) total,
|
||||||
|
(uint64_t) where->size,
|
||||||
|
(uint64_t) where->start, strerror(errno));
|
||||||
|
|
||||||
|
if (n <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
total += n;
|
||||||
|
buffer += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (total == (size_t) where->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------
|
||||||
|
* LVM2 uses O_DIRECT when performing metadata io, which requires
|
||||||
|
* block size aligned accesses. If any io is not aligned we have
|
||||||
|
* to perform the io via a bounce buffer, obviously this is quite
|
||||||
|
* inefficient.
|
||||||
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the sector size from an _open_ device.
|
||||||
|
*/
|
||||||
|
static int _get_block_size(struct device *dev, unsigned int *size)
|
||||||
|
{
|
||||||
|
const char *name = dev_name(dev);
|
||||||
|
|
||||||
|
if ((dev->block_size == -1)) {
|
||||||
|
if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) {
|
||||||
|
log_sys_error("ioctl BLKBSZGET", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
log_debug("%s: block size is %u bytes", name, dev->block_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = (unsigned int) dev->block_size;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Widens a region to be an aligned region.
|
||||||
|
*/
|
||||||
|
static void _widen_region(unsigned int block_size, struct device_area *region,
|
||||||
|
struct device_area *result)
|
||||||
|
{
|
||||||
|
uint64_t mask = block_size - 1, delta;
|
||||||
|
memcpy(result, region, sizeof(*result));
|
||||||
|
|
||||||
|
/* adjust the start */
|
||||||
|
delta = result->start & mask;
|
||||||
|
if (delta) {
|
||||||
|
result->start -= delta;
|
||||||
|
result->size += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* adjust the end */
|
||||||
|
delta = (result->start + result->size) & mask;
|
||||||
|
if (delta)
|
||||||
|
result->size += block_size - delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _aligned_io(struct device_area *where, void *buffer,
|
||||||
|
int should_write)
|
||||||
|
{
|
||||||
|
void *bounce;
|
||||||
|
unsigned int block_size = 0;
|
||||||
|
uintptr_t mask;
|
||||||
|
struct device_area widened;
|
||||||
|
|
||||||
|
if (!(where->dev->flags & DEV_REGULAR) &&
|
||||||
|
!_get_block_size(where->dev, &block_size)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!block_size)
|
||||||
|
block_size = lvm_getpagesize();
|
||||||
|
|
||||||
|
_widen_region(block_size, where, &widened);
|
||||||
|
|
||||||
|
/* Do we need to use a bounce buffer? */
|
||||||
|
mask = block_size - 1;
|
||||||
|
if (!memcmp(where, &widened, sizeof(widened)) &&
|
||||||
|
!((uintptr_t) buffer & mask))
|
||||||
|
return _io(where, buffer, should_write);
|
||||||
|
|
||||||
|
/* Allocate a bounce buffer with an extra block */
|
||||||
|
if (!(bounce = alloca((size_t) widened.size + block_size))) {
|
||||||
|
log_error("Bounce buffer alloca failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Realign start of bounce buffer (using the extra sector)
|
||||||
|
*/
|
||||||
|
if (((uintptr_t) bounce) & mask)
|
||||||
|
bounce = (void *) ((((uintptr_t) bounce) + mask) & ~mask);
|
||||||
|
|
||||||
|
/* channel the io through the bounce buffer */
|
||||||
|
if (!_io(&widened, bounce, 0)) {
|
||||||
|
if (!should_write) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* FIXME pre-extend the file */
|
||||||
|
memset(bounce, '\n', widened.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_write) {
|
||||||
|
memcpy(bounce + (where->start - widened.start), buffer,
|
||||||
|
(size_t) where->size);
|
||||||
|
|
||||||
|
/* ... then we write */
|
||||||
|
return _io(&widened, bounce, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, bounce + (where->start - widened.start),
|
||||||
|
(size_t) where->size);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dev_get_size_file(const struct device *dev, uint64_t *size)
|
||||||
|
{
|
||||||
|
const char *name = dev_name(dev);
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
if (stat(name, &info)) {
|
||||||
|
log_sys_error("stat", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = info.st_size;
|
||||||
|
*size >>= SECTOR_SHIFT; /* Convert to sectors */
|
||||||
|
|
||||||
|
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dev_get_size_dev(const struct device *dev, uint64_t *size)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
const char *name = dev_name(dev);
|
||||||
|
|
||||||
|
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||||
|
log_sys_error("open", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
|
||||||
|
log_sys_error("ioctl BLKGETSIZE64", name);
|
||||||
|
if (close(fd))
|
||||||
|
log_sys_error("close", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size >>= BLKSIZE_SHIFT; /* Convert to sectors */
|
||||||
|
if (close(fd))
|
||||||
|
log_sys_error("close", name);
|
||||||
|
|
||||||
|
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------
|
||||||
|
* Public functions
|
||||||
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int dev_get_size(const struct device *dev, uint64_t *size)
|
||||||
|
{
|
||||||
|
if ((dev->flags & DEV_REGULAR))
|
||||||
|
return _dev_get_size_file(dev, size);
|
||||||
|
else
|
||||||
|
return _dev_get_size_dev(dev, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Unused
|
||||||
|
int dev_get_sectsize(struct device *dev, uint32_t *size)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int s;
|
||||||
|
const char *name = dev_name(dev);
|
||||||
|
|
||||||
|
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||||
|
log_sys_error("open", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, BLKSSZGET, &s) < 0) {
|
||||||
|
log_sys_error("ioctl BLKSSZGET", name);
|
||||||
|
if (close(fd))
|
||||||
|
log_sys_error("close", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close(fd))
|
||||||
|
log_sys_error("close", name);
|
||||||
|
|
||||||
|
*size = (uint32_t) s;
|
||||||
|
|
||||||
|
log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void dev_flush(struct device *dev)
|
||||||
|
{
|
||||||
|
if (!(dev->flags & DEV_REGULAR) && ioctl(dev->fd, BLKFLSBUF, 0) >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fsync(dev->fd) >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
const char *name;
|
||||||
|
int need_excl = 0, need_rw = 0;
|
||||||
|
|
||||||
|
if ((flags & O_ACCMODE) == O_RDWR)
|
||||||
|
need_rw = 1;
|
||||||
|
|
||||||
|
if ((flags & O_EXCL))
|
||||||
|
need_excl = 1;
|
||||||
|
|
||||||
|
if (dev->fd >= 0) {
|
||||||
|
if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
|
||||||
|
((dev->flags & DEV_OPENED_EXCL) || !need_excl)) {
|
||||||
|
dev->open_count++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->open_count && !need_excl) {
|
||||||
|
/* FIXME Ensure we never get here */
|
||||||
|
log_debug("WARNING: %s already opened read-only",
|
||||||
|
dev_name(dev));
|
||||||
|
dev->open_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_close_immediate(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memlock())
|
||||||
|
log_error("WARNING: dev_open(%s) called while suspended",
|
||||||
|
dev_name(dev));
|
||||||
|
|
||||||
|
if (dev->flags & DEV_REGULAR)
|
||||||
|
name = dev_name(dev);
|
||||||
|
else if (!(name = dev_name_confirmed(dev, quiet))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dev->flags & DEV_REGULAR) &&
|
||||||
|
((stat(name, &buf) < 0) || (buf.st_rdev != dev->dev))) {
|
||||||
|
log_error("%s: stat failed: Has device name changed?", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef O_DIRECT_SUPPORT
|
||||||
|
if (direct) {
|
||||||
|
if (!(dev->flags & DEV_O_DIRECT_TESTED))
|
||||||
|
dev->flags |= DEV_O_DIRECT;
|
||||||
|
|
||||||
|
if ((dev->flags & DEV_O_DIRECT))
|
||||||
|
flags |= O_DIRECT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef O_NOATIME
|
||||||
|
/* Don't update atime on device inodes */
|
||||||
|
if (!(dev->flags & DEV_REGULAR))
|
||||||
|
flags |= O_NOATIME;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((dev->fd = open(name, flags, 0777)) < 0) {
|
||||||
|
#ifdef O_DIRECT_SUPPORT
|
||||||
|
if (direct && !(dev->flags & DEV_O_DIRECT_TESTED)) {
|
||||||
|
flags &= ~O_DIRECT;
|
||||||
|
if ((dev->fd = open(name, flags, 0777)) >= 0) {
|
||||||
|
dev->flags &= ~DEV_O_DIRECT;
|
||||||
|
log_debug("%s: Not using O_DIRECT", name);
|
||||||
|
goto opened;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (quiet)
|
||||||
|
log_sys_debug("open", name);
|
||||||
|
else
|
||||||
|
log_sys_error("open", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef O_DIRECT_SUPPORT
|
||||||
|
opened:
|
||||||
|
if (direct)
|
||||||
|
dev->flags |= DEV_O_DIRECT_TESTED;
|
||||||
|
#endif
|
||||||
|
dev->open_count++;
|
||||||
|
dev->flags &= ~DEV_ACCESSED_W;
|
||||||
|
|
||||||
|
if (need_rw)
|
||||||
|
dev->flags |= DEV_OPENED_RW;
|
||||||
|
else
|
||||||
|
dev->flags &= ~DEV_OPENED_RW;
|
||||||
|
|
||||||
|
if (need_excl)
|
||||||
|
dev->flags |= DEV_OPENED_EXCL;
|
||||||
|
else
|
||||||
|
dev->flags &= ~DEV_OPENED_EXCL;
|
||||||
|
|
||||||
|
if (!(dev->flags & DEV_REGULAR) &&
|
||||||
|
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
|
||||||
|
log_error("%s: fstat failed: Has device name changed?", name);
|
||||||
|
dev_close_immediate(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef O_DIRECT_SUPPORT
|
||||||
|
if (!(dev->flags & DEV_REGULAR))
|
||||||
|
dev_flush(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((flags & O_CREAT) && !(flags & O_TRUNC))
|
||||||
|
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
|
||||||
|
|
||||||
|
list_add(&_open_devices, &dev->open_list);
|
||||||
|
|
||||||
|
log_debug("Opened %s %s%s%s", dev_name(dev),
|
||||||
|
dev->flags & DEV_OPENED_RW ? "RW" : "RO",
|
||||||
|
dev->flags & DEV_OPENED_EXCL ? " O_EXCL" : "",
|
||||||
|
dev->flags & DEV_O_DIRECT ? " O_DIRECT" : "");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_open_quiet(struct device *dev)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
|
||||||
|
|
||||||
|
return dev_open_flags(dev, flags, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_open(struct device *dev)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
|
||||||
|
|
||||||
|
return dev_open_flags(dev, flags, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_test_excl(struct device *dev)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
flags = vg_write_lock_held() ? O_RDWR : O_RDONLY;
|
||||||
|
flags |= O_EXCL;
|
||||||
|
|
||||||
|
r = dev_open_flags(dev, flags, 1, 1);
|
||||||
|
if (r)
|
||||||
|
dev_close_immediate(dev);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _close(struct device *dev)
|
||||||
|
{
|
||||||
|
if (close(dev->fd))
|
||||||
|
log_sys_error("close", dev_name(dev));
|
||||||
|
dev->fd = -1;
|
||||||
|
dev->block_size = -1;
|
||||||
|
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)->
|
||||||
|
str);
|
||||||
|
dm_free(dev->aliases.n);
|
||||||
|
dm_free(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dev_close(struct device *dev, int immediate)
|
||||||
|
{
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
|
if (dev->fd < 0) {
|
||||||
|
log_error("Attempt to close device '%s' "
|
||||||
|
"which is not open.", dev_name(dev));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef O_DIRECT_SUPPORT
|
||||||
|
if (dev->flags & DEV_ACCESSED_W)
|
||||||
|
dev_flush(dev);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (dev->open_count > 0)
|
||||||
|
dev->open_count--;
|
||||||
|
|
||||||
|
if (immediate && dev->open_count)
|
||||||
|
log_debug("%s: Immediate close attempt while still referenced",
|
||||||
|
dev_name(dev));
|
||||||
|
|
||||||
|
/* Close unless device is known to belong to a locked VG */
|
||||||
|
if (immediate ||
|
||||||
|
(dev->open_count < 1 &&
|
||||||
|
(!(info = info_from_pvid(dev->pvid)) ||
|
||||||
|
!info->vginfo ||
|
||||||
|
!vgname_is_locked(info->vginfo->vgname))))
|
||||||
|
_close(dev);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_close(struct device *dev)
|
||||||
|
{
|
||||||
|
return _dev_close(dev, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_close_immediate(struct device *dev)
|
||||||
|
{
|
||||||
|
return _dev_close(dev, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dev_close_all(void)
|
||||||
|
{
|
||||||
|
struct list *doh, *doht;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
list_iterate_safe(doh, doht, &_open_devices) {
|
||||||
|
dev = list_struct_base(doh, struct device, open_list);
|
||||||
|
if (dev->open_count < 1)
|
||||||
|
_close(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||||
|
{
|
||||||
|
struct device_area where;
|
||||||
|
|
||||||
|
if (!dev->open_count) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
where.dev = dev;
|
||||||
|
where.start = offset;
|
||||||
|
where.size = len;
|
||||||
|
|
||||||
|
return _aligned_io(&where, buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME If O_DIRECT can't extend file, dev_extend first; dev_truncate after.
|
||||||
|
* But fails if concurrent processes writing
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* FIXME pre-extend the file */
|
||||||
|
int dev_append(struct device *dev, size_t len, void *buffer)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!dev->open_count) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = dev_write(dev, dev->end, len, buffer);
|
||||||
|
dev->end += (uint64_t) len;
|
||||||
|
|
||||||
|
#ifndef O_DIRECT_SUPPORT
|
||||||
|
dev_flush(dev);
|
||||||
|
#endif
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
||||||
|
{
|
||||||
|
struct device_area where;
|
||||||
|
|
||||||
|
if (!dev->open_count) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
where.dev = dev;
|
||||||
|
where.start = offset;
|
||||||
|
where.size = len;
|
||||||
|
|
||||||
|
dev->flags |= DEV_ACCESSED_W;
|
||||||
|
|
||||||
|
return _aligned_io(&where, buffer, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set(struct device *dev, uint64_t offset, size_t len, int value)
|
||||||
|
{
|
||||||
|
size_t s;
|
||||||
|
char buffer[4096] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (!dev_open(dev)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((offset % SECTOR_SIZE) || (len % SECTOR_SIZE))
|
||||||
|
log_debug("Wiping %s at %" PRIu64 " length %" PRIsize_t,
|
||||||
|
dev_name(dev), offset, len);
|
||||||
|
else
|
||||||
|
log_debug("Wiping %s at sector %" PRIu64 " length %" PRIsize_t
|
||||||
|
" sectors", dev_name(dev), offset >> SECTOR_SHIFT,
|
||||||
|
len >> SECTOR_SHIFT);
|
||||||
|
|
||||||
|
memset(buffer, value, sizeof(buffer));
|
||||||
|
while (1) {
|
||||||
|
s = len > sizeof(buffer) ? sizeof(buffer) : len;
|
||||||
|
if (!dev_write(dev, offset, s, buffer))
|
||||||
|
break;
|
||||||
|
|
||||||
|
len -= s;
|
||||||
|
if (!len)
|
||||||
|
break;
|
||||||
|
|
||||||
|
offset += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->flags |= DEV_ACCESSED_W;
|
||||||
|
|
||||||
|
if (!dev_close(dev))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
return (len == 0);
|
||||||
|
}
|
||||||
71
lib/device/dev-md.c
Normal file
71
lib/device/dev-md.c
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Luca Berra
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU 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"
|
||||||
|
|
||||||
|
/* Lifted from <linux/raid/md_p.h> because of difficulty including it */
|
||||||
|
|
||||||
|
#define MD_SB_MAGIC 0xa92b4efc
|
||||||
|
#define MD_RESERVED_BYTES (64 * 1024)
|
||||||
|
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
|
||||||
|
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) \
|
||||||
|
- MD_RESERVED_SECTORS)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns -1 on error
|
||||||
|
*/
|
||||||
|
int dev_is_md(struct device *dev, uint64_t *sb)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
#ifdef linux
|
||||||
|
|
||||||
|
uint64_t size, sb_offset;
|
||||||
|
uint32_t md_magic;
|
||||||
|
|
||||||
|
if (!dev_get_size(dev, &size)) {
|
||||||
|
stack;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < MD_RESERVED_SECTORS * 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dev_open(dev)) {
|
||||||
|
stack;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
|
||||||
|
|
||||||
|
/* Check if it is an md component device. */
|
||||||
|
/* Version 1 is little endian; version 0.90.0 is machine endian */
|
||||||
|
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
|
||||||
|
((md_magic == xlate32(MD_SB_MAGIC)) ||
|
||||||
|
(md_magic == MD_SB_MAGIC))) {
|
||||||
|
if (sb)
|
||||||
|
*sb = sb_offset;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev_close(dev))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
282
lib/device/device.c
Normal file
282
lib/device/device.c
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "lvm-types.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
#include "filter.h"
|
||||||
|
#include "xlate.h"
|
||||||
|
|
||||||
|
/* See linux/genhd.h and fs/partitions/msdos */
|
||||||
|
|
||||||
|
#define PART_MAGIC 0xAA55
|
||||||
|
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
|
||||||
|
#define PART_OFFSET UINT64_C(0x1BE)
|
||||||
|
|
||||||
|
struct partition {
|
||||||
|
uint8_t boot_ind;
|
||||||
|
uint8_t head;
|
||||||
|
uint8_t sector;
|
||||||
|
uint8_t cyl;
|
||||||
|
uint8_t sys_ind; /* partition type */
|
||||||
|
uint8_t end_head;
|
||||||
|
uint8_t end_sector;
|
||||||
|
uint8_t end_cyl;
|
||||||
|
uint32_t start_sect;
|
||||||
|
uint32_t nr_sects;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
static int _is_partitionable(struct device *dev)
|
||||||
|
{
|
||||||
|
int parts = max_partitions(MAJOR(dev->dev));
|
||||||
|
|
||||||
|
if ((parts <= 1) || (MINOR(dev->dev) % parts))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _has_partition_table(struct device *dev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
unsigned p;
|
||||||
|
uint16_t buf[SECTOR_SIZE/sizeof(uint16_t)];
|
||||||
|
uint16_t *part_magic;
|
||||||
|
struct partition *part;
|
||||||
|
|
||||||
|
if (!dev_open(dev)) {
|
||||||
|
stack;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev_read(dev, UINT64_C(0), sizeof(buf), &buf)) {
|
||||||
|
stack;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Check for other types of partition table too */
|
||||||
|
|
||||||
|
/* Check for msdos partition table */
|
||||||
|
part_magic = buf + PART_MAGIC_OFFSET/sizeof(buf[0]);
|
||||||
|
if ((*part_magic == xlate16(PART_MAGIC))) {
|
||||||
|
part = (struct partition *) (buf + PART_OFFSET/sizeof(buf[0]));
|
||||||
|
for (p = 0; p < 4; p++, part++) {
|
||||||
|
/* Table is invalid if boot indicator not 0 or 0x80 */
|
||||||
|
if ((part->boot_ind & 0x7f)) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Must have at least one non-empty partition */
|
||||||
|
if (part->nr_sects)
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (!dev_close(dev))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_partitioned_dev(struct device *dev)
|
||||||
|
{
|
||||||
|
if (!_is_partitionable(dev))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return _has_partition_table(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/major.h>
|
||||||
|
#include <linux/genhd.h>
|
||||||
|
|
||||||
|
int _get_partition_type(struct dev_filter *filter, struct device *d);
|
||||||
|
|
||||||
|
#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
|
||||||
|
|
||||||
|
int is_extended_partition(struct device *d)
|
||||||
|
{
|
||||||
|
return (MINOR_PART(d) > 4) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device *dev_primary(struct dev_mgr *dm, struct device *d)
|
||||||
|
{
|
||||||
|
struct device *ret;
|
||||||
|
|
||||||
|
ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
|
||||||
|
/* FIXME: Needs replacing with a 'refresh' */
|
||||||
|
if (!ret) {
|
||||||
|
init_dev_scan(dm);
|
||||||
|
ret = dev_by_dev(dm, d->dev - MINOR_PART(dm, d));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int partition_type_is_lvm(struct dev_mgr *dm, struct device *d)
|
||||||
|
{
|
||||||
|
int pt;
|
||||||
|
|
||||||
|
pt = _get_partition_type(dm, d);
|
||||||
|
|
||||||
|
if (!pt) {
|
||||||
|
if (is_whole_disk(dm, d))
|
||||||
|
/* FIXME: Overloaded pt=0 in error cases */
|
||||||
|
return 1;
|
||||||
|
else {
|
||||||
|
log_error
|
||||||
|
("%s: missing partition table "
|
||||||
|
"on partitioned device", d->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_whole_disk(dm, d)) {
|
||||||
|
log_error("%s: looks to possess partition table", d->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check part type */
|
||||||
|
if (pt != LVM_PARTITION && pt != LVM_NEW_PARTITION) {
|
||||||
|
log_error("%s: invalid partition type 0x%x "
|
||||||
|
"(must be 0x%x)", d->name, pt, LVM_NEW_PARTITION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pt == LVM_PARTITION) {
|
||||||
|
log_error
|
||||||
|
("%s: old LVM partition type found - please change to 0x%x",
|
||||||
|
d->name, LVM_NEW_PARTITION);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _get_partition_type(struct dev_mgr *dm, struct device *d)
|
||||||
|
{
|
||||||
|
int pv_handle = -1;
|
||||||
|
struct device *primary;
|
||||||
|
ssize_t read_ret;
|
||||||
|
ssize_t bytes_read = 0;
|
||||||
|
char *buffer;
|
||||||
|
unsigned short *s_buffer;
|
||||||
|
struct partition *part;
|
||||||
|
loff_t offset = 0;
|
||||||
|
loff_t extended_offset = 0;
|
||||||
|
int part_sought;
|
||||||
|
int part_found = 0;
|
||||||
|
int first_partition = 1;
|
||||||
|
int extended_partition = 0;
|
||||||
|
int p;
|
||||||
|
|
||||||
|
if (!(primary = dev_primary(dm, d))) {
|
||||||
|
log_error
|
||||||
|
("Failed to find main device containing partition %s",
|
||||||
|
d->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(buffer = dm_malloc(SECTOR_SIZE))) {
|
||||||
|
log_error("Failed to allocate partition table buffer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get partition table */
|
||||||
|
if ((pv_handle = open(primary->name, O_RDONLY)) < 0) {
|
||||||
|
log_error("%s: open failed: %s", primary->name,
|
||||||
|
strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_buffer = (unsigned short *) buffer;
|
||||||
|
part = (struct partition *) (buffer + 0x1be);
|
||||||
|
part_sought = MINOR_PART(dm, d);
|
||||||
|
|
||||||
|
do {
|
||||||
|
bytes_read = 0;
|
||||||
|
|
||||||
|
if (llseek(pv_handle, offset * SECTOR_SIZE, SEEK_SET) == -1) {
|
||||||
|
log_error("%s: llseek failed: %s",
|
||||||
|
primary->name, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((bytes_read < SECTOR_SIZE) &&
|
||||||
|
(read_ret =
|
||||||
|
read(pv_handle, buffer + bytes_read,
|
||||||
|
SECTOR_SIZE - bytes_read)) != -1)
|
||||||
|
bytes_read += read_ret;
|
||||||
|
|
||||||
|
if (read_ret == -1) {
|
||||||
|
log_error("%s: read failed: %s", primary->name,
|
||||||
|
strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_buffer[255] == 0xAA55) {
|
||||||
|
if (is_whole_disk(dm, d))
|
||||||
|
return -1;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
extended_partition = 0;
|
||||||
|
|
||||||
|
/* Loop through primary partitions */
|
||||||
|
for (p = 0; p < 4; p++) {
|
||||||
|
if (part[p].sys_ind == DOS_EXTENDED_PARTITION ||
|
||||||
|
part[p].sys_ind == LINUX_EXTENDED_PARTITION
|
||||||
|
|| part[p].sys_ind == WIN98_EXTENDED_PARTITION) {
|
||||||
|
extended_partition = 1;
|
||||||
|
offset = extended_offset + part[p].start_sect;
|
||||||
|
if (extended_offset == 0)
|
||||||
|
extended_offset = part[p].start_sect;
|
||||||
|
if (first_partition == 1)
|
||||||
|
part_found++;
|
||||||
|
} else if (first_partition == 1) {
|
||||||
|
if (p == part_sought) {
|
||||||
|
if (part[p].sys_ind == 0) {
|
||||||
|
/* missing primary? */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
part_found++;
|
||||||
|
} else if (!part[p].sys_ind)
|
||||||
|
part_found++;
|
||||||
|
|
||||||
|
if (part_sought == part_found)
|
||||||
|
return part[p].sys_ind;
|
||||||
|
|
||||||
|
}
|
||||||
|
first_partition = 0;
|
||||||
|
}
|
||||||
|
while (extended_partition == 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
102
lib/device/device.h
Normal file
102
lib/device/device.h
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_DEVICE_H
|
||||||
|
#define _LVM_DEVICE_H
|
||||||
|
|
||||||
|
#include "uuid.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
|
||||||
|
#define DEV_REGULAR 0x00000002 /* Regular file? */
|
||||||
|
#define DEV_ALLOCED 0x00000004 /* dm_malloc used */
|
||||||
|
#define DEV_OPENED_RW 0x00000008 /* Opened RW */
|
||||||
|
#define DEV_OPENED_EXCL 0x00000010 /* Opened EXCL */
|
||||||
|
#define DEV_O_DIRECT 0x00000020 /* Use O_DIRECT */
|
||||||
|
#define DEV_O_DIRECT_TESTED 0x00000040 /* DEV_O_DIRECT is reliable */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All devices in LVM will be represented by one of these.
|
||||||
|
* pointer comparisons are valid.
|
||||||
|
*/
|
||||||
|
struct device {
|
||||||
|
struct list aliases; /* struct str_list from lvm-types.h */
|
||||||
|
dev_t dev;
|
||||||
|
|
||||||
|
/* private */
|
||||||
|
int fd;
|
||||||
|
int open_count;
|
||||||
|
int block_size;
|
||||||
|
uint32_t flags;
|
||||||
|
uint64_t end;
|
||||||
|
struct list open_list;
|
||||||
|
|
||||||
|
char pvid[ID_LEN + 1];
|
||||||
|
char _padding[7];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device_list {
|
||||||
|
struct list list;
|
||||||
|
struct device *dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device_area {
|
||||||
|
struct device *dev;
|
||||||
|
uint64_t start; /* Bytes */
|
||||||
|
uint64_t size; /* Bytes */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All io should use these routines.
|
||||||
|
*/
|
||||||
|
int dev_get_size(const struct device *dev, uint64_t *size);
|
||||||
|
int dev_get_sectsize(struct device *dev, uint32_t *size);
|
||||||
|
|
||||||
|
/* Use quiet version if device number could change e.g. when opening LV */
|
||||||
|
int dev_open(struct device *dev);
|
||||||
|
int dev_open_quiet(struct device *dev);
|
||||||
|
int dev_open_flags(struct device *dev, int flags, int direct, int quiet);
|
||||||
|
int dev_close(struct device *dev);
|
||||||
|
int dev_close_immediate(struct device *dev);
|
||||||
|
void dev_close_all(void);
|
||||||
|
int dev_test_excl(struct device *dev);
|
||||||
|
|
||||||
|
int dev_fd(struct device *dev);
|
||||||
|
const char *dev_name(const struct device *dev);
|
||||||
|
|
||||||
|
int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer);
|
||||||
|
int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer);
|
||||||
|
int dev_append(struct device *dev, size_t len, void *buffer);
|
||||||
|
int dev_set(struct device *dev, uint64_t offset, size_t len, int value);
|
||||||
|
void dev_flush(struct device *dev);
|
||||||
|
|
||||||
|
struct device *dev_create_file(const char *filename, struct device *dev,
|
||||||
|
struct str_list *alias, int use_malloc);
|
||||||
|
|
||||||
|
/* Return a valid device name from the alias list; NULL otherwise */
|
||||||
|
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 is_partitioned_dev(struct device *dev);
|
||||||
|
|
||||||
|
#endif
|
||||||
698
lib/display/display.c
Normal file
698
lib/display/display.c
Normal file
@@ -0,0 +1,698 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "activate.h"
|
||||||
|
#include "toolcontext.h"
|
||||||
|
#include "segtype.h"
|
||||||
|
|
||||||
|
#define SIZE_BUF 128
|
||||||
|
|
||||||
|
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
alloc_policy_t alloc;
|
||||||
|
const char *str;
|
||||||
|
} _policies[] = {
|
||||||
|
{
|
||||||
|
ALLOC_CONTIGUOUS, "contiguous"}, {
|
||||||
|
ALLOC_CLING, "cling"}, {
|
||||||
|
ALLOC_NORMAL, "normal"}, {
|
||||||
|
ALLOC_ANYWHERE, "anywhere"}, {
|
||||||
|
ALLOC_INHERIT, "inherit"}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int _num_policies = sizeof(_policies) / sizeof(*_policies);
|
||||||
|
|
||||||
|
uint64_t units_to_bytes(const char *units, char *unit_type)
|
||||||
|
{
|
||||||
|
char *ptr = NULL;
|
||||||
|
uint64_t v;
|
||||||
|
|
||||||
|
if (isdigit(*units)) {
|
||||||
|
v = (uint64_t) strtod(units, &ptr);
|
||||||
|
if (ptr == units)
|
||||||
|
return 0;
|
||||||
|
units = ptr;
|
||||||
|
} else
|
||||||
|
v = 1;
|
||||||
|
|
||||||
|
if (v == 1)
|
||||||
|
*unit_type = *units;
|
||||||
|
else
|
||||||
|
*unit_type = 'U';
|
||||||
|
|
||||||
|
switch (*units) {
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
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 'k':
|
||||||
|
v *= KILO;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
v *= KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
v *= KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
v *= KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
v *= KILO * KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
v *= KILO * KILO * KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
#undef KILO
|
||||||
|
#define KILO UINT64_C(1000)
|
||||||
|
case 'K':
|
||||||
|
v *= KILO;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
v *= KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
v *= KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
v *= KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
v *= KILO * KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
v *= KILO * KILO * KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
#undef KILO
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*(units + 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_alloc_string(alloc_policy_t alloc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < _num_policies; i++)
|
||||||
|
if (_policies[i].alloc == alloc)
|
||||||
|
return _policies[i].str;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
alloc_policy_t get_alloc_from_string(const char *str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < _num_policies; i++)
|
||||||
|
if (!strcmp(_policies[i].str, str))
|
||||||
|
return _policies[i].alloc;
|
||||||
|
|
||||||
|
/* Special case for old metadata */
|
||||||
|
if(!strcmp("next free", str))
|
||||||
|
return ALLOC_NORMAL;
|
||||||
|
|
||||||
|
log_error("Unrecognised allocation policy %s", str);
|
||||||
|
return ALLOC_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Size supplied in sectors */
|
||||||
|
static const char *_display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
|
||||||
|
{
|
||||||
|
int 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"},
|
||||||
|
{" ", " ", " "},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
|
||||||
|
log_error("no memory for size display buffer");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (size == UINT64_C(0)) {
|
||||||
|
sprintf(size_buf, "0%s", suffix ? size_str[s][sl] : "");
|
||||||
|
return size_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s < 10) {
|
||||||
|
byte = cmd->current_settings.unit_factor;
|
||||||
|
size *= UINT64_C(512);
|
||||||
|
} else {
|
||||||
|
size /= 2;
|
||||||
|
suffix = 1;
|
||||||
|
if (cmd->current_settings.unit_type == 'H')
|
||||||
|
units = UINT64_C(1000);
|
||||||
|
else
|
||||||
|
units = UINT64_C(1024);
|
||||||
|
byte = units * units * units * units * units;
|
||||||
|
s = 0;
|
||||||
|
while (size_str[s] && size < byte)
|
||||||
|
s++, byte /= units;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Make precision configurable */
|
||||||
|
switch(toupper((int) cmd->current_settings.unit_type)) {
|
||||||
|
case 'B':
|
||||||
|
case 'S':
|
||||||
|
precision = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
precision = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
|
||||||
|
(double) size / byte, suffix ? size_str[s][sl] : "");
|
||||||
|
|
||||||
|
return size_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *display_size_long(struct cmd_context *cmd, uint64_t size)
|
||||||
|
{
|
||||||
|
return _display_size(cmd, size, SIZE_LONG);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *display_size_units(struct cmd_context *cmd, uint64_t size)
|
||||||
|
{
|
||||||
|
return _display_size(cmd, size, SIZE_UNIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *display_size(struct cmd_context *cmd, uint64_t size)
|
||||||
|
{
|
||||||
|
return _display_size(cmd, size, SIZE_SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pvdisplay_colons(struct physical_volume *pv)
|
||||||
|
{
|
||||||
|
char uuid[64] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (!pv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
|
||||||
|
stack;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print("%s:%s:%" PRIu64 ":-1:%u:%u:-1:%" PRIu32 ":%u:%u:%u:%s",
|
||||||
|
dev_name(pv->dev), pv->vg_name, pv->size,
|
||||||
|
/* FIXME pv->pv_number, Derive or remove? */
|
||||||
|
pv->status, /* FIXME Support old or new format here? */
|
||||||
|
pv->status & ALLOCATABLE_PV, /* FIXME remove? */
|
||||||
|
/* FIXME pv->lv_cur, Remove? */
|
||||||
|
pv->pe_size / 2,
|
||||||
|
pv->pe_count,
|
||||||
|
pv->pe_count - pv->pe_alloc_count,
|
||||||
|
pv->pe_alloc_count, *uuid ? uuid : "none");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Include label fields */
|
||||||
|
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
||||||
|
void *handle __attribute((unused)))
|
||||||
|
{
|
||||||
|
char uuid[64] __attribute((aligned(8)));
|
||||||
|
const char *size;
|
||||||
|
|
||||||
|
uint32_t pe_free;
|
||||||
|
|
||||||
|
if (!pv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
|
||||||
|
stack;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print("--- %sPhysical volume ---", pv->pe_size ? "" : "NEW ");
|
||||||
|
log_print("PV Name %s", dev_name(pv->dev));
|
||||||
|
log_print("VG Name %s%s", pv->vg_name,
|
||||||
|
pv->status & EXPORTED_VG ? " (exported)" : "");
|
||||||
|
|
||||||
|
size = display_size(cmd, (uint64_t) pv->size);
|
||||||
|
if (pv->pe_size && pv->pe_count) {
|
||||||
|
|
||||||
|
/******** FIXME display LVM on-disk data size
|
||||||
|
size2 = display_size(cmd, pv->size);
|
||||||
|
********/
|
||||||
|
|
||||||
|
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
|
||||||
|
size,
|
||||||
|
display_size(cmd, (pv->size -
|
||||||
|
(uint64_t) pv->pe_count * pv->pe_size)));
|
||||||
|
|
||||||
|
} else
|
||||||
|
log_print("PV Size %s", size);
|
||||||
|
|
||||||
|
/* PV number not part of LVM2 design
|
||||||
|
log_print("PV# %u", pv->pv_number);
|
||||||
|
*/
|
||||||
|
|
||||||
|
pe_free = pv->pe_count - pv->pe_alloc_count;
|
||||||
|
if (pv->pe_count && (pv->status & ALLOCATABLE_PV))
|
||||||
|
log_print("Allocatable yes %s",
|
||||||
|
(!pe_free && pv->pe_count) ? "(but full)" : "");
|
||||||
|
else
|
||||||
|
log_print("Allocatable NO");
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
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(struct cmd_context *cmd __attribute((unused)),
|
||||||
|
struct volume_group *vg __attribute((unused)),
|
||||||
|
struct physical_volume *pv,
|
||||||
|
void *handle __attribute((unused)))
|
||||||
|
{
|
||||||
|
char uuid[64] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (!pv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!id_write_format(&pv->id, uuid, sizeof(uuid))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print("PV Name %s ", dev_name(pv->dev));
|
||||||
|
/* FIXME pv->pv_number); */
|
||||||
|
log_print("PV UUID %s", *uuid ? uuid : "none");
|
||||||
|
log_print("PV Status %sallocatable",
|
||||||
|
(pv->status & ALLOCATABLE_PV) ? "" : "NOT ");
|
||||||
|
log_print("Total PE / Free PE %u / %u",
|
||||||
|
pv->pe_count, pv->pe_count - pv->pe_alloc_count);
|
||||||
|
|
||||||
|
log_print(" ");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lvdisplay_colons(struct logical_volume *lv)
|
||||||
|
{
|
||||||
|
int inkernel;
|
||||||
|
struct lvinfo info;
|
||||||
|
inkernel = lv_info(lv->vg->cmd, lv, &info, 1) && info.exists;
|
||||||
|
|
||||||
|
log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
|
||||||
|
lv->vg->cmd->dev_dir,
|
||||||
|
lv->vg->name,
|
||||||
|
lv->name,
|
||||||
|
lv->vg->name,
|
||||||
|
(lv->status & (LVM_READ | LVM_WRITE)) >> 8, inkernel ? 1 : 0,
|
||||||
|
/* FIXME lv->lv_number, */
|
||||||
|
inkernel ? info.open_count : 0, lv->size, lv->le_count,
|
||||||
|
/* 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, struct logical_volume *lv,
|
||||||
|
void *handle __attribute((unused)))
|
||||||
|
{
|
||||||
|
struct lvinfo info;
|
||||||
|
int inkernel, snap_active = 0;
|
||||||
|
char uuid[64] __attribute((aligned(8)));
|
||||||
|
struct lv_segment *snap_seg = NULL;
|
||||||
|
float snap_percent; /* fused, fsize; */
|
||||||
|
|
||||||
|
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inkernel = lv_info(cmd, lv, &info, 1) && info.exists;
|
||||||
|
|
||||||
|
log_print("--- Logical volume ---");
|
||||||
|
|
||||||
|
log_print("LV Name %s%s/%s", lv->vg->cmd->dev_dir,
|
||||||
|
lv->vg->name, lv->name);
|
||||||
|
log_print("VG Name %s", lv->vg->name);
|
||||||
|
|
||||||
|
log_print("LV UUID %s", uuid);
|
||||||
|
|
||||||
|
log_print("LV Write Access %s",
|
||||||
|
(lv->status & LVM_WRITE) ? "read/write" : "read only");
|
||||||
|
|
||||||
|
if (lv_is_origin(lv)) {
|
||||||
|
log_print("LV snapshot status source of");
|
||||||
|
|
||||||
|
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_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_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_active = 0;
|
||||||
|
|
||||||
|
log_print("LV snapshot status %s destination for %s%s/%s",
|
||||||
|
(snap_active > 0) ? "active" : "INACTIVE",
|
||||||
|
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||||
|
snap_seg->origin->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inkernel && info.suspended)
|
||||||
|
log_print("LV Status suspended");
|
||||||
|
else
|
||||||
|
log_print("LV Status %savailable",
|
||||||
|
inkernel ? "" : "NOT ");
|
||||||
|
|
||||||
|
/********* FIXME lv_number
|
||||||
|
log_print("LV # %u", lv->lv_number + 1);
|
||||||
|
************/
|
||||||
|
|
||||||
|
if (inkernel)
|
||||||
|
log_print("# open %u", info.open_count);
|
||||||
|
|
||||||
|
log_print("LV Size %s",
|
||||||
|
display_size(cmd,
|
||||||
|
snap_seg ? snap_seg->origin->size : lv->size));
|
||||||
|
|
||||||
|
log_print("Current LE %u",
|
||||||
|
snap_seg ? snap_seg->origin->le_count : lv->le_count);
|
||||||
|
|
||||||
|
if (snap_seg) {
|
||||||
|
log_print("COW-table size %s",
|
||||||
|
display_size(cmd, (uint64_t) lv->size));
|
||||||
|
log_print("COW-table LE %u", lv->le_count);
|
||||||
|
|
||||||
|
if (snap_active)
|
||||||
|
log_print("Allocated to snapshot %.2f%% ", snap_percent);
|
||||||
|
|
||||||
|
log_print("Snapshot chunk size %s",
|
||||||
|
display_size(cmd, (uint64_t) snap_seg->chunk_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print("Segments %u", list_size(&lv->segments));
|
||||||
|
|
||||||
|
/********* FIXME Stripes & stripesize for each segment
|
||||||
|
log_print("Stripe size (KByte) %u", lv->stripesize / 2);
|
||||||
|
***********/
|
||||||
|
|
||||||
|
log_print("Allocation %s", get_alloc_string(lv->alloc));
|
||||||
|
log_print("Read ahead sectors %u", lv->read_ahead);
|
||||||
|
|
||||||
|
if (lv->status & FIXED_MINOR) {
|
||||||
|
if (lv->major >= 0)
|
||||||
|
log_print("Persistent major %d", lv->major);
|
||||||
|
log_print("Persistent minor %d", lv->minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inkernel)
|
||||||
|
log_print("Block device %d:%d", info.major,
|
||||||
|
info.minor);
|
||||||
|
|
||||||
|
log_print(" ");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
|
||||||
|
{
|
||||||
|
switch (seg_type(seg, s)) {
|
||||||
|
case AREA_PV:
|
||||||
|
/* FIXME Re-check the conditions for 'Missing' */
|
||||||
|
log_print("%sPhysical volume\t%s", pre,
|
||||||
|
seg_pv(seg, s) ?
|
||||||
|
dev_name(seg_dev(seg, s)) :
|
||||||
|
"Missing");
|
||||||
|
|
||||||
|
if (seg_pv(seg, s))
|
||||||
|
log_print("%sPhysical extents\t%d to %d", pre,
|
||||||
|
seg_pe(seg, s),
|
||||||
|
seg_pe(seg, s) + seg->area_len - 1);
|
||||||
|
break;
|
||||||
|
case AREA_LV:
|
||||||
|
log_print("%sLogical volume\t%s", pre,
|
||||||
|
seg_lv(seg, s) ?
|
||||||
|
seg_lv(seg, s)->name : "Missing");
|
||||||
|
|
||||||
|
if (seg_lv(seg, s))
|
||||||
|
log_print("%sLogical extents\t%d to %d", pre,
|
||||||
|
seg_le(seg, s),
|
||||||
|
seg_le(seg, s) + seg->area_len - 1);
|
||||||
|
break;
|
||||||
|
case AREA_UNASSIGNED:
|
||||||
|
log_print("%sUnassigned area", pre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int lvdisplay_segments(struct logical_volume *lv)
|
||||||
|
{
|
||||||
|
struct lv_segment *seg;
|
||||||
|
|
||||||
|
log_print("--- Segments ---");
|
||||||
|
|
||||||
|
list_iterate_items(seg, &lv->segments) {
|
||||||
|
log_print("Logical extent %u to %u:",
|
||||||
|
seg->le, seg->le + seg->len - 1);
|
||||||
|
|
||||||
|
log_print(" Type\t\t%s", seg->segtype->ops->name(seg));
|
||||||
|
|
||||||
|
if (seg->segtype->ops->display)
|
||||||
|
seg->segtype->ops->display(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print(" ");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vgdisplay_extents(struct volume_group *vg __attribute((unused)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vgdisplay_full(struct volume_group *vg)
|
||||||
|
{
|
||||||
|
uint32_t access;
|
||||||
|
uint32_t active_pvs;
|
||||||
|
char uuid[64] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (vg->status & PARTIAL_VG)
|
||||||
|
active_pvs = list_size(&vg->pvs);
|
||||||
|
else
|
||||||
|
active_pvs = vg->pv_count;
|
||||||
|
|
||||||
|
log_print("--- Volume group ---");
|
||||||
|
log_print("VG Name %s", vg->name);
|
||||||
|
log_print("System ID %s", vg->system_id);
|
||||||
|
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));
|
||||||
|
log_print("Metadata Sequence No %d", vg->seqno);
|
||||||
|
}
|
||||||
|
access = 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" : "");
|
||||||
|
log_print("VG Status %s%sresizable",
|
||||||
|
vg->status & EXPORTED_VG ? "exported/" : "",
|
||||||
|
vg->status & RESIZEABLE_VG ? "" : "NOT ");
|
||||||
|
/* vg number not part of LVM2 design
|
||||||
|
log_print ("VG # %u\n", vg->vg_number);
|
||||||
|
*/
|
||||||
|
if (vg->status & CLUSTERED) {
|
||||||
|
log_print("Clustered yes");
|
||||||
|
log_print("Shared %s",
|
||||||
|
vg->status & SHARED ? "yes" : "no");
|
||||||
|
}
|
||||||
|
log_print("MAX LV %u", vg->max_lv);
|
||||||
|
log_print("Cur LV %u", vg->lv_count + vg->snapshot_count);
|
||||||
|
log_print("Open LV %u", lvs_in_vg_opened(vg));
|
||||||
|
/****** FIXME Max LV Size
|
||||||
|
log_print ( "MAX LV Size %s",
|
||||||
|
( s1 = display_size ( LVM_LV_SIZE_MAX(vg))));
|
||||||
|
free ( s1);
|
||||||
|
*********/
|
||||||
|
log_print("Max PV %u", vg->max_pv);
|
||||||
|
log_print("Cur PV %u", vg->pv_count);
|
||||||
|
log_print("Act PV %u", active_pvs);
|
||||||
|
|
||||||
|
log_print("VG Size %s",
|
||||||
|
display_size(vg->cmd,
|
||||||
|
(uint64_t) vg->extent_count * vg->extent_size));
|
||||||
|
|
||||||
|
log_print("PE Size %s",
|
||||||
|
display_size(vg->cmd, (uint64_t) vg->extent_size));
|
||||||
|
|
||||||
|
log_print("Total PE %u", vg->extent_count);
|
||||||
|
|
||||||
|
log_print("Alloc PE / Size %u / %s",
|
||||||
|
vg->extent_count - vg->free_count,
|
||||||
|
display_size(vg->cmd,
|
||||||
|
((uint64_t) vg->extent_count - vg->free_count) *
|
||||||
|
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));
|
||||||
|
|
||||||
|
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
|
||||||
|
stack;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print("VG UUID %s", uuid);
|
||||||
|
log_print(" ");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vgdisplay_colons(struct volume_group *vg)
|
||||||
|
{
|
||||||
|
uint32_t active_pvs;
|
||||||
|
const char *access;
|
||||||
|
char uuid[64] __attribute((aligned(8)));
|
||||||
|
|
||||||
|
if (vg->status & PARTIAL_VG)
|
||||||
|
active_pvs = list_size(&vg->pvs);
|
||||||
|
else
|
||||||
|
active_pvs = vg->pv_count;
|
||||||
|
|
||||||
|
switch (vg->status & (LVM_READ | LVM_WRITE)) {
|
||||||
|
case LVM_READ | LVM_WRITE:
|
||||||
|
access = "r/w";
|
||||||
|
break;
|
||||||
|
case LVM_READ:
|
||||||
|
access = "r";
|
||||||
|
break;
|
||||||
|
case LVM_WRITE:
|
||||||
|
access = "w";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
access = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
|
||||||
|
stack;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_print("%s:%s:%d:-1:%u:%u:%u:-1:%u:%u:%u:%" PRIu64 ":%" PRIu32
|
||||||
|
":%u:%u:%u:%s",
|
||||||
|
vg->name,
|
||||||
|
access,
|
||||||
|
vg->status,
|
||||||
|
/* internal volume group number; obsolete */
|
||||||
|
vg->max_lv,
|
||||||
|
vg->lv_count,
|
||||||
|
lvs_in_vg_opened(vg),
|
||||||
|
/* FIXME: maximum logical volume size */
|
||||||
|
vg->max_pv,
|
||||||
|
vg->pv_count,
|
||||||
|
active_pvs,
|
||||||
|
(uint64_t) vg->extent_count * (vg->extent_size / 2),
|
||||||
|
vg->extent_size / 2,
|
||||||
|
vg->extent_count,
|
||||||
|
vg->extent_count - vg->free_count,
|
||||||
|
vg->free_count,
|
||||||
|
uuid[0] ? uuid : "none");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vgdisplay_short(struct volume_group *vg)
|
||||||
|
{
|
||||||
|
log_print("\"%s\" %-9s [%-9s used / %s free]", vg->name,
|
||||||
|
/********* FIXME if "open" print "/used" else print "/idle"??? ******/
|
||||||
|
display_size(vg->cmd,
|
||||||
|
(uint64_t) vg->extent_count * vg->extent_size),
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_formats(struct cmd_context *cmd)
|
||||||
|
{
|
||||||
|
struct format_type *fmt;
|
||||||
|
|
||||||
|
list_iterate_items(fmt, &cmd->formats) {
|
||||||
|
log_print("%s", fmt->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_segtypes(struct cmd_context *cmd)
|
||||||
|
{
|
||||||
|
struct segment_type *segtype;
|
||||||
|
|
||||||
|
list_iterate_items(segtype, &cmd->segtypes) {
|
||||||
|
log_print("%s", segtype->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
58
lib/display/display.h
Normal file
58
lib/display/display.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LVM_DISPLAY_H
|
||||||
|
#define _LVM_DISPLAY_H
|
||||||
|
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint64_t units_to_bytes(const char *units, char *unit_type);
|
||||||
|
|
||||||
|
/* Specify size in KB */
|
||||||
|
const char *display_size(struct cmd_context *cmd, uint64_t size);
|
||||||
|
const char *display_size_long(struct cmd_context *cmd, uint64_t size);
|
||||||
|
const char *display_size_units(struct cmd_context *cmd, uint64_t size);
|
||||||
|
|
||||||
|
char *display_uuid(char *uuidstr);
|
||||||
|
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre);
|
||||||
|
|
||||||
|
void pvdisplay_colons(struct physical_volume *pv);
|
||||||
|
void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
||||||
|
void *handle);
|
||||||
|
int pvdisplay_short(struct cmd_context *cmd, struct volume_group *vg,
|
||||||
|
struct physical_volume *pv, void *handle);
|
||||||
|
|
||||||
|
void lvdisplay_colons(struct logical_volume *lv);
|
||||||
|
int lvdisplay_segments(struct logical_volume *lv);
|
||||||
|
int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||||
|
void *handle);
|
||||||
|
|
||||||
|
void vgdisplay_extents(struct volume_group *vg);
|
||||||
|
void vgdisplay_full(struct volume_group *vg);
|
||||||
|
void vgdisplay_colons(struct volume_group *vg);
|
||||||
|
void vgdisplay_short(struct volume_group *vg);
|
||||||
|
|
||||||
|
void display_formats(struct cmd_context *cmd);
|
||||||
|
void display_segtypes(struct cmd_context *cmd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocation policy display conversion routines.
|
||||||
|
*/
|
||||||
|
const char *get_alloc_string(alloc_policy_t alloc);
|
||||||
|
alloc_policy_t get_alloc_from_string(const char *str);
|
||||||
|
|
||||||
|
#endif
|
||||||
112
lib/error/errseg.c
Normal file
112
lib/error/errseg.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of LVM2.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use,
|
||||||
|
* modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
* of the GNU General Public License v.2.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lib.h"
|
||||||
|
#include "toolcontext.h"
|
||||||
|
#include "segtype.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "text_export.h"
|
||||||
|
#include "text_import.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "str_list.h"
|
||||||
|
#include "targets.h"
|
||||||
|
#include "lvm-string.h"
|
||||||
|
#include "activate.h"
|
||||||
|
#include "str_list.h"
|
||||||
|
|
||||||
|
static const char *_errseg_name(const struct lv_segment *seg)
|
||||||
|
{
|
||||||
|
return seg->segtype->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _errseg_merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
||||||
|
{
|
||||||
|
seg1->len += seg2->len;
|
||||||
|
seg1->area_len += seg2->area_len;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEVMAPPER_SUPPORT
|
||||||
|
static int _errseg_add_target_line(struct dev_manager *dm __attribute((unused)),
|
||||||
|
struct dm_pool *mem __attribute((unused)),
|
||||||
|
struct cmd_context *cmd __attribute((unused)),
|
||||||
|
void **target_state __attribute((unused)),
|
||||||
|
struct lv_segment *seg __attribute((unused)),
|
||||||
|
struct dm_tree_node *node, uint64_t len,
|
||||||
|
uint32_t *pvmove_mirror_count __attribute((unused)))
|
||||||
|
{
|
||||||
|
return dm_tree_node_add_error_target(node, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _errseg_target_present(const struct lv_segment *seg __attribute((unused)))
|
||||||
|
{
|
||||||
|
static int _errseg_checked = 0;
|
||||||
|
static int _errseg_present = 0;
|
||||||
|
|
||||||
|
/* Reported truncated in older kernels */
|
||||||
|
if (!_errseg_checked &&
|
||||||
|
(target_present("error", 0) || target_present("erro", 0)))
|
||||||
|
_errseg_present = 1;
|
||||||
|
|
||||||
|
_errseg_checked = 1;
|
||||||
|
return _errseg_present;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int _errseg_modules_needed(struct dm_pool *mem,
|
||||||
|
const struct lv_segment *seg,
|
||||||
|
struct list *modules)
|
||||||
|
{
|
||||||
|
if (!str_list_add(mem, modules, "error")) {
|
||||||
|
log_error("error module string list allocation failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _errseg_destroy(const struct segment_type *segtype)
|
||||||
|
{
|
||||||
|
dm_free((void *)segtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct segtype_handler _error_ops = {
|
||||||
|
.name = _errseg_name,
|
||||||
|
.merge_segments = _errseg_merge_segments,
|
||||||
|
#ifdef DEVMAPPER_SUPPORT
|
||||||
|
.add_target_line = _errseg_add_target_line,
|
||||||
|
.target_present = _errseg_target_present,
|
||||||
|
#endif
|
||||||
|
.modules_needed = _errseg_modules_needed,
|
||||||
|
.destroy = _errseg_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct segment_type *init_error_segtype(struct cmd_context *cmd)
|
||||||
|
{
|
||||||
|
struct segment_type *segtype = dm_malloc(sizeof(*segtype));
|
||||||
|
|
||||||
|
if (!segtype)
|
||||||
|
return_NULL;
|
||||||
|
|
||||||
|
segtype->cmd = cmd;
|
||||||
|
segtype->ops = &_error_ops;
|
||||||
|
segtype->name = "error";
|
||||||
|
segtype->private = NULL;
|
||||||
|
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
|
||||||
|
|
||||||
|
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||||
|
|
||||||
|
return segtype;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user