mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-05 16:23:51 +03:00
Compare commits
475 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
0
CONTRIBUTORS
Normal file
0
CONTRIBUTORS
Normal file
12
Makefile.in
12
Makefile.in
@@ -22,11 +22,13 @@ ifeq ("@INTL@", "yes")
|
|||||||
SUBDIRS += po
|
SUBDIRS += po
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SUBDIRS += lib tools
|
SUBDIRS += lib tools daemons
|
||||||
|
|
||||||
ifeq ($(MAKECMDGOALS),distclean)
|
ifeq ($(MAKECMDGOALS),distclean)
|
||||||
SUBDIRS += lib/format1 \
|
SUBDIRS += daemons/clvmd \
|
||||||
|
lib/format1 \
|
||||||
lib/format_pool \
|
lib/format_pool \
|
||||||
|
lib/locking \
|
||||||
lib/mirror \
|
lib/mirror \
|
||||||
lib/snapshot \
|
lib/snapshot \
|
||||||
po \
|
po \
|
||||||
@@ -35,14 +37,16 @@ endif
|
|||||||
|
|
||||||
include make.tmpl
|
include make.tmpl
|
||||||
|
|
||||||
|
daemons: lib
|
||||||
lib: include
|
lib: include
|
||||||
tools: lib
|
tools: lib
|
||||||
po: lib tools
|
po: tools daemons
|
||||||
|
|
||||||
ifeq ("@INTL@", "yes")
|
ifeq ("@INTL@", "yes")
|
||||||
lib.pofile: include.pofile
|
lib.pofile: include.pofile
|
||||||
tools.pofile: lib.pofile
|
tools.pofile: lib.pofile
|
||||||
po.pofile: lib.pofile tools.pofile
|
daemons.pofile: lib.pofile
|
||||||
|
po.pofile: tools.pofile daemons.pofile
|
||||||
pofile: po.pofile
|
pofile: po.pofile
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
4
README
4
README
@@ -9,8 +9,8 @@ Installation instructions are in INSTALL.
|
|||||||
There is no warranty - see COPYING and COPYING.LIB.
|
There is no warranty - see COPYING and COPYING.LIB.
|
||||||
|
|
||||||
Tarballs are available from:
|
Tarballs are available from:
|
||||||
ftp://ftp.sistina.com/pub/LVM2/tools/
|
ftp://sources.redhat.com/pub/lvm2/
|
||||||
ftp://ftp.sistina.com/pub/LVM2/device-mapper/
|
ftp://sources.redhat.com/pub/dm/
|
||||||
|
|
||||||
To access the CVS tree use:
|
To access the CVS tree use:
|
||||||
cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
|
cvs -d :pserver:cvs@sources.redhat.com:/cvs/lvm2 login
|
||||||
|
|||||||
386
WHATS_NEW
386
WHATS_NEW
@@ -1,5 +1,389 @@
|
|||||||
Version 2.00.17 -
|
Version 2.02.00 -
|
||||||
|
===================================
|
||||||
|
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 read-only GFS pool support.
|
||||||
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
|
Add lvm2create_initrd script from http://poochiereds.net/svn/lvm2/
|
||||||
Fix rounding of large diplayed sizes.
|
Fix rounding of large diplayed sizes.
|
||||||
|
|||||||
72
WHATS_NEW_DM
72
WHATS_NEW_DM
@@ -1,5 +1,75 @@
|
|||||||
Version 1.00.18
|
Version 1.02.00 -
|
||||||
=============================
|
=============================
|
||||||
|
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.
|
Add target message-passing ioctl.
|
||||||
|
|
||||||
Version 1.00.17 - 17 Apr 2004
|
Version 1.00.17 - 17 Apr 2004
|
||||||
|
|||||||
423
configure.in
423
configure.in
@@ -1,29 +1,64 @@
|
|||||||
##
|
##
|
||||||
## Copyright 1999-2000 Sistina Software, Inc.
|
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
## Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
##
|
##
|
||||||
## This is free software released under the GNU General Public License.
|
## This file is part of the LVM2.
|
||||||
## There is no warranty for this software. See the file COPYING for
|
|
||||||
## details.
|
|
||||||
##
|
##
|
||||||
## See the file CONTRIBUTORS for a list of contributors.
|
## 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.
|
||||||
##
|
##
|
||||||
## This file is maintained by:
|
## You should have received a copy of the GNU General Public License
|
||||||
## AJ Lewis <lewis@sistina.com>
|
## along with this program; if not, write to the Free Software Foundation,
|
||||||
##
|
## Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
## File name: configure.in
|
|
||||||
##
|
|
||||||
## Description: Input file for autoconf. Generates the configure script
|
|
||||||
## that tries to keep everything nice and portable. It also
|
|
||||||
## simplifies distribution package building considerably.
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
AC_PREREQ(2.53)
|
||||||
|
################################################################################
|
||||||
|
dnl -- Process this file with autoconf to produce a configure script.
|
||||||
AC_INIT(lib/device/dev-cache.h)
|
AC_INIT(lib/device/dev-cache.h)
|
||||||
|
|
||||||
dnl setup the directory where autoconf has auxilary files
|
################################################################################
|
||||||
|
dnl -- Setup the directory where autoconf has auxilary files
|
||||||
AC_CONFIG_AUX_DIR(autoconf)
|
AC_CONFIG_AUX_DIR(autoconf)
|
||||||
|
|
||||||
dnl Checks for programs.
|
################################################################################
|
||||||
|
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"
|
||||||
|
SOFLAG="-shared"
|
||||||
|
DEVMAPPER=yes
|
||||||
|
ODIRECT=yes
|
||||||
|
SELINUX=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"
|
||||||
|
SOFLAG="-dynamiclib"
|
||||||
|
DEVMAPPER=yes
|
||||||
|
ODIRECT=no
|
||||||
|
SELINUX=no
|
||||||
|
CLUSTER=none
|
||||||
|
FSADM=no ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
dnl -- Checks for programs.
|
||||||
AC_PROG_AWK
|
AC_PROG_AWK
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
@@ -31,213 +66,310 @@ AC_PROG_LN_S
|
|||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
AC_PROG_RANLIB
|
AC_PROG_RANLIB
|
||||||
|
|
||||||
dnl Checks for header files.
|
################################################################################
|
||||||
|
dnl -- Checks for header files.
|
||||||
AC_HEADER_DIRENT
|
AC_HEADER_DIRENT
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS(fcntl.h malloc.h sys/ioctl.h unistd.h)
|
AC_HEADER_SYS_WAIT
|
||||||
|
AC_HEADER_TIME
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
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_CONST
|
||||||
AC_C_INLINE
|
AC_C_INLINE
|
||||||
AC_TYPE_OFF_T
|
AC_TYPE_OFF_T
|
||||||
AC_TYPE_PID_T
|
AC_TYPE_PID_T
|
||||||
AC_TYPE_SIZE_T
|
AC_TYPE_SIZE_T
|
||||||
|
AC_TYPE_MODE_T
|
||||||
AC_STRUCT_ST_RDEV
|
AC_STRUCT_ST_RDEV
|
||||||
AC_HEADER_TIME
|
AC_STRUCT_TM
|
||||||
|
|
||||||
dnl Get system type
|
################################################################################
|
||||||
AC_CANONICAL_SYSTEM
|
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
|
||||||
|
|
||||||
case "$host_os" in
|
################################################################################
|
||||||
linux*)
|
dnl -- Prefix is /usr by default, the exec_prefix default is setup later
|
||||||
CFLAGS=
|
|
||||||
CLDFLAGS="-Wl,--version-script,.export.sym"
|
|
||||||
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
|
||||||
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
|
||||||
LD_DEPS=".export.sym"
|
|
||||||
LD_FLAGS="-Wl,--export-dynamic"
|
|
||||||
SOFLAG="-shared"
|
|
||||||
DEVMAPPER=yes
|
|
||||||
ODIRECT=yes ;;
|
|
||||||
darwin*)
|
|
||||||
CFLAGS="-no-cpp-precomp -fno-common"
|
|
||||||
CLDFLAGS=
|
|
||||||
CLDWHOLEARCHIVE="-all_load"
|
|
||||||
CLDNOWHOLEARCHIVE=
|
|
||||||
LD_DEPS=
|
|
||||||
LD_FLAGS=
|
|
||||||
SOFLAG="-dynamiclib"
|
|
||||||
DEVMAPPER=no
|
|
||||||
ODIRECT=no ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
dnl -- prefix is /usr by default, the exec_prefix default is setup later
|
|
||||||
AC_PREFIX_DEFAULT(/usr)
|
AC_PREFIX_DEFAULT(/usr)
|
||||||
|
|
||||||
OWNER="root"
|
################################################################################
|
||||||
GROUP="root"
|
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"
|
||||||
|
|
||||||
dnl -- setup the ownership of the files
|
|
||||||
AC_ARG_WITH(user,
|
AC_ARG_WITH(user,
|
||||||
[ --with-user=USER Set the owner of installed files ],
|
[ --with-user=USER Set the owner of installed files ],
|
||||||
[ OWNER="$withval" ])
|
[ OWNER="$withval" ])
|
||||||
|
AC_MSG_RESULT($OWNER)
|
||||||
|
|
||||||
if test x$OWNER != x; then
|
if test x$OWNER != x; then
|
||||||
OWNER="-o $OWNER"
|
OWNER="-o $OWNER"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl -- setup the group ownership of the files
|
################################################################################
|
||||||
|
dnl -- Setup the group ownership of the files
|
||||||
|
AC_MSG_CHECKING(group owner)
|
||||||
|
GROUP="root"
|
||||||
AC_ARG_WITH(group,
|
AC_ARG_WITH(group,
|
||||||
[ --with-group=GROUP Set the group owner of installed files ],
|
[ --with-group=GROUP Set the group owner of installed files ],
|
||||||
[ GROUP="$withval" ])
|
[ GROUP="$withval" ])
|
||||||
|
AC_MSG_RESULT($GROUP)
|
||||||
|
|
||||||
if test x$GROUP != x; then
|
if test x$GROUP != x; then
|
||||||
GROUP="-g $GROUP"
|
GROUP="-g $GROUP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
dnl -- LVM1 tool fallback option
|
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
|
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)
|
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
|
if test x$LVM1_FALLBACK = xyes; then
|
||||||
CFLAGS="$CFLAGS -DLVM1_FALLBACK"
|
CFLAGS="$CFLAGS -DLVM1_FALLBACK"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
dnl -- format1 inclusion type
|
dnl -- format1 inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include support for lvm1 metadata)
|
||||||
AC_ARG_WITH(lvm1,
|
AC_ARG_WITH(lvm1,
|
||||||
[ --with-lvm1=TYPE LVM1 metadata support: internal/shared/none
|
[ --with-lvm1=TYPE LVM1 metadata support: internal/shared/none
|
||||||
[TYPE=internal] ],
|
[TYPE=internal] ],
|
||||||
[ LVM1="$withval" ],
|
[ LVM1="$withval" ],
|
||||||
[ LVM1="internal" ])
|
[ LVM1="internal" ])
|
||||||
|
AC_MSG_RESULT($LVM1)
|
||||||
|
|
||||||
if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
|
if [[ "x$LVM1" != xnone -a "x$LVM1" != xinternal -a "x$LVM1" != xshared ]];
|
||||||
then AC_MSG_ERROR(
|
then AC_MSG_ERROR(
|
||||||
--with-lvm1 parameter invalid
|
--with-lvm1 parameter invalid
|
||||||
)
|
)
|
||||||
exit
|
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
if test x$LVM1 = xinternal; then
|
if test x$LVM1 = xinternal; then
|
||||||
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
|
CFLAGS="$CFLAGS -DLVM1_INTERNAL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
dnl -- format_pool inclusion type
|
dnl -- format_pool inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include support for GFS pool metadata)
|
||||||
AC_ARG_WITH(pool,
|
AC_ARG_WITH(pool,
|
||||||
[ --with-pool=TYPE GFS pool read-only support: internal/shared/none
|
[ --with-pool=TYPE GFS pool read-only support: internal/shared/none
|
||||||
[TYPE=internal] ],
|
[TYPE=internal] ],
|
||||||
[ POOL="$withval" ],
|
[ POOL="$withval" ],
|
||||||
[ POOL="internal" ])
|
[ POOL="internal" ])
|
||||||
|
AC_MSG_RESULT($POOL)
|
||||||
|
|
||||||
if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
|
if [[ "x$POOL" != xnone -a "x$POOL" != xinternal -a "x$POOL" != xshared ]];
|
||||||
then AC_MSG_ERROR(
|
then AC_MSG_ERROR(
|
||||||
--with-pool parameter invalid
|
--with-pool parameter invalid
|
||||||
)
|
)
|
||||||
exit
|
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
if test x$POOL = xinternal; then
|
if test x$POOL = xinternal; then
|
||||||
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
|
CFLAGS="$CFLAGS -DPOOL_INTERNAL"
|
||||||
fi
|
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)
|
||||||
|
|
||||||
AC_ARG_ENABLE(jobs, [ --enable-jobs=NUM Number of jobs to run simultaneously], JOBS=-j$enableval, JOBS=-j2)
|
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
|
||||||
|
CFLAGS="$CFLAGS -DCLUSTER_LOCKING_INTERNAL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
dnl -- snapshots inclusion type
|
dnl -- snapshots inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include snapshots)
|
||||||
AC_ARG_WITH(snapshots,
|
AC_ARG_WITH(snapshots,
|
||||||
[ --with-snapshots=TYPE Snapshot support: internal/shared/none
|
[ --with-snapshots=TYPE Snapshot support: internal/shared/none
|
||||||
[TYPE=internal] ],
|
[TYPE=internal] ],
|
||||||
[ SNAPSHOTS="$withval" ],
|
[ SNAPSHOTS="$withval" ],
|
||||||
[ SNAPSHOTS="internal" ])
|
[ SNAPSHOTS="internal" ])
|
||||||
|
AC_MSG_RESULT($SNAPSHOTS)
|
||||||
|
|
||||||
if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
|
if [[ "x$SNAPSHOTS" != xnone -a "x$SNAPSHOTS" != xinternal -a "x$SNAPSHOTS" != xshared ]];
|
||||||
then AC_MSG_ERROR(
|
then AC_MSG_ERROR(
|
||||||
--with-snapshots parameter invalid
|
--with-snapshots parameter invalid
|
||||||
)
|
)
|
||||||
exit
|
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
if test x$SNAPSHOTS = xinternal; then
|
if test x$SNAPSHOTS = xinternal; then
|
||||||
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
|
CFLAGS="$CFLAGS -DSNAPSHOT_INTERNAL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
dnl -- mirrors inclusion type
|
dnl -- mirrors inclusion type
|
||||||
|
AC_MSG_CHECKING(whether to include mirrors)
|
||||||
AC_ARG_WITH(mirrors,
|
AC_ARG_WITH(mirrors,
|
||||||
[ --with-mirrors=TYPE Mirror support: internal/shared/none
|
[ --with-mirrors=TYPE Mirror support: internal/shared/none
|
||||||
[TYPE=internal] ],
|
[TYPE=internal] ],
|
||||||
[ MIRRORS="$withval" ],
|
[ MIRRORS="$withval" ],
|
||||||
[ MIRRORS="internal" ])
|
[ MIRRORS="internal" ])
|
||||||
|
AC_MSG_RESULT($MIRRORS)
|
||||||
|
|
||||||
if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
|
if [[ "x$MIRRORS" != xnone -a "x$MIRRORS" != xinternal -a "x$MIRRORS" != xshared ]];
|
||||||
then AC_MSG_ERROR(
|
then AC_MSG_ERROR(
|
||||||
--with-mirrors parameter invalid
|
--with-mirrors parameter invalid
|
||||||
)
|
)
|
||||||
exit
|
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
if test x$MIRRORS = xinternal; then
|
if test x$MIRRORS = xinternal; then
|
||||||
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
|
CFLAGS="$CFLAGS -DMIRRORED_INTERNAL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Enables staticly-linked tools
|
################################################################################
|
||||||
|
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
|
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)
|
statically. Default is dynamic linking], STATIC_LINK=$enableval, STATIC_LINK=no)
|
||||||
|
AC_MSG_RESULT($STATIC_LINK)
|
||||||
|
|
||||||
dnl Enable readline
|
################################################################################
|
||||||
AC_ARG_ENABLE(readline, [ --enable-readline Enable readline support], \
|
dnl -- Enable readline
|
||||||
|
AC_MSG_CHECKING(whether to enable readline)
|
||||||
|
AC_ARG_ENABLE(readline, [ --enable-readline Enable readline support],
|
||||||
READLINE=$enableval, READLINE=no)
|
READLINE=$enableval, READLINE=no)
|
||||||
|
AC_MSG_RESULT($READLINE)
|
||||||
|
|
||||||
if test x$READLINE = xyes; then
|
if test x$READLINE = xyes; then
|
||||||
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
|
CFLAGS="$CFLAGS -DREADLINE_SUPPORT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo $ac_n "checking whether to enable debugging""... $ac_c" 1>&6
|
################################################################################
|
||||||
dnl Enable Debugging
|
dnl -- Disable selinux
|
||||||
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging], \
|
AC_MSG_CHECKING(whether to enable selinux support)
|
||||||
DEBUG=yes, DEBUG=no)
|
AC_ARG_ENABLE(selinux, [ --disable-selinux Disable selinux support],
|
||||||
echo "$ac_t""$DEBUG" 1>&6
|
SELINUX=$enableval)
|
||||||
|
AC_MSG_RESULT($SELINUX)
|
||||||
|
|
||||||
echo $ac_n "checking whether to enable device-mapper""... $ac_c" 1>&6
|
################################################################################
|
||||||
dnl Disable devmapper
|
dnl -- Build cluster LVM daemon
|
||||||
AC_ARG_ENABLE(devmapper, [ --disable-devmapper Disable device-mapper interaction], \
|
AC_MSG_CHECKING(whether to build cluster LVM daemon)
|
||||||
DEVMAPPER=no)
|
AC_ARG_WITH(clvmd,
|
||||||
echo "$ac_t""$DEVMAPPER" 1>&6
|
[ --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=
|
||||||
|
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
|
if test x$DEVMAPPER = xyes; then
|
||||||
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
|
CFLAGS="$CFLAGS -DDEVMAPPER_SUPPORT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo $ac_n "checking whether to enable O_DIRECT""... $ac_c" 1>&6
|
################################################################################
|
||||||
dnl Disable O_DIRECT
|
dnl -- Disable O_DIRECT
|
||||||
AC_ARG_ENABLE(o_direct, [ --disable-o_direct Disable O_DIRECT], \
|
AC_MSG_CHECKING(whether to enable O_DIRECT)
|
||||||
ODIRECT=no)
|
AC_ARG_ENABLE(o_direct, [ --disable-o_direct Disable O_DIRECT],
|
||||||
echo "$ac_t""$ODIRECT" 1>&6
|
ODIRECT=$enableval)
|
||||||
|
AC_MSG_RESULT($ODIRECT)
|
||||||
|
|
||||||
if test x$ODIRECT = xyes; then
|
if test x$ODIRECT = xyes; then
|
||||||
CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
|
CFLAGS="$CFLAGS -DO_DIRECT_SUPPORT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo $ac_n "checking whether to compile liblvm2cmd.so""... $ac_c" 1>&6
|
################################################################################
|
||||||
dnl Enable cmdlib
|
dnl -- Enable cmdlib
|
||||||
AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library], \
|
AC_MSG_CHECKING(whether to compile liblvm2cmd.so)
|
||||||
CMDLIB=yes, CMDLIB=no)
|
AC_ARG_ENABLE(cmdlib, [ --enable-cmdlib Build shared command library],
|
||||||
echo "$ac_t""$CMDLIB" 1>&6
|
CMDLIB=$enableval, CMDLIB=no)
|
||||||
|
AC_MSG_RESULT($CMDLIB)
|
||||||
|
|
||||||
if test x$CMDLIB = xyes; then
|
if test x$CMDLIB = xyes; then
|
||||||
CFLAGS="$CFLAGS -DCMDLIB"
|
CFLAGS="$CFLAGS -DCMDLIB"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Mess with default exec_prefix
|
################################################################################
|
||||||
|
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 -- Mess with default exec_prefix
|
||||||
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]];
|
||||||
then exec_prefix="";
|
then exec_prefix="";
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
dnl Checks for library functions.
|
################################################################################
|
||||||
|
dnl -- Checks for library functions.
|
||||||
AC_PROG_GCC_TRADITIONAL
|
AC_PROG_GCC_TRADITIONAL
|
||||||
AC_TYPE_SIGNAL
|
AC_TYPE_SIGNAL
|
||||||
AC_FUNC_VPRINTF
|
AC_FUNC_VPRINTF
|
||||||
AC_CHECK_FUNCS(mkdir rmdir uname)
|
AC_CHECK_FUNCS(mkdir rmdir uname,,AC_MSG_ERROR(bailing out))
|
||||||
|
|
||||||
dnl check for termcap (Shamelessly copied from parted 1.4.17)
|
################################################################################
|
||||||
|
dnl -- Check for termcap (Shamelessly copied from parted 1.4.17)
|
||||||
if test x$READLINE = xyes; then
|
if test x$READLINE = xyes; then
|
||||||
AC_SEARCH_LIBS(tgetent, ncurses curses termcap termlib, ,
|
AC_SEARCH_LIBS(tgetent, ncurses curses termcap termlib, ,
|
||||||
AC_MSG_ERROR(
|
AC_MSG_ERROR(
|
||||||
@@ -250,42 +382,51 @@ Note: if you are using precompiled packages you will also need the development
|
|||||||
Note: (n)curses also seems to work as a substitute for termcap. This was
|
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.
|
not found either - but you could try installing that as well.
|
||||||
)
|
)
|
||||||
exit
|
|
||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Check for dlopen
|
################################################################################
|
||||||
|
dnl -- Check for dlopen
|
||||||
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
|
AC_CHECK_LIB(dl, dlopen, HAVE_LIBDL=yes, HAVE_LIBDL=no)
|
||||||
|
|
||||||
if [[ "x$HAVE_LIBDL" = xyes -a "x$STATIC_LINK" = xno ]]; then
|
if [[ "x$HAVE_LIBDL" = xyes ]]; then
|
||||||
CFLAGS="$CFLAGS -DHAVE_LIBDL"
|
CFLAGS="$CFLAGS -DHAVE_LIBDL"
|
||||||
LIBS="-ldl $LIBS"
|
LIBS="-ldl $LIBS"
|
||||||
else
|
else
|
||||||
HAVE_LIBDL=no
|
HAVE_LIBDL=no
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Check for shared/static conflicts
|
################################################################################
|
||||||
if [[ \( "x$LVM1" = xshared -o "x$POOL" = xshared -o \
|
dnl -- Check for shared/static conflicts
|
||||||
"x$SNAPSHOTS" = xshared -o "x$MIRRORS" = xshared \
|
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 ]];
|
\) -a "x$STATIC_LINK" = xyes ]];
|
||||||
then AC_MSG_ERROR(
|
then AC_MSG_ERROR(
|
||||||
Features cannot be 'shared' when building statically
|
Features cannot be 'shared' when building statically
|
||||||
)
|
)
|
||||||
exit
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Check for is_selinux_enabled
|
################################################################################
|
||||||
AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
|
dnl -- Check for is_selinux_enabled
|
||||||
|
if test x$SELINUX = xyes; then
|
||||||
|
AC_MSG_CHECKING(for is_selinux_enabled function)
|
||||||
|
AC_CHECK_LIB(selinux, is_selinux_enabled, HAVE_SELINUX=yes, HAVE_SELINUX=no)
|
||||||
|
AC_MSG_RESULT($HAVE_SELINUX)
|
||||||
|
|
||||||
if test x$HAVE_SELINUX = xyes; then
|
if test x$HAVE_SELINUX = xyes; then
|
||||||
CFLAGS="$CFLAGS -DHAVE_SELINUX"
|
CFLAGS="$CFLAGS -DHAVE_SELINUX"
|
||||||
LIBS="-lselinux $LIBS"
|
LIBS="-lselinux $LIBS"
|
||||||
|
else
|
||||||
|
AC_MSG_WARN(Disabling selinux)
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl Check for getopt
|
################################################################################
|
||||||
|
dnl -- Check for getopt
|
||||||
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
|
AC_CHECK_HEADERS(getopt.h, CFLAGS="$CFLAGS -DHAVE_GETOPTLONG")
|
||||||
|
|
||||||
dnl Check for readline (Shamelessly copied from parted 1.4.17)
|
################################################################################
|
||||||
|
dnl -- Check for readline (Shamelessly copied from parted 1.4.17)
|
||||||
if test x$READLINE = xyes; then
|
if test x$READLINE = xyes; then
|
||||||
AC_CHECK_LIB(readline, readline, ,
|
AC_CHECK_LIB(readline, readline, ,
|
||||||
AC_MSG_ERROR(
|
AC_MSG_ERROR(
|
||||||
@@ -296,17 +437,17 @@ support with --disable-readline or download and install readline from:
|
|||||||
Note: if you are using precompiled packages you will also need the development
|
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).
|
package as well (which may be called readline-devel or something similar).
|
||||||
)
|
)
|
||||||
exit
|
|
||||||
)
|
)
|
||||||
AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
|
AC_CHECK_FUNC(rl_completion_matches, CFLAGS="$CFLAGS -DHAVE_RL_COMPLETION_MATCHES")
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo $ac_n "checking whether to enable internationalisation""... $ac_c" 1>&6
|
################################################################################
|
||||||
dnl Internationalisation stuff
|
dnl -- Internationalisation stuff
|
||||||
AC_ARG_ENABLE(nls, [ --enable-nls Enable Native Language Support],\
|
AC_MSG_CHECKING(whether to enable internationalisation)
|
||||||
INTL=yes, INTL=no)
|
AC_ARG_ENABLE(nls, [ --enable-nls Enable Native Language Support],
|
||||||
echo "$ac_t""$INTL" 1>&6
|
INTL=$enableval, INTL=no)
|
||||||
|
AC_MSG_RESULT($INTL)
|
||||||
|
|
||||||
if test x$INTL = xyes; then
|
if test x$INTL = xyes; then
|
||||||
INTL_PACKAGE="lvm2"
|
INTL_PACKAGE="lvm2"
|
||||||
@@ -315,7 +456,6 @@ if test x$INTL = xyes; then
|
|||||||
then AC_MSG_ERROR(
|
then AC_MSG_ERROR(
|
||||||
msgfmt not found in path $PATH
|
msgfmt not found in path $PATH
|
||||||
)
|
)
|
||||||
exit
|
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
AC_ARG_WITH(localedir,
|
AC_ARG_WITH(localedir,
|
||||||
@@ -324,6 +464,7 @@ if test x$INTL = xyes; then
|
|||||||
[ LOCALEDIR='${prefix}/share/locale' ])
|
[ LOCALEDIR='${prefix}/share/locale' ])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
AC_ARG_WITH(confdir,
|
AC_ARG_WITH(confdir,
|
||||||
[ --with-confdir=DIR Configuration files in DIR [/etc]],
|
[ --with-confdir=DIR Configuration files in DIR [/etc]],
|
||||||
[ CONFDIR="$withval" ],
|
[ CONFDIR="$withval" ],
|
||||||
@@ -334,13 +475,61 @@ AC_ARG_WITH(staticdir,
|
|||||||
[ STATICDIR="$withval" ],
|
[ STATICDIR="$withval" ],
|
||||||
[ STATICDIR='${exec_prefix}/sbin' ])
|
[ STATICDIR='${exec_prefix}/sbin' ])
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
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
|
||||||
|
|
||||||
|
if test x$DEVMAPPER = xyes; then
|
||||||
|
AC_CHECK_HEADERS(libdevmapper.h,,AC_MSG_ERROR(bailing out))
|
||||||
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
|
CFLAGS="$CFLAGS -DMODPROBE_CMD=\\\"$MODPROBE_CMD\\\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
if test "-f VERSION"; then
|
if test "-f VERSION"; then
|
||||||
LVM_VERSION="\"`cat VERSION`\""
|
LVM_VERSION="\"`cat VERSION`\""
|
||||||
else
|
else
|
||||||
LVM_VERSION="Unknown"
|
LVM_VERSION="Unknown"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
AC_SUBST(JOBS)
|
AC_SUBST(JOBS)
|
||||||
AC_SUBST(STATIC_LINK)
|
AC_SUBST(STATIC_LINK)
|
||||||
AC_SUBST(LVM1)
|
AC_SUBST(LVM1)
|
||||||
@@ -350,11 +539,12 @@ AC_SUBST(MIRRORS)
|
|||||||
AC_SUBST(OWNER)
|
AC_SUBST(OWNER)
|
||||||
AC_SUBST(GROUP)
|
AC_SUBST(GROUP)
|
||||||
AC_SUBST(CFLAGS)
|
AC_SUBST(CFLAGS)
|
||||||
|
AC_SUBST(COPTIMISE_FLAG)
|
||||||
AC_SUBST(CLDFLAGS)
|
AC_SUBST(CLDFLAGS)
|
||||||
AC_SUBST(CLDWHOLEARCHIVE)
|
AC_SUBST(CLDWHOLEARCHIVE)
|
||||||
AC_SUBST(CLDNOWHOLEARCHIVE)
|
AC_SUBST(CLDNOWHOLEARCHIVE)
|
||||||
AC_SUBST(LD_DEPS)
|
AC_SUBST(LDDEPS)
|
||||||
AC_SUBST(LD_FLAGS)
|
AC_SUBST(LDFLAGS)
|
||||||
AC_SUBST(SOFLAG)
|
AC_SUBST(SOFLAG)
|
||||||
AC_SUBST(LIBS)
|
AC_SUBST(LIBS)
|
||||||
AC_SUBST(LVM_VERSION)
|
AC_SUBST(LVM_VERSION)
|
||||||
@@ -370,23 +560,31 @@ AC_SUBST(CONFDIR)
|
|||||||
AC_SUBST(STATICDIR)
|
AC_SUBST(STATICDIR)
|
||||||
AC_SUBST(INTL_PACKAGE)
|
AC_SUBST(INTL_PACKAGE)
|
||||||
AC_SUBST(INTL)
|
AC_SUBST(INTL)
|
||||||
|
AC_SUBST(CLVMD)
|
||||||
|
AC_SUBST(CLUSTER)
|
||||||
|
AC_SUBST(FSADM)
|
||||||
|
|
||||||
dnl First and last lines should not contain files to generate in order to
|
################################################################################
|
||||||
dnl keep utility scripts running properly
|
dnl -- First and last lines should not contain files to generate in order to
|
||||||
|
dnl -- keep utility scripts running properly
|
||||||
AC_OUTPUT( \
|
AC_OUTPUT( \
|
||||||
Makefile \
|
Makefile \
|
||||||
make.tmpl \
|
make.tmpl \
|
||||||
|
daemons/Makefile \
|
||||||
|
daemons/clvmd/Makefile \
|
||||||
doc/Makefile \
|
doc/Makefile \
|
||||||
include/Makefile \
|
include/Makefile \
|
||||||
lib/Makefile \
|
lib/Makefile \
|
||||||
lib/format1/Makefile \
|
lib/format1/Makefile \
|
||||||
lib/format_pool/Makefile \
|
lib/format_pool/Makefile \
|
||||||
|
lib/locking/Makefile \
|
||||||
lib/mirror/Makefile \
|
lib/mirror/Makefile \
|
||||||
lib/snapshot/Makefile \
|
lib/snapshot/Makefile \
|
||||||
man/Makefile \
|
man/Makefile \
|
||||||
po/Makefile \
|
po/Makefile \
|
||||||
tools/Makefile \
|
tools/Makefile \
|
||||||
tools/version.h \
|
tools/version.h \
|
||||||
|
tools/fsadm/Makefile \
|
||||||
test/mm/Makefile \
|
test/mm/Makefile \
|
||||||
test/device/Makefile \
|
test/device/Makefile \
|
||||||
test/format1/Makefile \
|
test/format1/Makefile \
|
||||||
@@ -395,8 +593,9 @@ test/filters/Makefile \
|
|||||||
)
|
)
|
||||||
|
|
||||||
if test x$ODIRECT != xyes; then
|
if test x$ODIRECT != xyes; then
|
||||||
echo
|
AC_MSG_WARN(Warning: O_DIRECT disabled: low-memory pvmove may lock up)
|
||||||
echo Warning: O_DIRECT disabled.
|
fi
|
||||||
echo Use of pvmove may cause machine to lock up under low memory conditions.
|
|
||||||
echo
|
if test x$FSADM == xyes; then
|
||||||
|
AC_MSG_WARN(fsadm support is untested)
|
||||||
fi
|
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
|
||||||
|
|
||||||
76
daemons/clvmd/Makefile.in
Normal file
76
daemons/clvmd/Makefile.in
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#
|
||||||
|
# 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 \
|
||||||
|
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")
|
||||||
|
CFLAGS += -DDEBUG
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("$(GULM)", "yes")
|
||||||
|
SOURCES += clvmd-gulm.c tcp-comms.c
|
||||||
|
LMLIBS += -lccs -lgulm
|
||||||
|
CFLAGS += -DUSE_GULM
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("$(CMAN)", "yes")
|
||||||
|
SOURCES += clvmd-cman.c
|
||||||
|
LMLIBS += -ldlm
|
||||||
|
CFLAGS += -DUSE_CMAN
|
||||||
|
endif
|
||||||
|
|
||||||
|
TARGETS = \
|
||||||
|
clvmd
|
||||||
|
|
||||||
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
CFLAGS += -D_REENTRANT -fno-strict-aliasing
|
||||||
|
LIBS += -ldevmapper -llvm -lpthread
|
||||||
|
|
||||||
|
INSTALL_TARGETS = \
|
||||||
|
install_clvmd
|
||||||
|
|
||||||
|
clvmd: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
|
||||||
|
$(CC) -o clvmd $(OBJECTS) $(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)
|
||||||
|
|
||||||
66
daemons/clvmd/clvm.h
Normal file
66
daemons/clvmd/clvm.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#endif
|
||||||
540
daemons/clvmd/clvmd-cman.c
Normal file
540
daemons/clvmd/clvmd-cman.c
Normal file
@@ -0,0 +1,540 @@
|
|||||||
|
/*
|
||||||
|
* 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 cluster_sock;
|
||||||
|
static int num_nodes;
|
||||||
|
static struct cl_cluster_node *nodes = NULL;
|
||||||
|
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 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);
|
||||||
|
|
||||||
|
struct lock_wait {
|
||||||
|
pthread_cond_t cond;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
struct dlm_lksb lksb;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int _init_cluster(void)
|
||||||
|
{
|
||||||
|
struct sockaddr_cl saddr;
|
||||||
|
int port = CLUSTER_PORT_CLVMD;
|
||||||
|
|
||||||
|
/* Open the cluster communication socket */
|
||||||
|
cluster_sock = socket(AF_CLUSTER, SOCK_DGRAM, CLPROTO_CLIENT);
|
||||||
|
if (cluster_sock == -1) {
|
||||||
|
/* Don't print an error here because we could be just probing for CMAN */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Set Close-on-exec */
|
||||||
|
fcntl(cluster_sock, F_SETFD, 1);
|
||||||
|
|
||||||
|
/* Bind to our port number on the cluster.
|
||||||
|
Writes to this will block if the cluster loses quorum */
|
||||||
|
saddr.scl_family = AF_CLUSTER;
|
||||||
|
saddr.scl_port = port;
|
||||||
|
|
||||||
|
if (bind
|
||||||
|
(cluster_sock, (struct sockaddr *) &saddr,
|
||||||
|
sizeof(struct sockaddr_cl))) {
|
||||||
|
syslog(LOG_ERR, "Can't bind cluster socket: %m");
|
||||||
|
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 cluster_sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _get_num_nodes()
|
||||||
|
{
|
||||||
|
return num_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send_message with the fd check removed */
|
||||||
|
static int _cluster_send_message(void *buf, int msglen, char *csid, const char *errtext)
|
||||||
|
{
|
||||||
|
struct iovec iov[2];
|
||||||
|
struct msghdr msg;
|
||||||
|
struct sockaddr_cl saddr;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
msg.msg_control = NULL;
|
||||||
|
msg.msg_controllen = 0;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_iov = iov;
|
||||||
|
msg.msg_flags = 0;
|
||||||
|
iov[0].iov_len = msglen;
|
||||||
|
iov[0].iov_base = buf;
|
||||||
|
|
||||||
|
saddr.scl_family = AF_CLUSTER;
|
||||||
|
saddr.scl_port = CLUSTER_PORT_CLVMD;
|
||||||
|
if (csid) {
|
||||||
|
msg.msg_name = &saddr;
|
||||||
|
msg.msg_namelen = sizeof(saddr);
|
||||||
|
memcpy(&saddr.scl_nodeid, csid, CMAN_MAX_CSID_LEN);
|
||||||
|
} else { /* Cluster broadcast */
|
||||||
|
|
||||||
|
msg.msg_name = NULL;
|
||||||
|
msg.msg_namelen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
len = sendmsg(cluster_sock, &msg, 0);
|
||||||
|
if (len < 0 && errno != EAGAIN)
|
||||||
|
log_error(errtext);
|
||||||
|
|
||||||
|
} while (len == -1 && errno == EAGAIN);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _get_our_csid(char *csid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
memset(csid, 0, CMAN_MAX_CSID_LEN);
|
||||||
|
|
||||||
|
for (i = 0; i < num_nodes; i++) {
|
||||||
|
if (nodes[i].us)
|
||||||
|
memcpy(csid, &nodes[i].node_id, CMAN_MAX_CSID_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call a callback routine for each node that known (down mean 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++) {
|
||||||
|
callback(client, (char *)&nodes[i].node_id, node_updown[nodes[i].node_id]);
|
||||||
|
if (!node_updown[nodes[i].node_id])
|
||||||
|
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 process_oob_msg(char *buf, int len, int nodeid)
|
||||||
|
{
|
||||||
|
char namebuf[256];
|
||||||
|
switch (buf[0]) {
|
||||||
|
case CLUSTER_OOB_MSG_PORTCLOSED:
|
||||||
|
name_from_nodeid(nodeid, namebuf);
|
||||||
|
log_notice("clvmd on node %s has died\n", namebuf);
|
||||||
|
DEBUGLOG("Got OOB message, removing node %s\n", namebuf);
|
||||||
|
|
||||||
|
node_updown[nodeid] = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLUSTER_OOB_MSG_STATECHANGE:
|
||||||
|
DEBUGLOG("Got OOB message, Cluster state change\n");
|
||||||
|
get_members();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* ERROR */
|
||||||
|
DEBUGLOG("Got unknown OOB message: %d\n", buf[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _cluster_fd_callback(struct local_client *client, char *buf, int len, char *csid,
|
||||||
|
struct local_client **new_client)
|
||||||
|
{
|
||||||
|
struct iovec iov[2];
|
||||||
|
struct msghdr msg;
|
||||||
|
struct sockaddr_cl saddr;
|
||||||
|
|
||||||
|
/* We never return a new client */
|
||||||
|
*new_client = NULL;
|
||||||
|
|
||||||
|
msg.msg_control = NULL;
|
||||||
|
msg.msg_controllen = 0;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_iov = iov;
|
||||||
|
msg.msg_name = &saddr;
|
||||||
|
msg.msg_flags = 0;
|
||||||
|
msg.msg_namelen = sizeof(saddr);
|
||||||
|
iov[0].iov_len = len;
|
||||||
|
iov[0].iov_base = buf;
|
||||||
|
|
||||||
|
len = recvmsg(cluster_sock, &msg, MSG_OOB | O_NONBLOCK);
|
||||||
|
if (len < 0 && errno == EAGAIN)
|
||||||
|
return len;
|
||||||
|
|
||||||
|
DEBUGLOG("Read on cluster socket, len = %d\n", len);
|
||||||
|
|
||||||
|
/* A real error */
|
||||||
|
if (len < 0) {
|
||||||
|
log_error("read error on cluster socket: %m");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF - we have left the cluster */
|
||||||
|
if (len == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Is it OOB? probably a node gone down */
|
||||||
|
if (msg.msg_flags & MSG_OOB) {
|
||||||
|
process_oob_msg(iov[0].iov_base, len, saddr.scl_nodeid);
|
||||||
|
|
||||||
|
/* Tell the upper layer to ignore this message */
|
||||||
|
len = -1;
|
||||||
|
errno = EAGAIN;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memcpy(csid, &saddr.scl_nodeid, sizeof(saddr.scl_nodeid));
|
||||||
|
/* Send it back to clvmd */
|
||||||
|
process_message(client, buf, len, csid);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
close(cluster_sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_listening(int nodeid)
|
||||||
|
{
|
||||||
|
struct cl_listen_request rq;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
rq.port = CLUSTER_PORT_CLVMD;
|
||||||
|
rq.nodeid = nodeid;
|
||||||
|
|
||||||
|
do {
|
||||||
|
status = ioctl(cluster_sock, SIOCCLUSTER_ISLISTENING, &rq);
|
||||||
|
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].node_id] = is_listening(nodes[i].node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a list of active cluster members */
|
||||||
|
static void get_members()
|
||||||
|
{
|
||||||
|
struct cl_cluster_nodelist nodelist;
|
||||||
|
|
||||||
|
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, 0);
|
||||||
|
if (num_nodes == -1) {
|
||||||
|
log_error("Unable to get node count");
|
||||||
|
} else {
|
||||||
|
/* 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 cl_cluster_node));
|
||||||
|
if (!nodes) {
|
||||||
|
log_error("Unable to allocate nodes array\n");
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodelist.max_members = count_nodes;
|
||||||
|
nodelist.nodes = nodes;
|
||||||
|
|
||||||
|
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
|
||||||
|
if (num_nodes <= 0) {
|
||||||
|
log_error("Unable to get node details");
|
||||||
|
exit(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity check struct */
|
||||||
|
if (nodes[0].size != sizeof(struct cl_cluster_node)) {
|
||||||
|
log_error
|
||||||
|
("sizeof(cl_cluster_node) does not match size returned from the kernel: aborting\n");
|
||||||
|
exit(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
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].name) == 0) {
|
||||||
|
memcpy(csid, &nodes[i].node_id, 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].node_id, CMAN_MAX_CSID_LEN) == 0) {
|
||||||
|
strcpy(name, nodes[i].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].node_id) {
|
||||||
|
strcpy(name, nodes[i].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 ioctl(cluster_sock, SIOCCLUSTER_ISQUORATE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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,
|
||||||
|
.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;
|
||||||
|
}
|
||||||
286
daemons/clvmd/clvmd-command.c
Normal file
286
daemons/clvmd/clvmd-command.c
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
/* 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,
|
||||||
|
"Internal lvm error, check syslog");
|
||||||
|
return EIO;
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
|
||||||
|
status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
|
||||||
|
if (status)
|
||||||
|
status = errno;
|
||||||
|
else
|
||||||
|
dm_hash_insert(lock_hash, lockname, (void *)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 *) 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
70
daemons/clvmd/clvmd-comms.h
Normal file
70
daemons/clvmd/clvmd-comms.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 (*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 "cnxman-socket.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_CLUSTER_MEMBER_NAME_LEN
|
||||||
|
struct cluster_ops *init_cman_cluster(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
1000
daemons/clvmd/clvmd-gulm.c
Normal file
1000
daemons/clvmd/clvmd-gulm.c
Normal file
File diff suppressed because it is too large
Load Diff
12
daemons/clvmd/clvmd-gulm.h
Normal file
12
daemons/clvmd/clvmd-gulm.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
1857
daemons/clvmd/clvmd.c
Normal file
1857
daemons/clvmd/clvmd.c
Normal file
File diff suppressed because it is too large
Load Diff
124
daemons/clvmd/clvmd.h
Normal file
124
daemons/clvmd/clvmd.h
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DEBUGLOG(fmt, args...) {time_t P; time(&P); fprintf(stderr, "CLVMD[%x]: %.15s ", (int)pthread_self(), ctime(&P)+4 ); fprintf(stderr, fmt, ## args);}
|
||||||
|
#else
|
||||||
|
#define DEBUGLOG(fmt, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
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
|
||||||
542
daemons/clvmd/lvm-functions.c
Normal file
542
daemons/clvmd/lvm-functions.c
Normal file
@@ -0,0 +1,542 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
static struct cmd_context *cmd = NULL;
|
||||||
|
static struct dm_hash_table *lv_hash = NULL;
|
||||||
|
static pthread_mutex_t lv_hash_lock;
|
||||||
|
|
||||||
|
struct lv_info {
|
||||||
|
int lock_id;
|
||||||
|
int lock_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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 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_deactivate_lock, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
fclose(vgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(lvs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This checks some basic cluster-LVM configuration stuff */
|
||||||
|
static void check_config()
|
||||||
|
{
|
||||||
|
int locking_type;
|
||||||
|
|
||||||
|
locking_type = find_config_int(cmd->cft->root, "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_str(cmd->cft->root, "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))) {
|
||||||
|
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();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
35
daemons/clvmd/lvm-functions.h
Normal file
35
daemons/clvmd/lvm-functions.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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 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);
|
||||||
|
|
||||||
|
#endif
|
||||||
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;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
@@ -13,30 +13,18 @@
|
|||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#ifndef _CLVM_SYSTEM_LV_H
|
||||||
#include "selinux.h"
|
#define _CLVM_SYSTEM_LV_H
|
||||||
|
|
||||||
#include <selinux/selinux.h>
|
/* Prototypes for System-LV functions */
|
||||||
|
|
||||||
int set_selinux_context(const char *path)
|
/* "low-level" functions */
|
||||||
{
|
extern int system_lv_umount(void);
|
||||||
security_context_t scontext;
|
extern int system_lv_mount(int readwrite);
|
||||||
|
extern int system_lv_eraseall(void);
|
||||||
|
|
||||||
log_very_verbose("Setting SELinux context for %s", path);
|
/* "high-level" functions */
|
||||||
if (is_selinux_enabled() <= 0)
|
extern int system_lv_write_data(char *data, ssize_t len);
|
||||||
return 1;
|
extern int system_lv_read_data(char *fname_base, char *data, ssize_t *len);
|
||||||
|
|
||||||
if (matchpathcon(path, 0, &scontext) < 0) {
|
#endif
|
||||||
log_sys_error("matchpathcon", path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lsetfilecon(path, scontext) < 0) && (errno != ENOTSUP)) {
|
|
||||||
log_sys_error("lsetfilecon", path);
|
|
||||||
free(scontext);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(scontext);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
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 ? 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);
|
||||||
3
daemons/dmeventd/.exported_symbols
Normal file
3
daemons/dmeventd/.exported_symbols
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
process_event
|
||||||
|
register_device
|
||||||
|
unregister_device
|
||||||
51
daemons/dmeventd/Makefile.in
Normal file
51
daemons/dmeventd/Makefile.in
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#
|
||||||
|
# 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 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 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@
|
||||||
|
|
||||||
|
TARGETS = dmevent dmeventd
|
||||||
|
INSTALL_TYPE = install_dynamic
|
||||||
|
|
||||||
|
SOURCES = noop.c
|
||||||
|
CLEAN_TARGETS = dmevent.o dmeventd.o
|
||||||
|
|
||||||
|
ifeq ("@LIB_SUFFIX@","dylib")
|
||||||
|
LIB_SHARED = libdmeventdnoop.dylib
|
||||||
|
else
|
||||||
|
LIB_SHARED = libdmeventdnoop.so
|
||||||
|
endif
|
||||||
|
|
||||||
|
LDFLAGS += -ldl -ldevmapper -lmultilog
|
||||||
|
|
||||||
|
include ../make.tmpl
|
||||||
|
|
||||||
|
libdmeventdnoop.so: noop.o
|
||||||
|
|
||||||
|
dmevent: dmevent.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
|
||||||
|
$(CC) -o $@ dmevent.o $(LDFLAGS) \
|
||||||
|
-L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog $(LIBS)
|
||||||
|
|
||||||
|
dmeventd: dmeventd.o $(interfacedir)/libdevmapper.$(LIB_SUFFIX) $(top_srcdir)/lib/event/libdmevent.$(LIB_SUFFIX)
|
||||||
|
$(CC) -o $@ dmeventd.o $(LDFLAGS) \
|
||||||
|
-L$(interfacedir) -L$(DESTDIR)/lib -L$(top_srcdir)/lib/event -L$(top_srcdir)/multilog -lpthread -ldmevent $(LIBS)
|
||||||
|
|
||||||
|
install: $(INSTALL_TYPE)
|
||||||
|
|
||||||
|
.PHONY: install_dynamic
|
||||||
|
|
||||||
|
install_dynamic: dmeventd
|
||||||
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) dmeventd $(sbindir)/dmeventd
|
||||||
|
|
||||||
240
daemons/dmeventd/dmevent.c
Normal file
240
daemons/dmeventd/dmevent.c
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
* 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 "libdevmapper.h"
|
||||||
|
#include "libdm-event.h"
|
||||||
|
#include "libmultilog.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 <dlfcn.h>
|
||||||
|
|
||||||
|
static enum event_type events = ALL_ERRORS; /* All until we can distinguish. */
|
||||||
|
static char default_dso_name[] = "noop"; /* default DSO is noop */
|
||||||
|
static int default_reg = 1; /* default action is register */
|
||||||
|
static uint32_t timeout;
|
||||||
|
|
||||||
|
struct event_ops {
|
||||||
|
int (*dm_register_for_event)(char *dso_name, char *device,
|
||||||
|
enum event_type event_types);
|
||||||
|
int (*dm_unregister_for_event)(char *dso_name, char *device,
|
||||||
|
enum event_type event_types);
|
||||||
|
int (*dm_get_registered_device)(char **dso_name, char **device,
|
||||||
|
enum event_type *event_types, int next);
|
||||||
|
int (*dm_set_event_timeout)(char *device, uint32_t time);
|
||||||
|
int (*dm_get_event_timeout)(char *device, uint32_t *time);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Display help. */
|
||||||
|
static void print_usage(char *name)
|
||||||
|
{
|
||||||
|
char *cmd = strrchr(name, '/');
|
||||||
|
|
||||||
|
cmd = cmd ? cmd + 1 : name;
|
||||||
|
printf("Usage::\n"
|
||||||
|
"%s [options] <device>\n"
|
||||||
|
"\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -d <dso> Specify the DSO to use.\n"
|
||||||
|
" -h Print this usage.\n"
|
||||||
|
" -l List registered devices.\n"
|
||||||
|
" -r Register for event (default).\n"
|
||||||
|
" -t <timeout> (un)register for timeout event.\n"
|
||||||
|
" -u Unregister for event.\n"
|
||||||
|
"\n", cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse command line arguments. */
|
||||||
|
static int parse_argv(int argc, char **argv, char **dso_name_arg,
|
||||||
|
char **device_arg, int *reg, int *list)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
const char *options = "d:hlrt:u";
|
||||||
|
|
||||||
|
while ((c = getopt(argc, argv, options)) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'd':
|
||||||
|
*dso_name_arg = optarg;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
print_usage(argv[0]);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
case 'l':
|
||||||
|
*list = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
*reg = 1;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
events = TIMEOUT;
|
||||||
|
if (sscanf(optarg, "%"SCNu32, &timeout) != 1){
|
||||||
|
fprintf(stderr, "invalid timeout '%s'\n",
|
||||||
|
optarg);
|
||||||
|
timeout = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
*reg = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown option '%c'.\n"
|
||||||
|
"Try '-h' for help.\n", c);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
|
if (!*list) {
|
||||||
|
fprintf(stderr, "You need to specify a device.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
*device_arg = argv[optind];
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int lookup_symbol(void *dl, void **symbol, const char *name)
|
||||||
|
{
|
||||||
|
if ((*symbol = dlsym(dl, name)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fprintf(stderr, "error looking up %s symbol: %s\n", name, dlerror());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lookup_symbols(void *dl, struct event_ops *e)
|
||||||
|
{
|
||||||
|
return lookup_symbol(dl, (void *) &e->dm_register_for_event,
|
||||||
|
"dm_register_for_event") &&
|
||||||
|
lookup_symbol(dl, (void *) &e->dm_unregister_for_event,
|
||||||
|
"dm_unregister_for_event") &&
|
||||||
|
lookup_symbol(dl, (void *) &e->dm_get_registered_device,
|
||||||
|
"dm_get_registered_device") &&
|
||||||
|
lookup_symbol(dl, (void *) &e->dm_set_event_timeout,
|
||||||
|
"dm_set_event_timeout") &&
|
||||||
|
lookup_symbol(dl, (void *) &e->dm_get_event_timeout,
|
||||||
|
"dm_get_event_timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
void *dl;
|
||||||
|
struct event_ops e;
|
||||||
|
int list = 0, next = 0, ret, reg = default_reg;
|
||||||
|
char *device, *device_arg = NULL, *dso_name, *dso_name_arg = NULL;
|
||||||
|
|
||||||
|
if (!parse_argv(argc, argv, &dso_name_arg, &device_arg, ®, &list))
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
if (device_arg) {
|
||||||
|
if (!(device = strdup(device_arg)))
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else
|
||||||
|
device = NULL;
|
||||||
|
|
||||||
|
if (dso_name_arg) {
|
||||||
|
if (!(dso_name = strdup(dso_name_arg)))
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else {
|
||||||
|
if (!(dso_name = strdup(default_dso_name)))
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: use -v/-q options to set this */
|
||||||
|
multilog_add_type(standard, NULL);
|
||||||
|
multilog_init_verbose(standard, _LOG_DEBUG);
|
||||||
|
|
||||||
|
if (!(dl = dlopen("libdmevent.so", RTLD_NOW))){
|
||||||
|
fprintf(stderr, "Cannot dlopen libdmevent.so: %s\n", dlerror());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!(lookup_symbols(dl, &e)))
|
||||||
|
goto out;
|
||||||
|
if (list) {
|
||||||
|
while (1) {
|
||||||
|
if ((ret= e.dm_get_registered_device(&dso_name,
|
||||||
|
&device,
|
||||||
|
&events, next)))
|
||||||
|
break;
|
||||||
|
printf("%s %s 0x%x", dso_name, device, events);
|
||||||
|
if (events & TIMEOUT){
|
||||||
|
if ((ret = e.dm_get_event_timeout(device,
|
||||||
|
&timeout))) {
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
printf(" %"PRIu32"\n", timeout);
|
||||||
|
} else
|
||||||
|
printf("\n");
|
||||||
|
if (device_arg)
|
||||||
|
break;
|
||||||
|
|
||||||
|
next = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = (ret && device_arg) ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = reg ? e.dm_register_for_event(dso_name, device, events) :
|
||||||
|
e.dm_unregister_for_event(dso_name, device, events))) {
|
||||||
|
fprintf(stderr, "Failed to %sregister %s: %s\n",
|
||||||
|
reg ? "": "un", device, strerror(-ret));
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
} else {
|
||||||
|
if (reg && (events & TIMEOUT) &&
|
||||||
|
((ret = e.dm_set_event_timeout(device, timeout)))){
|
||||||
|
fprintf(stderr, "Failed to set timeout for %s: %s\n",
|
||||||
|
device, strerror(-ret));
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
} else {
|
||||||
|
printf("%s %sregistered successfully.\n",
|
||||||
|
device, reg ? "" : "un");
|
||||||
|
ret = EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
multilog_del_type(standard);
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
free(device);
|
||||||
|
if (dso_name)
|
||||||
|
free(dso_name);
|
||||||
|
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||||
|
* Emacs will notice this stuff at the end of the file and automatically
|
||||||
|
* adjust the settings for this buffer only. This must remain at the end
|
||||||
|
* of the file.
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
* Local variables:
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
1083
daemons/dmeventd/dmeventd.c
Normal file
1083
daemons/dmeventd/dmeventd.c
Normal file
File diff suppressed because it is too large
Load Diff
12
daemons/dmeventd/mktestdevices
Normal file
12
daemons/dmeventd/mktestdevices
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Create test devices for dmeventd
|
||||||
|
#
|
||||||
|
|
||||||
|
trap "rm -f /tmp/tmp.$$" 0 1 2 3 15
|
||||||
|
|
||||||
|
echo "0 1024 zero" > /tmp/tmp.$$
|
||||||
|
dmsetup create test /tmp/tmp.$$
|
||||||
|
dmsetup create test1 /tmp/tmp.$$
|
||||||
|
|
||||||
|
kill -15 $$
|
||||||
39
daemons/dmeventd/noop.c
Normal file
39
daemons/dmeventd/noop.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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 "libdm-event.h"
|
||||||
|
#include "libmultilog.h"
|
||||||
|
|
||||||
|
|
||||||
|
void process_event(char *device, enum event_type event)
|
||||||
|
{
|
||||||
|
log_err("[%s] %s(%d) - Device: %s, Event %d\n",
|
||||||
|
__FILE__, __func__, __LINE__, device, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
int register_device(char *device)
|
||||||
|
{
|
||||||
|
log_err("[%s] %s(%d) - Device: %s\n",
|
||||||
|
__FILE__, __func__, __LINE__, device);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unregister_device(char *device)
|
||||||
|
{
|
||||||
|
log_err("[%s] %s(%d) - Device: %s\n",
|
||||||
|
__FILE__, __func__, __LINE__, device);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ VPATH = @srcdir@
|
|||||||
CONFSRC=example.conf
|
CONFSRC=example.conf
|
||||||
CONFDEST=lvm.conf
|
CONFDEST=lvm.conf
|
||||||
|
|
||||||
include ../make.tmpl
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
@if [ ! -e $(confdir)/$(CONFDEST) ]; then \
|
||||||
|
|||||||
@@ -27,8 +27,18 @@ devices {
|
|||||||
# the device will be accepted or rejected (ignored). Devices that
|
# the device will be accepted or rejected (ignored). Devices that
|
||||||
# don't match any patterns are accepted.
|
# don't match any patterns are accepted.
|
||||||
|
|
||||||
# Remember to run vgscan after you change this parameter to ensure
|
# Be careful if there there are symbolic links or multiple filesystem
|
||||||
# that the cache file gets regenerated (see below).
|
# 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:
|
# By default we accept every block device:
|
||||||
filter = [ "a/.*/" ]
|
filter = [ "a/.*/" ]
|
||||||
@@ -252,11 +262,10 @@ activation {
|
|||||||
#
|
#
|
||||||
# metadata {
|
# metadata {
|
||||||
# Default number of copies of metadata to hold on each PV. 0, 1 or 2.
|
# Default number of copies of metadata to hold on each PV. 0, 1 or 2.
|
||||||
# It's best to leave this at 2.
|
# You might want to override it from the command line with 0
|
||||||
# You might want to override it from the command line with 0 or 1
|
|
||||||
# when running pvcreate on new PVs which are to be added to large VGs.
|
# when running pvcreate on new PVs which are to be added to large VGs.
|
||||||
|
|
||||||
# pvmetadatacopies = 2
|
# pvmetadatacopies = 1
|
||||||
|
|
||||||
# Approximate default size of on-disk metadata areas in sectors.
|
# Approximate default size of on-disk metadata areas in sectors.
|
||||||
# You should increase this if you have large volume groups or
|
# You should increase this if you have large volume groups or
|
||||||
|
|||||||
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'
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
../daemons/clvmd/clvm.h
|
||||||
../lib/activate/activate.h
|
../lib/activate/activate.h
|
||||||
../lib/activate/targets.h
|
../lib/activate/targets.h
|
||||||
../lib/cache/lvmcache.h
|
../lib/cache/lvmcache.h
|
||||||
@@ -5,9 +6,7 @@
|
|||||||
../lib/commands/toolcontext.h
|
../lib/commands/toolcontext.h
|
||||||
../lib/config/config.h
|
../lib/config/config.h
|
||||||
../lib/config/defaults.h
|
../lib/config/defaults.h
|
||||||
../lib/datastruct/bitset.h
|
|
||||||
../lib/datastruct/btree.h
|
../lib/datastruct/btree.h
|
||||||
../lib/datastruct/hash.h
|
|
||||||
../lib/datastruct/list.h
|
../lib/datastruct/list.h
|
||||||
../lib/datastruct/lvm-types.h
|
../lib/datastruct/lvm-types.h
|
||||||
../lib/datastruct/str_list.h
|
../lib/datastruct/str_list.h
|
||||||
@@ -22,6 +21,7 @@
|
|||||||
../lib/filters/filter.h
|
../lib/filters/filter.h
|
||||||
../lib/format1/format1.h
|
../lib/format1/format1.h
|
||||||
../lib/format_pool/format_pool.h
|
../lib/format_pool/format_pool.h
|
||||||
|
../lib/format_text/archiver.h
|
||||||
../lib/format_text/format-text.h
|
../lib/format_text/format-text.h
|
||||||
../lib/format_text/text_export.h
|
../lib/format_text/text_export.h
|
||||||
../lib/format_text/text_import.h
|
../lib/format_text/text_import.h
|
||||||
@@ -30,19 +30,19 @@
|
|||||||
../lib/log/log.h
|
../lib/log/log.h
|
||||||
../lib/metadata/lv_alloc.h
|
../lib/metadata/lv_alloc.h
|
||||||
../lib/metadata/metadata.h
|
../lib/metadata/metadata.h
|
||||||
../lib/metadata/segtypes.h
|
../lib/metadata/pv_alloc.h
|
||||||
../lib/mm/dbg_malloc.h
|
../lib/metadata/segtype.h
|
||||||
../lib/mm/memlock.h
|
../lib/mm/memlock.h
|
||||||
../lib/mm/pool.h
|
|
||||||
../lib/mm/xlate.h
|
../lib/mm/xlate.h
|
||||||
../lib/misc/crc.h
|
../lib/misc/crc.h
|
||||||
../lib/misc/intl.h
|
../lib/misc/intl.h
|
||||||
../lib/misc/lib.h
|
../lib/misc/lib.h
|
||||||
|
../lib/misc/lvm-exec.h
|
||||||
../lib/misc/lvm-file.h
|
../lib/misc/lvm-file.h
|
||||||
../lib/misc/lvm-string.h
|
../lib/misc/lvm-string.h
|
||||||
../lib/misc/selinux.h
|
|
||||||
../lib/misc/sharedlib.h
|
../lib/misc/sharedlib.h
|
||||||
../lib/regex/matcher.h
|
../lib/regex/matcher.h
|
||||||
../lib/report/report.h
|
../lib/report/report.h
|
||||||
../lib/uuid/uuid.h
|
../lib/uuid/uuid.h
|
||||||
../po/pogen.h
|
../po/pogen.h
|
||||||
|
../tools/version.h
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ VPATH = @srcdir@
|
|||||||
|
|
||||||
LN_S = @LN_S@
|
LN_S = @LN_S@
|
||||||
|
|
||||||
|
.PHONY: clean distclean all install pofile install_cluster
|
||||||
|
|
||||||
all: .symlinks_created
|
all: .symlinks_created
|
||||||
|
|
||||||
.symlinks_created: .symlinks
|
.symlinks_created: .symlinks
|
||||||
@@ -37,5 +39,5 @@ clean:
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
|
|
||||||
.PHONY: clean distclean all install pofile
|
install_cluster:
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of the LVM2.
|
# This file is part of the LVM2.
|
||||||
#
|
#
|
||||||
@@ -37,12 +37,11 @@ SOURCES =\
|
|||||||
cache/lvmcache.c \
|
cache/lvmcache.c \
|
||||||
commands/toolcontext.c \
|
commands/toolcontext.c \
|
||||||
config/config.c \
|
config/config.c \
|
||||||
datastruct/bitset.c \
|
|
||||||
datastruct/btree.c \
|
datastruct/btree.c \
|
||||||
datastruct/hash.c \
|
|
||||||
datastruct/str_list.c \
|
datastruct/str_list.c \
|
||||||
device/dev-cache.c \
|
device/dev-cache.c \
|
||||||
device/dev-io.c \
|
device/dev-io.c \
|
||||||
|
device/dev-md.c \
|
||||||
device/device.c \
|
device/device.c \
|
||||||
display/display.c \
|
display/display.c \
|
||||||
error/errseg.c \
|
error/errseg.c \
|
||||||
@@ -53,6 +52,7 @@ SOURCES =\
|
|||||||
filters/filter-md.c \
|
filters/filter-md.c \
|
||||||
filters/filter.c \
|
filters/filter.c \
|
||||||
format_text/archive.c \
|
format_text/archive.c \
|
||||||
|
format_text/archiver.c \
|
||||||
format_text/export.c \
|
format_text/export.c \
|
||||||
format_text/flags.c \
|
format_text/flags.c \
|
||||||
format_text/format-text.c \
|
format_text/format-text.c \
|
||||||
@@ -69,14 +69,15 @@ SOURCES =\
|
|||||||
metadata/merge.c \
|
metadata/merge.c \
|
||||||
metadata/metadata.c \
|
metadata/metadata.c \
|
||||||
metadata/mirror.c \
|
metadata/mirror.c \
|
||||||
|
metadata/pv_manip.c \
|
||||||
metadata/pv_map.c \
|
metadata/pv_map.c \
|
||||||
metadata/segtypes.c \
|
metadata/segtype.c \
|
||||||
metadata/snapshot_manip.c \
|
metadata/snapshot_manip.c \
|
||||||
misc/crc.c \
|
misc/crc.c \
|
||||||
|
misc/lvm-exec.c \
|
||||||
misc/lvm-file.c \
|
misc/lvm-file.c \
|
||||||
misc/lvm-string.c \
|
misc/lvm-string.c \
|
||||||
mm/memlock.c \
|
mm/memlock.c \
|
||||||
mm/pool.c \
|
|
||||||
regex/matcher.c \
|
regex/matcher.c \
|
||||||
regex/parse_rx.c \
|
regex/parse_rx.c \
|
||||||
regex/ttree.c \
|
regex/ttree.c \
|
||||||
@@ -104,6 +105,14 @@ ifeq ("@POOL@", "internal")
|
|||||||
format_pool/pool_label.c
|
format_pool/pool_label.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ("@CLUSTER@", "internal")
|
||||||
|
SOURCES += locking/cluster_locking.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ("@CLUSTER@", "shared")
|
||||||
|
SUBDIRS += locking
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ("@SNAPSHOTS@", "internal")
|
ifeq ("@SNAPSHOTS@", "internal")
|
||||||
SOURCES += snapshot/snapshot.c
|
SOURCES += snapshot/snapshot.c
|
||||||
endif
|
endif
|
||||||
@@ -112,10 +121,6 @@ ifeq ("@MIRRORS@", "internal")
|
|||||||
SOURCES += mirror/mirrored.c
|
SOURCES += mirror/mirrored.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ("@DEBUG@", "yes")
|
|
||||||
SOURCES += mm/dbg_malloc.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ("@DEVMAPPER@", "yes")
|
ifeq ("@DEVMAPPER@", "yes")
|
||||||
SOURCES +=\
|
SOURCES +=\
|
||||||
activate/dev_manager.c \
|
activate/dev_manager.c \
|
||||||
@@ -128,13 +133,9 @@ ifeq ("@HAVE_LIBDL@", "yes")
|
|||||||
misc/sharedlib.c
|
misc/sharedlib.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ("@HAVE_SELINUX@", "yes")
|
|
||||||
SOURCES += misc/selinux.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
LIB_STATIC = liblvm.a
|
LIB_STATIC = liblvm.a
|
||||||
|
|
||||||
$(SUBDIRS): $(LIB_STATIC)
|
$(SUBDIRS): $(LIB_STATIC)
|
||||||
|
|
||||||
include ../make.tmpl
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||||
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
|
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of LVM2.
|
* This file is part of LVM2.
|
||||||
*
|
*
|
||||||
@@ -19,13 +19,14 @@
|
|||||||
#include "memlock.h"
|
#include "memlock.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include "lvm-exec.h"
|
||||||
#include "lvm-file.h"
|
#include "lvm-file.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "dev_manager.h"
|
#include "dev_manager.h"
|
||||||
#include "str_list.h"
|
#include "str_list.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -78,12 +79,13 @@ int target_present(const char *target_name)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
|
||||||
|
int with_open_count)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||||
struct lvinfo *info)
|
struct lvinfo *info, int with_open_count)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -129,11 +131,11 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
|
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -143,6 +145,12 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
|
||||||
|
struct volume_group *vg)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void activation_exit(void)
|
void activation_exit(void)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -256,53 +264,28 @@ int library_version(char *version, size_t size)
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!dm_get_library_version(version, size))
|
return dm_get_library_version(version, size);
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int driver_version(char *version, size_t size)
|
int driver_version(char *version, size_t size)
|
||||||
{
|
{
|
||||||
int r = 0;
|
|
||||||
struct dm_task *dmt;
|
|
||||||
|
|
||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
log_very_verbose("Getting driver version");
|
log_very_verbose("Getting driver version");
|
||||||
if (!(dmt = dm_task_create(DM_DEVICE_VERSION))) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dm_task_run(dmt))
|
return dm_driver_version(version, size);
|
||||||
log_error("Failed to get driver version");
|
|
||||||
|
|
||||||
if (!dm_task_get_driver_version(dmt, version, size))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
r = 1;
|
|
||||||
|
|
||||||
out:
|
|
||||||
dm_task_destroy(dmt);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int target_present(const char *target_name)
|
static int _target_present(const char *target_name)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
struct dm_task *dmt;
|
struct dm_task *dmt;
|
||||||
struct dm_versions *target, *last_target;
|
struct dm_versions *target, *last_target;
|
||||||
|
|
||||||
if (!activation())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
log_very_verbose("Getting target version for %s", target_name);
|
log_very_verbose("Getting target version for %s", target_name);
|
||||||
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) {
|
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dm_task_run(dmt)) {
|
if (!dm_task_run(dmt)) {
|
||||||
log_debug("Failed to get %s target version", target_name);
|
log_debug("Failed to get %s target version", target_name);
|
||||||
@@ -329,26 +312,56 @@ int target_present(const char *target_name)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int target_present(const char *target_name, int use_modprobe)
|
||||||
* Returns 1 if info structure populated, else 0 on failure.
|
|
||||||
*/
|
|
||||||
static int _lv_info(const struct logical_volume *lv, int mknodes,
|
|
||||||
struct lvinfo *info)
|
|
||||||
{
|
{
|
||||||
int r;
|
#ifdef MODPROBE_CMD
|
||||||
struct dev_manager *dm;
|
char module[128];
|
||||||
struct dm_info dminfo;
|
#endif
|
||||||
|
|
||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
#ifdef MODPROBE_CMD
|
||||||
stack;
|
if (use_modprobe) {
|
||||||
return 0;
|
if (_target_present(target_name))
|
||||||
}
|
return 1;
|
||||||
|
|
||||||
if (!(r = dev_manager_info(dm, lv, mknodes, &dminfo)))
|
if (lvm_snprintf(module, sizeof(module), "dm-%s", target_name)
|
||||||
stack;
|
< 0) {
|
||||||
|
log_error("target_present module name too long: %s",
|
||||||
|
target_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exec_cmd(MODPROBE_CMD, module, "", ""))
|
||||||
|
return_0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return _target_present(target_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns 1 if info structure populated, else 0 on failure.
|
||||||
|
*/
|
||||||
|
static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int with_mknodes,
|
||||||
|
struct lvinfo *info, int with_open_count)
|
||||||
|
{
|
||||||
|
struct dm_info dminfo;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if (!activation())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(name = build_dm_name(cmd->mem, lv->vg->name, lv->name, NULL)))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
log_debug("Getting device info for %s", name);
|
||||||
|
if (!dev_manager_info(lv->vg->cmd->mem, name, lv, with_mknodes,
|
||||||
|
with_open_count, &dminfo)) {
|
||||||
|
dm_pool_free(cmd->mem, name);
|
||||||
|
return_0;
|
||||||
|
}
|
||||||
|
|
||||||
info->exists = dminfo.exists;
|
info->exists = dminfo.exists;
|
||||||
info->suspended = dminfo.suspended;
|
info->suspended = dminfo.suspended;
|
||||||
@@ -356,25 +369,28 @@ static int _lv_info(const struct logical_volume *lv, int mknodes,
|
|||||||
info->major = dminfo.major;
|
info->major = dminfo.major;
|
||||||
info->minor = dminfo.minor;
|
info->minor = dminfo.minor;
|
||||||
info->read_only = dminfo.read_only;
|
info->read_only = dminfo.read_only;
|
||||||
|
info->live_table = dminfo.live_table;
|
||||||
|
info->inactive_table = dminfo.inactive_table;
|
||||||
|
|
||||||
dev_manager_destroy(dm);
|
dm_pool_free(cmd->mem, name);
|
||||||
return r;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info)
|
int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, struct lvinfo *info,
|
||||||
|
int with_open_count)
|
||||||
{
|
{
|
||||||
return _lv_info(lv, 0, info);
|
return _lv_info(cmd, lv, 0, info, with_open_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||||
struct lvinfo *info)
|
struct lvinfo *info, int with_open_count)
|
||||||
{
|
{
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
|
|
||||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return _lv_info(lv, 0, info);
|
return _lv_info(cmd, lv, 0, info, with_open_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -388,10 +404,8 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
|
if (!(r = dev_manager_snapshot_percent(dm, lv, percent)))
|
||||||
stack;
|
stack;
|
||||||
@@ -402,7 +416,7 @@ int lv_snapshot_percent(struct logical_volume *lv, float *percent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME Merge with snapshot_percent */
|
/* FIXME Merge with snapshot_percent */
|
||||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
|
||||||
uint32_t *event_nr)
|
uint32_t *event_nr)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@@ -412,18 +426,14 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!lv_info(lv, &info)) {
|
if (!lv_info(cmd, lv, &info, 0))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!info.exists)
|
if (!info.exists)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
|
if (!(r = dev_manager_mirror_percent(dm, lv, wait, percent, event_nr)))
|
||||||
stack;
|
stack;
|
||||||
@@ -433,11 +443,11 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _lv_active(struct logical_volume *lv)
|
static int _lv_active(struct cmd_context *cmd, struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
struct lvinfo info;
|
struct lvinfo info;
|
||||||
|
|
||||||
if (!lv_info(lv, &info)) {
|
if (!lv_info(cmd, lv, &info, 0)) {
|
||||||
stack;
|
stack;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -445,11 +455,11 @@ static int _lv_active(struct logical_volume *lv)
|
|||||||
return info.exists;
|
return info.exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _lv_open_count(struct logical_volume *lv)
|
static int _lv_open_count(struct cmd_context *cmd, struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
struct lvinfo info;
|
struct lvinfo info;
|
||||||
|
|
||||||
if (!lv_info(lv, &info)) {
|
if (!lv_info(cmd, lv, &info, 1)) {
|
||||||
stack;
|
stack;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -457,16 +467,13 @@ static int _lv_open_count(struct logical_volume *lv)
|
|||||||
return info.open_count;
|
return info.open_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME Need to detect and handle an lv rename */
|
|
||||||
static int _lv_activate_lv(struct logical_volume *lv)
|
static int _lv_activate_lv(struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
struct dev_manager *dm;
|
struct dev_manager *dm;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(r = dev_manager_activate(dm, lv)))
|
if (!(r = dev_manager_activate(dm, lv)))
|
||||||
stack;
|
stack;
|
||||||
@@ -475,15 +482,28 @@ static int _lv_activate_lv(struct logical_volume *lv)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _lv_preload(struct logical_volume *lv)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
struct dev_manager *dm;
|
||||||
|
|
||||||
|
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
if (!(r = dev_manager_preload(dm, lv)))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
dev_manager_destroy(dm);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int _lv_deactivate(struct logical_volume *lv)
|
static int _lv_deactivate(struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
struct dev_manager *dm;
|
struct dev_manager *dm;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(r = dev_manager_deactivate(dm, lv)))
|
if (!(r = dev_manager_deactivate(dm, lv)))
|
||||||
stack;
|
stack;
|
||||||
@@ -497,10 +517,8 @@ static int _lv_suspend_lv(struct logical_volume *lv)
|
|||||||
int r;
|
int r;
|
||||||
struct dev_manager *dm;
|
struct dev_manager *dm;
|
||||||
|
|
||||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name))) {
|
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name)))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(r = dev_manager_suspend(dm, lv)))
|
if (!(r = dev_manager_suspend(dm, lv)))
|
||||||
stack;
|
stack;
|
||||||
@@ -515,17 +533,15 @@ static int _lv_suspend_lv(struct logical_volume *lv)
|
|||||||
*/
|
*/
|
||||||
int lvs_in_vg_activated(struct volume_group *vg)
|
int lvs_in_vg_activated(struct volume_group *vg)
|
||||||
{
|
{
|
||||||
struct list *lvh;
|
struct lv_list *lvl;
|
||||||
struct logical_volume *lv;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
list_iterate(lvh, &vg->lvs) {
|
list_iterate_items(lvl, &vg->lvs) {
|
||||||
lv = list_item(lvh, struct lv_list)->lv;
|
if (lvl->lv->status & VISIBLE_LV)
|
||||||
if (lv->status & VISIBLE_LV)
|
count += (_lv_active(vg->cmd, lvl->lv) == 1);
|
||||||
count += (_lv_active(lv) == 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
@@ -533,17 +549,15 @@ int lvs_in_vg_activated(struct volume_group *vg)
|
|||||||
|
|
||||||
int lvs_in_vg_opened(struct volume_group *vg)
|
int lvs_in_vg_opened(struct volume_group *vg)
|
||||||
{
|
{
|
||||||
struct list *lvh;
|
struct lv_list *lvl;
|
||||||
struct logical_volume *lv;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
if (!activation())
|
if (!activation())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
list_iterate(lvh, &vg->lvs) {
|
list_iterate_items(lvl, &vg->lvs) {
|
||||||
lv = list_item(lvh, struct lv_list)->lv;
|
if (lvl->lv->status & VISIBLE_LV)
|
||||||
if (lv->status & VISIBLE_LV)
|
count += (_lv_open_count(vg->cmd, lvl->lv) > 0);
|
||||||
count += (_lv_open_count(lv) > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
@@ -558,7 +572,8 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
/* Use precommitted metadata if present */
|
||||||
|
if (!(lv = lv_from_lvid(cmd, lvid_s, 1)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (test_mode()) {
|
if (test_mode()) {
|
||||||
@@ -566,14 +581,20 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lv_info(lv, &info)) {
|
if (!lv_info(cmd, lv, &info, 0))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!info.exists || info.suspended)
|
if (!info.exists || info.suspended)
|
||||||
return error_if_not_suspended ? 0 : 1;
|
return error_if_not_suspended ? 0 : 1;
|
||||||
|
|
||||||
|
/* If VG was precommitted, preload devices for the LV */
|
||||||
|
if ((lv->vg->status & PRECOMMITTED)) {
|
||||||
|
if (!_lv_preload(lv)) {
|
||||||
|
/* FIXME Revert preloading */
|
||||||
|
return_0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memlock_inc();
|
memlock_inc();
|
||||||
if (!_lv_suspend_lv(lv)) {
|
if (!_lv_suspend_lv(lv)) {
|
||||||
memlock_dec();
|
memlock_dec();
|
||||||
@@ -604,7 +625,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (test_mode()) {
|
if (test_mode()) {
|
||||||
@@ -612,10 +633,8 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lv_info(lv, &info)) {
|
if (!lv_info(cmd, lv, &info, 0))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!info.exists || !info.suspended)
|
if (!info.exists || !info.suspended)
|
||||||
return error_if_not_active ? 0 : 1;
|
return error_if_not_active ? 0 : 1;
|
||||||
@@ -649,7 +668,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (test_mode()) {
|
if (test_mode()) {
|
||||||
@@ -657,16 +676,14 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lv_info(lv, &info)) {
|
if (!lv_info(cmd, lv, &info, 1))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!info.exists)
|
if (!info.exists)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (info.open_count && (lv->status & VISIBLE_LV)) {
|
if (info.open_count && (lv->status & VISIBLE_LV)) {
|
||||||
log_error("LV %s/%s in use: not removing", lv->vg->name,
|
log_error("LV %s/%s in use: not deactivating", lv->vg->name,
|
||||||
lv->name);
|
lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -688,7 +705,7 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
goto activate;
|
goto activate;
|
||||||
|
|
||||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!_passes_activation_filter(cmd, lv)) {
|
if (!_passes_activation_filter(cmd, lv)) {
|
||||||
@@ -703,7 +720,8 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
|
||||||
|
int exclusive, int filter)
|
||||||
{
|
{
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
struct lvinfo info;
|
struct lvinfo info;
|
||||||
@@ -712,7 +730,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
|||||||
if (!activation())
|
if (!activation())
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!(lv = lv_from_lvid(cmd, lvid_s)))
|
if (!(lv = lv_from_lvid(cmd, lvid_s, 0)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (filter && !_passes_activation_filter(cmd, lv)) {
|
if (filter && !_passes_activation_filter(cmd, lv)) {
|
||||||
@@ -726,14 +744,15 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lv_info(lv, &info)) {
|
if (!lv_info(cmd, lv, &info, 0))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.exists && !info.suspended)
|
if (info.exists && !info.suspended && info.live_table)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (exclusive)
|
||||||
|
lv->status |= ACTIVATE_EXCL;
|
||||||
|
|
||||||
memlock_inc();
|
memlock_inc();
|
||||||
r = _lv_activate_lv(lv);
|
r = _lv_activate_lv(lv);
|
||||||
memlock_dec();
|
memlock_dec();
|
||||||
@@ -743,15 +762,15 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s, int filter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Activate LV */
|
/* Activate LV */
|
||||||
int lv_activate(struct cmd_context *cmd, const char *lvid_s)
|
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||||
{
|
{
|
||||||
return _lv_activate(cmd, lvid_s, 0);
|
return _lv_activate(cmd, lvid_s, exclusive, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Activate LV only if it passes filter */
|
/* Activate LV only if it passes filter */
|
||||||
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s)
|
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive)
|
||||||
{
|
{
|
||||||
return _lv_activate(cmd, lvid_s, 1);
|
return _lv_activate(cmd, lvid_s, exclusive, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
||||||
@@ -760,15 +779,13 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
|||||||
int r = 1;
|
int r = 1;
|
||||||
|
|
||||||
if (!lv) {
|
if (!lv) {
|
||||||
r = dev_manager_mknodes();
|
r = dm_mknodes(NULL);
|
||||||
fs_unlock();
|
fs_unlock();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_lv_info(lv, 1, &info)) {
|
if (!_lv_info(cmd, lv, 1, &info, 0))
|
||||||
stack;
|
return_0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.exists)
|
if (info.exists)
|
||||||
r = dev_manager_lv_mknodes(lv);
|
r = dev_manager_lv_mknodes(lv);
|
||||||
@@ -780,6 +797,34 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does PV use VG somewhere in its construction?
|
||||||
|
* Returns 1 on failure.
|
||||||
|
*/
|
||||||
|
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
|
||||||
|
struct volume_group *vg)
|
||||||
|
{
|
||||||
|
struct dev_manager *dm;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!activation())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!dm_is_dm_major(MAJOR(pv->dev->dev)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(dm = dev_manager_create(cmd, vg->name))) {
|
||||||
|
stack;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = dev_manager_device_uses_vg(dm, pv->dev, vg);
|
||||||
|
|
||||||
|
dev_manager_destroy(dm);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void activation_exit(void)
|
void activation_exit(void)
|
||||||
{
|
{
|
||||||
dev_manager_exit();
|
dev_manager_exit();
|
||||||
|
|||||||
@@ -18,10 +18,6 @@
|
|||||||
|
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
|
||||||
#ifdef DEVMAPPER_SUPPORT
|
|
||||||
# include <libdevmapper.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct lvinfo {
|
struct lvinfo {
|
||||||
int exists;
|
int exists;
|
||||||
int suspended;
|
int suspended;
|
||||||
@@ -29,6 +25,8 @@ struct lvinfo {
|
|||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
int read_only;
|
int read_only;
|
||||||
|
int live_table;
|
||||||
|
int inactive_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_activation(int activation);
|
void set_activation(int activation);
|
||||||
@@ -38,7 +36,7 @@ int driver_version(char *version, size_t size);
|
|||||||
int library_version(char *version, size_t size);
|
int library_version(char *version, size_t size);
|
||||||
int lvm1_present(struct cmd_context *cmd);
|
int lvm1_present(struct cmd_context *cmd);
|
||||||
|
|
||||||
int target_present(const char *target_name);
|
int target_present(const char *target_name, int use_modprobe);
|
||||||
|
|
||||||
void activation_exit(void);
|
void activation_exit(void);
|
||||||
|
|
||||||
@@ -46,8 +44,9 @@ 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_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(struct cmd_context *cmd, const char *lvid_s);
|
||||||
int lv_resume_if_active(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 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 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_deactivate(struct cmd_context *cmd, const char *lvid_s);
|
||||||
|
|
||||||
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
||||||
@@ -55,9 +54,10 @@ int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
|
|||||||
/*
|
/*
|
||||||
* Returns 1 if info structure has been populated, else 0.
|
* Returns 1 if info structure has been populated, else 0.
|
||||||
*/
|
*/
|
||||||
int lv_info(const struct logical_volume *lv, struct lvinfo *info);
|
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,
|
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s,
|
||||||
struct lvinfo *info);
|
struct lvinfo *info, int with_open_count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
|
* Returns 1 if activate_lv has been set: 1 = activate; 0 = don't.
|
||||||
@@ -69,7 +69,7 @@ int lv_activation_filter(struct cmd_context *cmd, const char *lvid_s,
|
|||||||
* Returns 1 if percent has been set, else 0.
|
* Returns 1 if percent has been set, else 0.
|
||||||
*/
|
*/
|
||||||
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
|
int lv_snapshot_percent(struct logical_volume *lv, float *percent);
|
||||||
int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
int lv_mirror_percent(struct cmd_context *cmd, struct logical_volume *lv, int wait, float *percent,
|
||||||
uint32_t *event_nr);
|
uint32_t *event_nr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -78,6 +78,10 @@ int lv_mirror_percent(struct logical_volume *lv, int wait, float *percent,
|
|||||||
int lvs_in_vg_activated(struct volume_group *vg);
|
int lvs_in_vg_activated(struct volume_group *vg);
|
||||||
int lvs_in_vg_opened(struct volume_group *vg);
|
int lvs_in_vg_opened(struct volume_group *vg);
|
||||||
|
|
||||||
int lv_setup_cow_store(struct logical_volume *lv);
|
/*
|
||||||
|
* Returns 1 if PV has a dependency tree that uses anything in VG.
|
||||||
|
*/
|
||||||
|
int pv_uses_vg(struct cmd_context *cmd, struct physical_volume *pv,
|
||||||
|
struct volume_group *vg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -17,9 +17,11 @@
|
|||||||
#define _LVM_DEV_MANAGER_H
|
#define _LVM_DEV_MANAGER_H
|
||||||
|
|
||||||
struct logical_volume;
|
struct logical_volume;
|
||||||
|
struct volume_group;
|
||||||
struct cmd_context;
|
struct cmd_context;
|
||||||
struct dev_manager;
|
struct dev_manager;
|
||||||
struct dm_info;
|
struct dm_info;
|
||||||
|
struct device;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor and destructor.
|
* Constructor and destructor.
|
||||||
@@ -35,8 +37,9 @@ void dev_manager_exit(void);
|
|||||||
* (eg, an origin is created before its snapshot, but is not
|
* (eg, an origin is created before its snapshot, but is not
|
||||||
* unsuspended until the snapshot is also created.)
|
* unsuspended until the snapshot is also created.)
|
||||||
*/
|
*/
|
||||||
int dev_manager_info(struct dev_manager *dm, const struct logical_volume *lv,
|
int dev_manager_info(struct dm_pool *mem, const char *name,
|
||||||
int mknodes, struct dm_info *info);
|
const struct logical_volume *lv,
|
||||||
|
int mknodes, int with_open_count, struct dm_info *info);
|
||||||
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
int dev_manager_snapshot_percent(struct dev_manager *dm,
|
||||||
struct logical_volume *lv, float *percent);
|
struct logical_volume *lv, float *percent);
|
||||||
int dev_manager_mirror_percent(struct dev_manager *dm,
|
int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||||
@@ -44,15 +47,18 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
|
|||||||
float *percent, uint32_t *event_nr);
|
float *percent, uint32_t *event_nr);
|
||||||
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
|
int dev_manager_suspend(struct dev_manager *dm, struct logical_volume *lv);
|
||||||
int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv);
|
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_deactivate(struct dev_manager *dm, struct logical_volume *lv);
|
||||||
|
|
||||||
int dev_manager_lv_mknodes(const struct logical_volume *lv);
|
int dev_manager_lv_mknodes(const struct logical_volume *lv);
|
||||||
int dev_manager_lv_rmnodes(const struct logical_volume *lv);
|
int dev_manager_lv_rmnodes(const struct logical_volume *lv);
|
||||||
int dev_manager_mknodes(void);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put the desired changes into effect.
|
* Put the desired changes into effect.
|
||||||
*/
|
*/
|
||||||
int dev_manager_execute(struct dev_manager *dm);
|
int dev_manager_execute(struct dev_manager *dm);
|
||||||
|
|
||||||
|
int dev_manager_device_uses_vg(struct dev_manager *dm, struct device *dev,
|
||||||
|
struct volume_group *vg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,16 +20,11 @@
|
|||||||
#include "lvm-file.h"
|
#include "lvm-file.h"
|
||||||
#include "memlock.h"
|
#include "memlock.h"
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
|
||||||
# include "selinux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <libdevmapper.h>
|
|
||||||
|
|
||||||
static int _mk_dir(const char *dev_dir, const char *vg_name)
|
static int _mk_dir(const char *dev_dir, const char *vg_name)
|
||||||
{
|
{
|
||||||
@@ -46,7 +41,7 @@ static int _mk_dir(const char *dev_dir, const char *vg_name)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
log_very_verbose("Creating directory %s", vg_path);
|
log_very_verbose("Creating directory %s", vg_path);
|
||||||
if (mkdir(vg_path, 0555)) {
|
if (mkdir(vg_path, 0777)) {
|
||||||
log_sys_error("mkdir", vg_path);
|
log_sys_error("mkdir", vg_path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -65,10 +60,10 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_very_verbose("Removing directory %s", vg_path);
|
if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
|
||||||
|
log_very_verbose("Removing directory %s", vg_path);
|
||||||
if (is_empty_dir(vg_path))
|
|
||||||
rmdir(vg_path);
|
rmdir(vg_path);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -180,7 +175,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
if (!set_selinux_context(lv_path)) {
|
if (!dm_set_selinux_context(lv_path, S_IFLNK)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -202,9 +197,9 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
|
if (lstat(lv_path, &buf) || !S_ISLNK(buf.st_mode)) {
|
||||||
if (errno != ENOENT)
|
if (errno == ENOENT)
|
||||||
log_error("%s not symbolic link - not removing",
|
return 1;
|
||||||
lv_path);
|
log_error("%s not symbolic link - not removing", lv_path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +278,7 @@ static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
|
|||||||
strlen(dev) + strlen(old_lv_name) + 5;
|
strlen(dev) + strlen(old_lv_name) + 5;
|
||||||
char *pos;
|
char *pos;
|
||||||
|
|
||||||
if (!(fsp = dbg_malloc(sizeof(*fsp) + len))) {
|
if (!(fsp = dm_malloc(sizeof(*fsp) + len))) {
|
||||||
log_error("No space to stack fs operation");
|
log_error("No space to stack fs operation");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -312,7 +307,7 @@ static void _pop_fs_ops(void)
|
|||||||
_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
|
_do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
|
||||||
fsp->dev, fsp->old_lv_name);
|
fsp->dev, fsp->old_lv_name);
|
||||||
list_del(&fsp->list);
|
list_del(&fsp->list);
|
||||||
dbg_free(fsp);
|
dm_free(fsp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,16 @@
|
|||||||
struct dev_manager;
|
struct dev_manager;
|
||||||
struct lv_segment;
|
struct lv_segment;
|
||||||
|
|
||||||
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg, char *params, size_t paramsize, int *pos,
|
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||||
int start_area, int areas);
|
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, int start_area, int 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
|
#endif
|
||||||
|
|||||||
161
lib/cache/lvmcache.c
vendored
161
lib/cache/lvmcache.c
vendored
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "dev-cache.h"
|
#include "dev-cache.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
@@ -24,10 +23,10 @@
|
|||||||
#include "memlock.h"
|
#include "memlock.h"
|
||||||
#include "str_list.h"
|
#include "str_list.h"
|
||||||
|
|
||||||
static struct hash_table *_pvid_hash = NULL;
|
static struct dm_hash_table *_pvid_hash = NULL;
|
||||||
static struct hash_table *_vgid_hash = NULL;
|
static struct dm_hash_table *_vgid_hash = NULL;
|
||||||
static struct hash_table *_vgname_hash = NULL;
|
static struct dm_hash_table *_vgname_hash = NULL;
|
||||||
static struct hash_table *_lock_hash = NULL;
|
static struct dm_hash_table *_lock_hash = NULL;
|
||||||
static struct list _vginfos;
|
static struct list _vginfos;
|
||||||
static int _has_scanned = 0;
|
static int _has_scanned = 0;
|
||||||
static int _vgs_locked = 0;
|
static int _vgs_locked = 0;
|
||||||
@@ -36,16 +35,16 @@ int lvmcache_init(void)
|
|||||||
{
|
{
|
||||||
list_init(&_vginfos);
|
list_init(&_vginfos);
|
||||||
|
|
||||||
if (!(_vgname_hash = hash_create(128)))
|
if (!(_vgname_hash = dm_hash_create(128)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(_vgid_hash = hash_create(128)))
|
if (!(_vgid_hash = dm_hash_create(128)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(_pvid_hash = hash_create(128)))
|
if (!(_pvid_hash = dm_hash_create(128)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(_lock_hash = hash_create(128)))
|
if (!(_lock_hash = dm_hash_create(128)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -58,25 +57,24 @@ void lvmcache_lock_vgname(const char *vgname, int read_only)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hash_insert(_lock_hash, vgname, (void *) 1))
|
if (!dm_hash_insert(_lock_hash, vgname, (void *) 1))
|
||||||
log_error("Cache locking failure for %s", vgname);
|
log_error("Cache locking failure for %s", vgname);
|
||||||
|
|
||||||
_vgs_locked++;
|
_vgs_locked++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _vgname_is_locked(const char *vgname) __attribute__ ((unused));
|
int vgname_is_locked(const char *vgname)
|
||||||
static int _vgname_is_locked(const char *vgname)
|
|
||||||
{
|
{
|
||||||
if (!_lock_hash)
|
if (!_lock_hash)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return hash_lookup(_lock_hash, vgname) ? 1 : 0;
|
return dm_hash_lookup(_lock_hash, vgname) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lvmcache_unlock_vgname(const char *vgname)
|
void lvmcache_unlock_vgname(const char *vgname)
|
||||||
{
|
{
|
||||||
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
|
/* FIXME: Clear all CACHE_LOCKED flags in this vg */
|
||||||
hash_remove(_lock_hash, vgname);
|
dm_hash_remove(_lock_hash, vgname);
|
||||||
|
|
||||||
/* FIXME Do this per-VG */
|
/* FIXME Do this per-VG */
|
||||||
if (!--_vgs_locked)
|
if (!--_vgs_locked)
|
||||||
@@ -95,7 +93,7 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
|
|||||||
if (!_vgname_hash)
|
if (!_vgname_hash)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(vginfo = hash_lookup(_vgname_hash, vgname)))
|
if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return vginfo;
|
return vginfo;
|
||||||
@@ -104,10 +102,31 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname)
|
|||||||
const struct format_type *fmt_from_vgname(const char *vgname)
|
const struct format_type *fmt_from_vgname(const char *vgname)
|
||||||
{
|
{
|
||||||
struct lvmcache_vginfo *vginfo;
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
struct label *label;
|
||||||
|
struct list *devh, *tmp;
|
||||||
|
struct list devs;
|
||||||
|
struct device_list *devl;
|
||||||
|
|
||||||
if (!(vginfo = vginfo_from_vgname(vgname)))
|
if (!(vginfo = vginfo_from_vgname(vgname)))
|
||||||
return NULL;
|
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) {
|
||||||
|
devl = dm_malloc(sizeof(*devl));
|
||||||
|
devl->dev = info->dev;
|
||||||
|
list_add(&devs, &devl->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
return vginfo->fmt;
|
return vginfo->fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +142,7 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid)
|
|||||||
strncpy(&id[0], vgid, ID_LEN);
|
strncpy(&id[0], vgid, ID_LEN);
|
||||||
id[ID_LEN] = '\0';
|
id[ID_LEN] = '\0';
|
||||||
|
|
||||||
if (!(vginfo = hash_lookup(_vgid_hash, id)))
|
if (!(vginfo = dm_hash_lookup(_vgid_hash, id)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return vginfo;
|
return vginfo;
|
||||||
@@ -140,7 +159,7 @@ struct lvmcache_info *info_from_pvid(const char *pvid)
|
|||||||
strncpy(&id[0], pvid, ID_LEN);
|
strncpy(&id[0], pvid, ID_LEN);
|
||||||
id[ID_LEN] = '\0';
|
id[ID_LEN] = '\0';
|
||||||
|
|
||||||
if (!(info = hash_lookup(_pvid_hash, id)))
|
if (!(info = dm_hash_lookup(_pvid_hash, id)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
@@ -156,7 +175,7 @@ static void _rescan_entry(struct lvmcache_info *info)
|
|||||||
|
|
||||||
static int _scan_invalid(void)
|
static int _scan_invalid(void)
|
||||||
{
|
{
|
||||||
hash_iter(_pvid_hash, (iterate_fn) _rescan_entry);
|
dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _rescan_entry);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -166,7 +185,6 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
|||||||
struct label *label;
|
struct label *label;
|
||||||
struct dev_iter *iter;
|
struct dev_iter *iter;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct list *fmth;
|
|
||||||
struct format_type *fmt;
|
struct format_type *fmt;
|
||||||
|
|
||||||
static int _scanning_in_progress = 0;
|
static int _scanning_in_progress = 0;
|
||||||
@@ -188,7 +206,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(iter = dev_iter_create(cmd->filter))) {
|
if (!(iter = dev_iter_create(cmd->filter, (full_scan == 2) ? 1: 0))) {
|
||||||
log_error("dev_iter creation failed");
|
log_error("dev_iter creation failed");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -201,8 +219,7 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan)
|
|||||||
_has_scanned = 1;
|
_has_scanned = 1;
|
||||||
|
|
||||||
/* Perform any format-specific scanning e.g. text files */
|
/* Perform any format-specific scanning e.g. text files */
|
||||||
list_iterate(fmth, &cmd->formats) {
|
list_iterate_items(fmt, &cmd->formats) {
|
||||||
fmt = list_item(fmth, struct format_type);
|
|
||||||
if (fmt->ops->scan && !fmt->ops->scan(fmt))
|
if (fmt->ops->scan && !fmt->ops->scan(fmt))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -229,7 +246,7 @@ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan)
|
|||||||
|
|
||||||
list_iterate_items(vgi, &_vginfos) {
|
list_iterate_items(vgi, &_vginfos) {
|
||||||
if (!str_list_add(cmd->mem, vgnames,
|
if (!str_list_add(cmd->mem, vgnames,
|
||||||
pool_strdup(cmd->mem, vgi->vgname))) {
|
dm_pool_strdup(cmd->mem, vgi->vgname))) {
|
||||||
log_error("strlist allocation failed");
|
log_error("strlist allocation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -266,7 +283,7 @@ struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid)
|
|||||||
if (memlock())
|
if (memlock())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
lvmcache_label_scan(cmd, 1);
|
lvmcache_label_scan(cmd, 2);
|
||||||
|
|
||||||
/* Try again */
|
/* Try again */
|
||||||
if ((info = info_from_pvid((char *) pvid))) {
|
if ((info = info_from_pvid((char *) pvid))) {
|
||||||
@@ -288,13 +305,13 @@ static void _drop_vginfo(struct lvmcache_info *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (info->vginfo && list_empty(&info->vginfo->infos)) {
|
if (info->vginfo && list_empty(&info->vginfo->infos)) {
|
||||||
hash_remove(_vgname_hash, info->vginfo->vgname);
|
dm_hash_remove(_vgname_hash, info->vginfo->vgname);
|
||||||
if (info->vginfo->vgname)
|
if (info->vginfo->vgname)
|
||||||
dbg_free(info->vginfo->vgname);
|
dm_free(info->vginfo->vgname);
|
||||||
if (*info->vginfo->vgid)
|
if (*info->vginfo->vgid)
|
||||||
hash_remove(_vgid_hash, info->vginfo->vgid);
|
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||||
list_del(&info->vginfo->list);
|
list_del(&info->vginfo->list);
|
||||||
dbg_free(info->vginfo);
|
dm_free(info->vginfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
info->vginfo = NULL;
|
info->vginfo = NULL;
|
||||||
@@ -304,13 +321,13 @@ static void _drop_vginfo(struct lvmcache_info *info)
|
|||||||
void lvmcache_del(struct lvmcache_info *info)
|
void lvmcache_del(struct lvmcache_info *info)
|
||||||
{
|
{
|
||||||
if (info->dev->pvid[0] && _pvid_hash)
|
if (info->dev->pvid[0] && _pvid_hash)
|
||||||
hash_remove(_pvid_hash, info->dev->pvid);
|
dm_hash_remove(_pvid_hash, info->dev->pvid);
|
||||||
|
|
||||||
_drop_vginfo(info);
|
_drop_vginfo(info);
|
||||||
|
|
||||||
info->label->labeller->ops->destroy_label(info->label->labeller,
|
info->label->labeller->ops->destroy_label(info->label->labeller,
|
||||||
info->label);
|
info->label);
|
||||||
dbg_free(info);
|
dm_free(info);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} */
|
} */
|
||||||
@@ -320,10 +337,10 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid)
|
|||||||
if (!strcmp(info->dev->pvid, pvid))
|
if (!strcmp(info->dev->pvid, pvid))
|
||||||
return 1;
|
return 1;
|
||||||
if (*info->dev->pvid) {
|
if (*info->dev->pvid) {
|
||||||
hash_remove(_pvid_hash, info->dev->pvid);
|
dm_hash_remove(_pvid_hash, info->dev->pvid);
|
||||||
}
|
}
|
||||||
strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
|
strncpy(info->dev->pvid, pvid, sizeof(info->dev->pvid));
|
||||||
if (!hash_insert(_pvid_hash, pvid, info)) {
|
if (!dm_hash_insert(_pvid_hash, pvid, info)) {
|
||||||
log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
|
log_error("_lvmcache_update: pvid insertion failed: %s", pvid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -338,13 +355,13 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (info->vginfo && *info->vginfo->vgid)
|
if (info->vginfo && *info->vginfo->vgid)
|
||||||
hash_remove(_vgid_hash, info->vginfo->vgid);
|
dm_hash_remove(_vgid_hash, info->vginfo->vgid);
|
||||||
if (!vgid)
|
if (!vgid)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
|
strncpy(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid));
|
||||||
info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
|
info->vginfo->vgid[sizeof(info->vginfo->vgid) - 1] = '\0';
|
||||||
if (!hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
|
if (!dm_hash_insert(_vgid_hash, info->vginfo->vgid, info->vginfo)) {
|
||||||
log_error("_lvmcache_update: vgid hash insertion failed: %s",
|
log_error("_lvmcache_update: vgid hash insertion failed: %s",
|
||||||
info->vginfo->vgid);
|
info->vginfo->vgid);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -372,22 +389,22 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
|||||||
|
|
||||||
/* Get existing vginfo or create new one */
|
/* Get existing vginfo or create new one */
|
||||||
if (!(vginfo = vginfo_from_vgname(vgname))) {
|
if (!(vginfo = vginfo_from_vgname(vgname))) {
|
||||||
if (!(vginfo = dbg_malloc(sizeof(*vginfo)))) {
|
if (!(vginfo = dm_malloc(sizeof(*vginfo)))) {
|
||||||
log_error("lvmcache_update_vgname: list alloc failed");
|
log_error("lvmcache_update_vgname: list alloc failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset(vginfo, 0, sizeof(*vginfo));
|
memset(vginfo, 0, sizeof(*vginfo));
|
||||||
if (!(vginfo->vgname = dbg_strdup(vgname))) {
|
if (!(vginfo->vgname = dm_strdup(vgname))) {
|
||||||
dbg_free(vginfo);
|
dm_free(vginfo);
|
||||||
log_error("cache vgname alloc failed for %s", vgname);
|
log_error("cache vgname alloc failed for %s", vgname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
list_init(&vginfo->infos);
|
list_init(&vginfo->infos);
|
||||||
if (!hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
|
if (!dm_hash_insert(_vgname_hash, vginfo->vgname, vginfo)) {
|
||||||
log_error("cache_update: vg hash insertion failed: %s",
|
log_error("cache_update: vg hash insertion failed: %s",
|
||||||
vginfo->vgname);
|
vginfo->vgname);
|
||||||
dbg_free(vginfo->vgname);
|
dm_free(vginfo->vgname);
|
||||||
dbg_free(vginfo);
|
dm_free(vginfo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Ensure orphans appear last on list_iterate */
|
/* Ensure orphans appear last on list_iterate */
|
||||||
@@ -403,23 +420,24 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname)
|
|||||||
/* FIXME Check consistency of list! */
|
/* FIXME Check consistency of list! */
|
||||||
vginfo->fmt = info->fmt;
|
vginfo->fmt = info->fmt;
|
||||||
|
|
||||||
|
log_debug("lvmcache: %s now %s%s", dev_name(info->dev),
|
||||||
|
*vgname ? "in VG " : "orphaned", vgname);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lvmcache_update_vg(struct volume_group *vg)
|
int lvmcache_update_vg(struct volume_group *vg)
|
||||||
{
|
{
|
||||||
struct list *pvh;
|
struct pv_list *pvl;
|
||||||
struct physical_volume *pv;
|
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
char pvid_s[ID_LEN + 1];
|
char pvid_s[ID_LEN + 1];
|
||||||
int vgid_updated = 0;
|
int vgid_updated = 0;
|
||||||
|
|
||||||
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
pvid_s[sizeof(pvid_s) - 1] = '\0';
|
||||||
|
|
||||||
list_iterate(pvh, &vg->pvs) {
|
list_iterate_items(pvl, &vg->pvs) {
|
||||||
pv = list_item(pvh, struct pv_list)->pv;
|
strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s) - 1);
|
||||||
strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
|
/* FIXME Could pvl->pv->dev->pvid ever be different? */
|
||||||
/* FIXME Could pv->dev->pvid ever be different? */
|
|
||||||
if ((info = info_from_pvid(pvid_s))) {
|
if ((info = info_from_pvid(pvid_s))) {
|
||||||
lvmcache_update_vgname(info, vg->name);
|
lvmcache_update_vgname(info, vg->name);
|
||||||
if (!vgid_updated) {
|
if (!vgid_updated) {
|
||||||
@@ -454,7 +472,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
|||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!(info = dbg_malloc(sizeof(*info)))) {
|
if (!(info = dm_malloc(sizeof(*info)))) {
|
||||||
log_error("lvmcache_info allocation failed");
|
log_error("lvmcache_info allocation failed");
|
||||||
label_destroy(label);
|
label_destroy(label);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -475,17 +493,36 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
|||||||
pvid, dev_name(dev),
|
pvid, dev_name(dev),
|
||||||
dev_name(existing->dev));
|
dev_name(existing->dev));
|
||||||
return NULL;
|
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() &&
|
} else if (MAJOR(existing->dev->dev) != md_major() &&
|
||||||
MAJOR(dev->dev) == md_major())
|
MAJOR(dev->dev) == md_major())
|
||||||
log_very_verbose("Duplicate PV %s on %s - "
|
log_very_verbose("Duplicate PV %s on %s - "
|
||||||
"using md %s", pvid,
|
"using md %s", pvid,
|
||||||
dev_name(existing->dev),
|
dev_name(existing->dev),
|
||||||
dev_name(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
|
else
|
||||||
log_error("Found duplicate PV %s: using %s not "
|
log_error("Found duplicate PV %s: using %s not "
|
||||||
"%s", pvid, dev_name(dev),
|
"%s", pvid, dev_name(dev),
|
||||||
dev_name(existing->dev));
|
dev_name(existing->dev));
|
||||||
}
|
}
|
||||||
|
/* Switch over to new preferred device */
|
||||||
|
existing->dev = dev;
|
||||||
info = existing;
|
info = existing;
|
||||||
/* Has labeller changed? */
|
/* Has labeller changed? */
|
||||||
if (info->label->labeller != labeller) {
|
if (info->label->labeller != labeller) {
|
||||||
@@ -505,7 +542,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
|||||||
|
|
||||||
if (!_lvmcache_update_pvid(info, pvid_s)) {
|
if (!_lvmcache_update_pvid(info, pvid_s)) {
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
dbg_free(info);
|
dm_free(info);
|
||||||
label_destroy(label);
|
label_destroy(label);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -513,9 +550,9 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
|
|||||||
|
|
||||||
if (!lvmcache_update_vgname(info, vgname)) {
|
if (!lvmcache_update_vgname(info, vgname)) {
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
hash_remove(_pvid_hash, pvid_s);
|
dm_hash_remove(_pvid_hash, pvid_s);
|
||||||
strcpy(info->dev->pvid, "");
|
strcpy(info->dev->pvid, "");
|
||||||
dbg_free(info);
|
dm_free(info);
|
||||||
label_destroy(label);
|
label_destroy(label);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -534,14 +571,14 @@ static void _lvmcache_destroy_entry(struct lvmcache_info *info)
|
|||||||
list_del(&info->list);
|
list_del(&info->list);
|
||||||
strcpy(info->dev->pvid, "");
|
strcpy(info->dev->pvid, "");
|
||||||
label_destroy(info->label);
|
label_destroy(info->label);
|
||||||
dbg_free(info);
|
dm_free(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
|
static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
|
||||||
{
|
{
|
||||||
if (vginfo->vgname)
|
if (vginfo->vgname)
|
||||||
dbg_free(vginfo->vgname);
|
dm_free(vginfo->vgname);
|
||||||
dbg_free(vginfo);
|
dm_free(vginfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _lvmcache_destroy_lockname(int present)
|
static void _lvmcache_destroy_lockname(int present)
|
||||||
@@ -551,29 +588,31 @@ static void _lvmcache_destroy_lockname(int present)
|
|||||||
|
|
||||||
void lvmcache_destroy(void)
|
void lvmcache_destroy(void)
|
||||||
{
|
{
|
||||||
|
log_verbose("Wiping internal VG cache");
|
||||||
|
|
||||||
_has_scanned = 0;
|
_has_scanned = 0;
|
||||||
|
|
||||||
if (_vgid_hash) {
|
if (_vgid_hash) {
|
||||||
hash_destroy(_vgid_hash);
|
dm_hash_destroy(_vgid_hash);
|
||||||
_vgid_hash = NULL;
|
_vgid_hash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pvid_hash) {
|
if (_pvid_hash) {
|
||||||
hash_iter(_pvid_hash, (iterate_fn) _lvmcache_destroy_entry);
|
dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_entry);
|
||||||
hash_destroy(_pvid_hash);
|
dm_hash_destroy(_pvid_hash);
|
||||||
_pvid_hash = NULL;
|
_pvid_hash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_vgname_hash) {
|
if (_vgname_hash) {
|
||||||
hash_iter(_vgname_hash,
|
dm_hash_iter(_vgname_hash,
|
||||||
(iterate_fn) _lvmcache_destroy_vgnamelist);
|
(dm_hash_iterate_fn) _lvmcache_destroy_vgnamelist);
|
||||||
hash_destroy(_vgname_hash);
|
dm_hash_destroy(_vgname_hash);
|
||||||
_vgname_hash = NULL;
|
_vgname_hash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_lock_hash) {
|
if (_lock_hash) {
|
||||||
hash_iter(_lock_hash, (iterate_fn) _lvmcache_destroy_lockname);
|
dm_hash_iter(_lock_hash, (dm_hash_iterate_fn) _lvmcache_destroy_lockname);
|
||||||
hash_destroy(_lock_hash);
|
dm_hash_destroy(_lock_hash);
|
||||||
_lock_hash = NULL;
|
_lock_hash = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
lib/cache/lvmcache.h
vendored
7
lib/cache/lvmcache.h
vendored
@@ -36,9 +36,10 @@ struct volume_group;
|
|||||||
struct lvmcache_vginfo {
|
struct lvmcache_vginfo {
|
||||||
struct list list; /* Join these vginfos together */
|
struct list list; /* Join these vginfos together */
|
||||||
struct list infos; /* List head for lvmcache_infos */
|
struct list infos; /* List head for lvmcache_infos */
|
||||||
|
const struct format_type *fmt;
|
||||||
char *vgname; /* "" == orphan */
|
char *vgname; /* "" == orphan */
|
||||||
char vgid[ID_LEN + 1];
|
char vgid[ID_LEN + 1];
|
||||||
const struct format_type *fmt;
|
char _padding[7];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lvmcache_info {
|
struct lvmcache_info {
|
||||||
@@ -56,7 +57,8 @@ struct lvmcache_info {
|
|||||||
int lvmcache_init(void);
|
int lvmcache_init(void);
|
||||||
void lvmcache_destroy(void);
|
void lvmcache_destroy(void);
|
||||||
|
|
||||||
/* Set full_scan to 1 to reread every filtered device label */
|
/* 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);
|
int lvmcache_label_scan(struct cmd_context *cmd, int full_scan);
|
||||||
|
|
||||||
/* Add/delete a device */
|
/* Add/delete a device */
|
||||||
@@ -79,6 +81,7 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid);
|
|||||||
struct lvmcache_info *info_from_pvid(const char *pvid);
|
struct lvmcache_info *info_from_pvid(const char *pvid);
|
||||||
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
|
struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid);
|
||||||
int vgs_locked(void);
|
int vgs_locked(void);
|
||||||
|
int vgname_is_locked(const char *vgname);
|
||||||
|
|
||||||
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
|
/* Returns list of struct str_lists containing pool-allocated copy of vgnames */
|
||||||
/* Set full_scan to 1 to reread every filtered device label */
|
/* Set full_scan to 1 to reread every filtered device label */
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
@@ -33,8 +32,10 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "memlock.h"
|
#include "memlock.h"
|
||||||
#include "str_list.h"
|
#include "str_list.h"
|
||||||
#include "segtypes.h"
|
#include "segtype.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
|
#include "dev-cache.h"
|
||||||
|
#include "archiver.h"
|
||||||
|
|
||||||
#ifdef HAVE_LIBDL
|
#ifdef HAVE_LIBDL
|
||||||
#include "sharedlib.h"
|
#include "sharedlib.h"
|
||||||
@@ -181,6 +182,12 @@ static int _process_config(struct cmd_context *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
|
||||||
|
log_error("Warning: proc dir %s not found - some checks will be bypassed",
|
||||||
|
cmd->proc_dir);
|
||||||
|
cmd->proc_dir[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
/* activation? */
|
/* activation? */
|
||||||
cmd->default_settings.activation = find_config_int(cmd->cft->root,
|
cmd->default_settings.activation = find_config_int(cmd->cft->root,
|
||||||
"global/activation",
|
"global/activation",
|
||||||
@@ -205,7 +212,7 @@ static int _process_config(struct cmd_context *cmd)
|
|||||||
|
|
||||||
static int _set_tag(struct cmd_context *cmd, const char *tag)
|
static int _set_tag(struct cmd_context *cmd, const char *tag)
|
||||||
{
|
{
|
||||||
log_very_verbose("Setting host tag: %s", pool_strdup(cmd->libmem, tag));
|
log_very_verbose("Setting host tag: %s", dm_pool_strdup(cmd->libmem, tag));
|
||||||
|
|
||||||
if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
|
if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
|
||||||
log_error("_set_tag: str_list_add %s failed", tag);
|
log_error("_set_tag: str_list_add %s failed", tag);
|
||||||
@@ -315,7 +322,7 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(cfl = pool_alloc(cmd->libmem, sizeof(*cfl)))) {
|
if (!(cfl = dm_pool_alloc(cmd->libmem, sizeof(*cfl)))) {
|
||||||
log_error("config_tree_list allocation failed");
|
log_error("config_tree_list allocation failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -487,6 +494,24 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(cn = find_config_node(cmd->cft->root, "devices/loopfiles")))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (cv = cn->v; cv; cv = cv->next) {
|
||||||
|
if (cv->type != CFG_STRING) {
|
||||||
|
log_error("Invalid string in config file: "
|
||||||
|
"devices/loopfiles");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev_cache_add_loopfile(cv->v.str)) {
|
||||||
|
log_error("Failed to add loopfile %s to internal "
|
||||||
|
"device cache", cv->v.str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,8 +544,8 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
|||||||
|
|
||||||
/* regex filter. Optional. */
|
/* regex filter. Optional. */
|
||||||
if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
|
if (!(cn = find_config_node(cmd->cft->root, "devices/filter")))
|
||||||
log_debug("devices/filter not found in config file: no regex "
|
log_very_verbose("devices/filter not found in config file: "
|
||||||
"filter installed");
|
"no regex filter installed");
|
||||||
|
|
||||||
else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) {
|
else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) {
|
||||||
log_error("Failed to create regex device filter");
|
log_error("Failed to create regex device filter");
|
||||||
@@ -537,6 +562,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
|
|||||||
/* md component filter. Optional, non-critical. */
|
/* md component filter. Optional, non-critical. */
|
||||||
if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
|
if (find_config_bool(cmd->cft->root, "devices/md_component_detection",
|
||||||
DEFAULT_MD_COMPONENT_DETECTION)) {
|
DEFAULT_MD_COMPONENT_DETECTION)) {
|
||||||
|
init_md_filtering(1);
|
||||||
if ((filters[nr_filt] = md_filter_create()))
|
if ((filters[nr_filt] = md_filter_create()))
|
||||||
nr_filt++;
|
nr_filt++;
|
||||||
}
|
}
|
||||||
@@ -595,7 +621,6 @@ static int _init_formats(struct cmd_context *cmd)
|
|||||||
const char *format;
|
const char *format;
|
||||||
|
|
||||||
struct format_type *fmt;
|
struct format_type *fmt;
|
||||||
struct list *fmth;
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBDL
|
#ifdef HAVE_LIBDL
|
||||||
const struct config_node *cn;
|
const struct config_node *cn;
|
||||||
@@ -662,8 +687,7 @@ static int _init_formats(struct cmd_context *cmd)
|
|||||||
format = find_config_str(cmd->cft->root, "global/format",
|
format = find_config_str(cmd->cft->root, "global/format",
|
||||||
DEFAULT_FORMAT);
|
DEFAULT_FORMAT);
|
||||||
|
|
||||||
list_iterate(fmth, &cmd->formats) {
|
list_iterate_items(fmt, &cmd->formats) {
|
||||||
fmt = list_item(fmth, struct format_type);
|
|
||||||
if (!strcasecmp(fmt->name, format) ||
|
if (!strcasecmp(fmt->name, format) ||
|
||||||
(fmt->alias && !strcasecmp(fmt->alias, format))) {
|
(fmt->alias && !strcasecmp(fmt->alias, format))) {
|
||||||
cmd->default_settings.fmt = fmt;
|
cmd->default_settings.fmt = fmt;
|
||||||
@@ -775,13 +799,76 @@ static int _init_hostname(struct cmd_context *cmd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(cmd->hostname = pool_strdup(cmd->libmem, uts.nodename))) {
|
if (!(cmd->hostname = dm_pool_strdup(cmd->libmem, uts.nodename))) {
|
||||||
log_error("_init_hostname: pool_strdup failed");
|
log_error("_init_hostname: dm_pool_strdup failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(cmd->kernel_vsn = pool_strdup(cmd->libmem, uts.release))) {
|
if (!(cmd->kernel_vsn = dm_pool_strdup(cmd->libmem, uts.release))) {
|
||||||
log_error("_init_hostname: pool_strdup kernel_vsn failed");
|
log_error("_init_hostname: dm_pool_strdup kernel_vsn failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _init_backup(struct cmd_context *cmd)
|
||||||
|
{
|
||||||
|
uint32_t days, min;
|
||||||
|
char default_dir[PATH_MAX];
|
||||||
|
const char *dir;
|
||||||
|
|
||||||
|
if (!cmd->sys_dir) {
|
||||||
|
log_warn("WARNING: Metadata changes will NOT be backed up");
|
||||||
|
backup_init(cmd, "");
|
||||||
|
archive_init(cmd, "", 0, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set up archiving */
|
||||||
|
cmd->default_settings.archive =
|
||||||
|
find_config_bool(cmd->cft->root, "backup/archive",
|
||||||
|
DEFAULT_ARCHIVE_ENABLED);
|
||||||
|
|
||||||
|
days = (uint32_t) find_config_int(cmd->cft->root, "backup/retain_days",
|
||||||
|
DEFAULT_ARCHIVE_DAYS);
|
||||||
|
|
||||||
|
min = (uint32_t) find_config_int(cmd->cft->root, "backup/retain_min",
|
||||||
|
DEFAULT_ARCHIVE_NUMBER);
|
||||||
|
|
||||||
|
if (lvm_snprintf
|
||||||
|
(default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
|
||||||
|
DEFAULT_ARCHIVE_SUBDIR) == -1) {
|
||||||
|
log_err("Couldn't create default archive path '%s/%s'.",
|
||||||
|
cmd->sys_dir, DEFAULT_ARCHIVE_SUBDIR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = find_config_str(cmd->cft->root, "backup/archive_dir",
|
||||||
|
default_dir);
|
||||||
|
|
||||||
|
if (!archive_init(cmd, dir, days, min)) {
|
||||||
|
log_debug("backup_init failed.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set up the backup */
|
||||||
|
cmd->default_settings.backup =
|
||||||
|
find_config_bool(cmd->cft->root, "backup/backup",
|
||||||
|
DEFAULT_BACKUP_ENABLED);
|
||||||
|
|
||||||
|
if (lvm_snprintf
|
||||||
|
(default_dir, sizeof(default_dir), "%s/%s", cmd->sys_dir,
|
||||||
|
DEFAULT_BACKUP_SUBDIR) == -1) {
|
||||||
|
log_err("Couldn't create default backup path '%s/%s'.",
|
||||||
|
cmd->sys_dir, DEFAULT_BACKUP_SUBDIR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = find_config_str(cmd->cft->root, "backup/backup_dir", default_dir);
|
||||||
|
|
||||||
|
if (!backup_init(cmd, dir)) {
|
||||||
|
log_debug("backup_init failed.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,7 +885,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!setlocale(LC_ALL, ""))
|
if (!setlocale(LC_ALL, ""))
|
||||||
log_error("setlocale failed");
|
log_very_verbose("setlocale failed");
|
||||||
|
|
||||||
#ifdef INTL_PACKAGE
|
#ifdef INTL_PACKAGE
|
||||||
bindtextdomain(INTL_PACKAGE, LOCALEDIR);
|
bindtextdomain(INTL_PACKAGE, LOCALEDIR);
|
||||||
@@ -806,7 +893,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
|||||||
|
|
||||||
init_syslog(DEFAULT_LOG_FACILITY);
|
init_syslog(DEFAULT_LOG_FACILITY);
|
||||||
|
|
||||||
if (!(cmd = dbg_malloc(sizeof(*cmd)))) {
|
if (!(cmd = dm_malloc(sizeof(*cmd)))) {
|
||||||
log_error("Failed to allocate command context");
|
log_error("Failed to allocate command context");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -824,10 +911,15 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Create system directory if it doesn't already exist */
|
/* Create system directory if it doesn't already exist */
|
||||||
if (*cmd->sys_dir && !create_dir(cmd->sys_dir))
|
if (*cmd->sys_dir && !create_dir(cmd->sys_dir)) {
|
||||||
|
log_error("Failed to create LVM2 system dir for metadata backups, config "
|
||||||
|
"files and internal cache.");
|
||||||
|
log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
|
||||||
|
"or empty string.");
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(cmd->libmem = pool_create(4 * 1024))) {
|
if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) {
|
||||||
log_error("Library memory pool creation failed");
|
log_error("Library memory pool creation failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -858,7 +950,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
|||||||
if (!_init_filters(cmd))
|
if (!_init_filters(cmd))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!(cmd->mem = pool_create(4 * 1024))) {
|
if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
|
||||||
log_error("Command memory pool creation failed");
|
log_error("Command memory pool creation failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -871,13 +963,16 @@ struct cmd_context *create_toolcontext(struct arg *the_args)
|
|||||||
if (!_init_segtypes(cmd))
|
if (!_init_segtypes(cmd))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (!_init_backup(cmd))
|
||||||
|
goto error;
|
||||||
|
|
||||||
cmd->current_settings = cmd->default_settings;
|
cmd->current_settings = cmd->default_settings;
|
||||||
|
|
||||||
cmd->config_valid = 1;
|
cmd->config_valid = 1;
|
||||||
return cmd;
|
return cmd;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
dbg_free(cmd);
|
dm_free(cmd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -981,21 +1076,22 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
|||||||
if (cmd->dump_filter)
|
if (cmd->dump_filter)
|
||||||
persistent_filter_dump(cmd->filter);
|
persistent_filter_dump(cmd->filter);
|
||||||
|
|
||||||
activation_exit();
|
archive_exit(cmd);
|
||||||
|
backup_exit(cmd);
|
||||||
lvmcache_destroy();
|
lvmcache_destroy();
|
||||||
label_exit();
|
label_exit();
|
||||||
_destroy_segtypes(&cmd->segtypes);
|
_destroy_segtypes(&cmd->segtypes);
|
||||||
_destroy_formats(&cmd->formats);
|
_destroy_formats(&cmd->formats);
|
||||||
cmd->filter->destroy(cmd->filter);
|
cmd->filter->destroy(cmd->filter);
|
||||||
pool_destroy(cmd->mem);
|
dm_pool_destroy(cmd->mem);
|
||||||
dev_cache_exit();
|
dev_cache_exit();
|
||||||
_destroy_tags(cmd);
|
_destroy_tags(cmd);
|
||||||
_destroy_tag_configs(cmd);
|
_destroy_tag_configs(cmd);
|
||||||
pool_destroy(cmd->libmem);
|
dm_pool_destroy(cmd->libmem);
|
||||||
dbg_free(cmd);
|
dm_free(cmd);
|
||||||
|
|
||||||
release_log_memory();
|
release_log_memory();
|
||||||
dump_memory();
|
activation_exit();
|
||||||
fin_log();
|
fin_log();
|
||||||
fin_syslog();
|
fin_syslog();
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#define _LVM_TOOLCONTEXT_H
|
#define _LVM_TOOLCONTEXT_H
|
||||||
|
|
||||||
#include "dev-cache.h"
|
#include "dev-cache.h"
|
||||||
#include "pool.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@@ -32,26 +31,26 @@ struct config_info {
|
|||||||
int syslog;
|
int syslog;
|
||||||
int activation;
|
int activation;
|
||||||
int suffix;
|
int suffix;
|
||||||
uint64_t unit_factor;
|
|
||||||
char unit_type;
|
|
||||||
const char *msg_prefix;
|
|
||||||
int cmd_name; /* Show command name? */
|
|
||||||
|
|
||||||
int archive; /* should we archive ? */
|
int archive; /* should we archive ? */
|
||||||
int backup; /* should we backup ? */
|
int backup; /* should we backup ? */
|
||||||
|
const char *msg_prefix;
|
||||||
struct format_type *fmt;
|
struct format_type *fmt;
|
||||||
|
uint64_t unit_factor;
|
||||||
|
int cmd_name; /* Show command name? */
|
||||||
mode_t umask;
|
mode_t umask;
|
||||||
|
char unit_type;
|
||||||
|
char _padding[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct config_tree;
|
struct config_tree;
|
||||||
|
struct archive_params;
|
||||||
|
struct backup_params;
|
||||||
|
|
||||||
/* FIXME Split into tool & library contexts */
|
/* FIXME Split into tool & library contexts */
|
||||||
/* command-instance-related variables needed by library */
|
/* command-instance-related variables needed by library */
|
||||||
struct cmd_context {
|
struct cmd_context {
|
||||||
struct pool *libmem; /* For permanent config data */
|
struct dm_pool *libmem; /* For permanent config data */
|
||||||
struct pool *mem; /* Transient: Cleared between each command */
|
struct dm_pool *mem; /* Transient: Cleared between each command */
|
||||||
|
|
||||||
const struct format_type *fmt; /* Current format to use by default */
|
const struct format_type *fmt; /* Current format to use by default */
|
||||||
struct format_type *fmt_backup; /* Format to use for backups */
|
struct format_type *fmt_backup; /* Format to use for backups */
|
||||||
@@ -75,6 +74,9 @@ struct cmd_context {
|
|||||||
struct config_info default_settings;
|
struct config_info default_settings;
|
||||||
struct config_info current_settings;
|
struct config_info current_settings;
|
||||||
|
|
||||||
|
struct archive_params *archive_params;
|
||||||
|
struct backup_params *backup_params;
|
||||||
|
|
||||||
/* List of defined tags */
|
/* List of defined tags */
|
||||||
struct list tags;
|
struct list tags;
|
||||||
int hosttags;
|
int hosttags;
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "crc.h"
|
#include "crc.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "str_list.h"
|
#include "str_list.h"
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
@@ -50,12 +49,12 @@ struct parser {
|
|||||||
int fd; /* descriptor for file being parsed */
|
int fd; /* descriptor for file being parsed */
|
||||||
int line; /* line number we are on */
|
int line; /* line number we are on */
|
||||||
|
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cs {
|
struct cs {
|
||||||
struct config_tree cft;
|
struct config_tree cft;
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
time_t timestamp;
|
time_t timestamp;
|
||||||
char *filename;
|
char *filename;
|
||||||
int exists;
|
int exists;
|
||||||
@@ -99,16 +98,16 @@ static int _tok_match(const char *str, const char *b, const char *e)
|
|||||||
struct config_tree *create_config_tree(const char *filename)
|
struct config_tree *create_config_tree(const char *filename)
|
||||||
{
|
{
|
||||||
struct cs *c;
|
struct cs *c;
|
||||||
struct pool *mem = pool_create(10 * 1024);
|
struct dm_pool *mem = dm_pool_create("config", 10 * 1024);
|
||||||
|
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(c = pool_zalloc(mem, sizeof(*c)))) {
|
if (!(c = dm_pool_zalloc(mem, sizeof(*c)))) {
|
||||||
stack;
|
stack;
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,13 +116,13 @@ struct config_tree *create_config_tree(const char *filename)
|
|||||||
c->timestamp = 0;
|
c->timestamp = 0;
|
||||||
c->exists = 0;
|
c->exists = 0;
|
||||||
if (filename)
|
if (filename)
|
||||||
c->filename = pool_strdup(c->mem, filename);
|
c->filename = dm_pool_strdup(c->mem, filename);
|
||||||
return &c->cft;
|
return &c->cft;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_config_tree(struct config_tree *cft)
|
void destroy_config_tree(struct config_tree *cft)
|
||||||
{
|
{
|
||||||
pool_destroy(((struct cs *) cft)->mem);
|
dm_pool_destroy(((struct cs *) cft)->mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_config_fd(struct config_tree *cft, struct device *dev,
|
int read_config_fd(struct config_tree *cft, struct device *dev,
|
||||||
@@ -136,7 +135,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
|||||||
int use_mmap = 1;
|
int use_mmap = 1;
|
||||||
off_t mmap_offset = 0;
|
off_t mmap_offset = 0;
|
||||||
|
|
||||||
if (!(p = pool_alloc(c->mem, sizeof(*p)))) {
|
if (!(p = dm_pool_alloc(c->mem, sizeof(*p)))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -157,7 +156,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
|||||||
}
|
}
|
||||||
p->fb = p->fb + mmap_offset;
|
p->fb = p->fb + mmap_offset;
|
||||||
} else {
|
} else {
|
||||||
if (!(p->fb = dbg_malloc(size + size2))) {
|
if (!(p->fb = dm_malloc(size + size2))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -197,7 +196,7 @@ int read_config_fd(struct config_tree *cft, struct device *dev,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
if (!use_mmap)
|
if (!use_mmap)
|
||||||
dbg_free(p->fb);
|
dm_free(p->fb);
|
||||||
else {
|
else {
|
||||||
/* unmap the file */
|
/* unmap the file */
|
||||||
if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
|
if (munmap((char *) (p->fb - mmap_offset), size + mmap_offset)) {
|
||||||
@@ -235,7 +234,7 @@ int read_config_file(struct config_tree *cft)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dev = dev_create_file(c->filename, NULL, NULL))) {
|
if (!(dev = dev_create_file(c->filename, NULL, NULL, 1))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -688,14 +687,14 @@ static void _eat_space(struct parser *p)
|
|||||||
*/
|
*/
|
||||||
static struct config_value *_create_value(struct parser *p)
|
static struct config_value *_create_value(struct parser *p)
|
||||||
{
|
{
|
||||||
struct config_value *v = pool_alloc(p->mem, sizeof(*v));
|
struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
|
||||||
memset(v, 0, sizeof(*v));
|
memset(v, 0, sizeof(*v));
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct config_node *_create_node(struct parser *p)
|
static struct config_node *_create_node(struct parser *p)
|
||||||
{
|
{
|
||||||
struct config_node *n = pool_alloc(p->mem, sizeof(*n));
|
struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
|
||||||
memset(n, 0, sizeof(*n));
|
memset(n, 0, sizeof(*n));
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@@ -703,7 +702,7 @@ static struct config_node *_create_node(struct parser *p)
|
|||||||
static char *_dup_tok(struct parser *p)
|
static char *_dup_tok(struct parser *p)
|
||||||
{
|
{
|
||||||
size_t len = p->te - p->tb;
|
size_t len = p->te - p->tb;
|
||||||
char *str = pool_alloc(p->mem, len + 1);
|
char *str = dm_pool_alloc(p->mem, len + 1);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#ifndef _LVM_CONFIG_H
|
#ifndef _LVM_CONFIG_H
|
||||||
#define _LVM_CONFIG_H
|
#define _LVM_CONFIG_H
|
||||||
|
|
||||||
|
#include "lvm-types.h"
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
struct cmd_context;
|
struct cmd_context;
|
||||||
|
|
||||||
|
|||||||
@@ -91,19 +91,22 @@
|
|||||||
#define DEFAULT_REP_HEADINGS 1
|
#define DEFAULT_REP_HEADINGS 1
|
||||||
#define DEFAULT_REP_SEPARATOR " "
|
#define DEFAULT_REP_SEPARATOR " "
|
||||||
|
|
||||||
#define DEFAULT_LVS_COLS "lv_name,vg_name,lv_attr,lv_size,origin,snap_percent,move_pv,copy_percent"
|
#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_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_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_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,origin,snap_percent,move_pv,copy_percent,lv_uuid"
|
#define DEFAULT_LVS_COLS_VERB "lv_name,vg_name,seg_count,lv_attr,lv_size,lv_major,lv_minor,lv_kernel_major,lv_kernel_minor,origin,snap_percent,move_pv,copy_percent,mirror_log,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_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,pv_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_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_LVS_SORT "vg_name,lv_name"
|
||||||
#define DEFAULT_VGS_SORT "vg_name"
|
#define DEFAULT_VGS_SORT "vg_name"
|
||||||
#define DEFAULT_PVS_SORT "pv_name"
|
#define DEFAULT_PVS_SORT "pv_name"
|
||||||
#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
|
#define DEFAULT_SEGS_SORT "vg_name,lv_name,seg_start"
|
||||||
|
#define DEFAULT_PVSEGS_SORT "pv_name,pvseg_start"
|
||||||
|
|
||||||
#endif /* _LVM_DEFAULTS_H */
|
#endif /* _LVM_DEFAULTS_H */
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ struct node {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct btree {
|
struct btree {
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
struct node *root;
|
struct node *root;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct btree *btree_create(struct pool *mem)
|
struct btree *btree_create(struct dm_pool *mem)
|
||||||
{
|
{
|
||||||
struct btree *t = pool_alloc(mem, sizeof(*t));
|
struct btree *t = dm_pool_alloc(mem, sizeof(*t));
|
||||||
|
|
||||||
if (t) {
|
if (t) {
|
||||||
t->mem = mem;
|
t->mem = mem;
|
||||||
@@ -86,7 +86,7 @@ int btree_insert(struct btree *t, uint32_t k, void *data)
|
|||||||
struct node *p, **c = _lookup(&t->root, key, &p), *n;
|
struct node *p, **c = _lookup(&t->root, key, &p), *n;
|
||||||
|
|
||||||
if (!*c) {
|
if (!*c) {
|
||||||
if (!(n = pool_alloc(t->mem, sizeof(*n)))) {
|
if (!(n = dm_pool_alloc(t->mem, sizeof(*n)))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,9 @@
|
|||||||
#ifndef _LVM_BTREE_H
|
#ifndef _LVM_BTREE_H
|
||||||
#define _LVM_BTREE_H
|
#define _LVM_BTREE_H
|
||||||
|
|
||||||
#include "pool.h"
|
|
||||||
|
|
||||||
struct btree;
|
struct btree;
|
||||||
|
|
||||||
struct btree *btree_create(struct pool *mem);
|
struct btree *btree_create(struct dm_pool *mem);
|
||||||
|
|
||||||
void *btree_lookup(struct btree *t, uint32_t k);
|
void *btree_lookup(struct btree *t, uint32_t k);
|
||||||
int btree_insert(struct btree *t, uint32_t k, void *data);
|
int btree_insert(struct btree *t, uint32_t k, void *data);
|
||||||
|
|||||||
@@ -18,17 +18,30 @@
|
|||||||
|
|
||||||
#include <assert.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 {
|
||||||
struct list *n, *p;
|
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) }
|
#define LIST_INIT(name) struct list name = { &(name), &(name) }
|
||||||
|
|
||||||
static inline void list_init(struct list *head)
|
static inline void list_init(struct list *head)
|
||||||
{
|
{
|
||||||
head->n = head->p = 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.
|
||||||
|
*/
|
||||||
static inline void list_add(struct list *head, struct list *elem)
|
static inline void list_add(struct list *head, struct list *elem)
|
||||||
{
|
{
|
||||||
assert(head->n);
|
assert(head->n);
|
||||||
@@ -40,6 +53,10 @@ static inline void list_add(struct list *head, struct list *elem)
|
|||||||
head->p = 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.
|
||||||
|
*/
|
||||||
static inline void list_add_h(struct list *head, struct list *elem)
|
static inline void list_add_h(struct list *head, struct list *elem)
|
||||||
{
|
{
|
||||||
assert(head->n);
|
assert(head->n);
|
||||||
@@ -51,53 +68,182 @@ static inline void list_add_h(struct list *head, struct list *elem)
|
|||||||
head->n = 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.
|
||||||
|
*/
|
||||||
static inline void list_del(struct list *elem)
|
static inline void list_del(struct list *elem)
|
||||||
{
|
{
|
||||||
elem->n->p = elem->p;
|
elem->n->p = elem->p;
|
||||||
elem->p->n = elem->n;
|
elem->p->n = elem->n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is the list empty?
|
||||||
|
*/
|
||||||
static inline int list_empty(struct list *head)
|
static inline int list_empty(struct list *head)
|
||||||
{
|
{
|
||||||
return head->n == head;
|
return head->n == head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the first element of the list?
|
||||||
|
*/
|
||||||
|
static inline int list_start(struct list *head, struct list *elem)
|
||||||
|
{
|
||||||
|
return elem->p == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this the last element of the list?
|
||||||
|
*/
|
||||||
static inline int list_end(struct list *head, struct list *elem)
|
static inline int list_end(struct list *head, struct list *elem)
|
||||||
{
|
{
|
||||||
return elem->n == head;
|
return elem->n == head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return first element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
static inline struct list *list_first(struct list *head)
|
||||||
|
{
|
||||||
|
return (list_empty(head) ? NULL : head->n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return last element of the list or NULL if empty
|
||||||
|
*/
|
||||||
|
static inline 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.
|
||||||
|
*/
|
||||||
|
static inline 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.
|
||||||
|
*/
|
||||||
static inline struct list *list_next(struct list *head, struct list *elem)
|
static inline struct list *list_next(struct list *head, struct list *elem)
|
||||||
{
|
{
|
||||||
return (list_end(head, elem) ? NULL : elem->n);
|
return (list_end(head, elem) ? NULL : elem->n);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define list_item(v, t) \
|
/*
|
||||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
|
* 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))
|
||||||
|
|
||||||
#define list_struct_base(v, t, h) \
|
/*
|
||||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->h))
|
* 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 a known element in a known structure, locate another */
|
/*
|
||||||
|
* Given the address v of one known element e in a known structure of type t,
|
||||||
|
* return another element f.
|
||||||
|
*/
|
||||||
#define struct_field(v, t, e, f) \
|
#define struct_field(v, t, e, f) \
|
||||||
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
|
(((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->e))->f)
|
||||||
|
|
||||||
/* Given a known element in a known structure, locate the list head */
|
/*
|
||||||
|
* Given the address v of a known element e in a known structure of type t,
|
||||||
|
* return the list head 'list'
|
||||||
|
*/
|
||||||
#define list_head(v, t, e) struct_field(v, t, e, list)
|
#define 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) \
|
#define list_iterate(v, head) \
|
||||||
for (v = (head)->n; v != head; v = v->n)
|
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) \
|
#define list_uniterate(v, head, start) \
|
||||||
for (v = (start)->p; v != head; v = v->p)
|
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) \
|
#define list_iterate_safe(v, t, head) \
|
||||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||||
|
|
||||||
#define list_iterate_items(v, head) \
|
/*
|
||||||
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
|
* Walk a list, setting 'v' in turn to the containing structure of each item.
|
||||||
v = list_item(v->list.n, typeof(*v)))
|
* 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.
|
||||||
|
*/
|
||||||
static inline unsigned int list_size(const struct list *head)
|
static inline unsigned int list_size(const struct list *head)
|
||||||
{
|
{
|
||||||
unsigned int s = 0;
|
unsigned int s = 0;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
/* Define some portable printing types */
|
/* Define some portable printing types */
|
||||||
#define PRIsize_t "Zu"
|
#define PRIsize_t "zu"
|
||||||
|
|
||||||
struct str_list {
|
struct str_list {
|
||||||
struct list list;
|
struct list list;
|
||||||
|
|||||||
@@ -16,11 +16,11 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "str_list.h"
|
#include "str_list.h"
|
||||||
|
|
||||||
struct list *str_list_create(struct pool *mem)
|
struct list *str_list_create(struct dm_pool *mem)
|
||||||
{
|
{
|
||||||
struct list *sl;
|
struct list *sl;
|
||||||
|
|
||||||
if (!(sl = pool_alloc(mem, sizeof(struct list)))) {
|
if (!(sl = dm_pool_alloc(mem, sizeof(struct list)))) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ struct list *str_list_create(struct pool *mem)
|
|||||||
return sl;
|
return sl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_list_add(struct pool *mem, struct list *sll, const char *str)
|
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str)
|
||||||
{
|
{
|
||||||
struct str_list *sln;
|
struct str_list *sln;
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ int str_list_add(struct pool *mem, struct list *sll, const char *str)
|
|||||||
if (str_list_match_item(sll, str))
|
if (str_list_match_item(sll, str))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!(sln = pool_alloc(mem, sizeof(*sln)))) {
|
if (!(sln = dm_pool_alloc(mem, sizeof(*sln)))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ int str_list_del(struct list *sll, const char *str)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold)
|
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold)
|
||||||
{
|
{
|
||||||
struct str_list *sl;
|
struct str_list *sl;
|
||||||
|
|
||||||
|
|||||||
@@ -16,14 +16,12 @@
|
|||||||
#ifndef _LVM_STR_LIST_H
|
#ifndef _LVM_STR_LIST_H
|
||||||
#define _LVM_STR_LIST_H
|
#define _LVM_STR_LIST_H
|
||||||
|
|
||||||
#include "pool.h"
|
struct list *str_list_create(struct dm_pool *mem);
|
||||||
|
int str_list_add(struct dm_pool *mem, struct list *sll, const char *str);
|
||||||
struct list *str_list_create(struct pool *mem);
|
|
||||||
int str_list_add(struct pool *mem, struct list *sll, const char *str);
|
|
||||||
int str_list_del(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_item(struct list *sll, const char *str);
|
||||||
int str_list_match_list(struct list *sll, struct list *sll2);
|
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_lists_equal(struct list *sll, struct list *sll2);
|
||||||
int str_list_dup(struct pool *mem, struct list *sllnew, struct list *sllold);
|
int str_list_dup(struct dm_pool *mem, struct list *sllnew, struct list *sllold);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,12 +15,10 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "dev-cache.h"
|
#include "dev-cache.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "hash.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "lvm-types.h"
|
#include "lvm-types.h"
|
||||||
#include "btree.h"
|
#include "btree.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "filter-persistent.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@@ -37,51 +35,73 @@ struct dir_list {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
struct hash_table *names;
|
struct dm_hash_table *names;
|
||||||
struct btree *devices;
|
struct btree *devices;
|
||||||
|
|
||||||
int has_scanned;
|
int has_scanned;
|
||||||
struct list dirs;
|
struct list dirs;
|
||||||
|
struct list files;
|
||||||
|
|
||||||
} _cache;
|
} _cache;
|
||||||
|
|
||||||
#define _alloc(x) pool_alloc(_cache.mem, (x))
|
#define _alloc(x) dm_pool_zalloc(_cache.mem, (x))
|
||||||
#define _free(x) pool_free(_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);
|
static int _insert(const char *path, int rec);
|
||||||
|
|
||||||
struct device *dev_create_file(const char *filename, struct device *dev,
|
struct device *dev_create_file(const char *filename, struct device *dev,
|
||||||
struct str_list *alias)
|
struct str_list *alias, int use_malloc)
|
||||||
{
|
{
|
||||||
int allocate = !dev;
|
int allocate = !dev;
|
||||||
|
|
||||||
if (allocate && !(dev = dbg_malloc(sizeof(*dev)))) {
|
if (allocate) {
|
||||||
log_error("struct device allocation failed");
|
if (use_malloc) {
|
||||||
return NULL;
|
if (!(dev = dm_malloc(sizeof(*dev)))) {
|
||||||
}
|
log_error("struct device allocation failed");
|
||||||
if (allocate && !(alias = dbg_malloc(sizeof(*alias)))) {
|
return NULL;
|
||||||
log_error("struct str_list allocation failed");
|
}
|
||||||
dbg_free(dev);
|
if (!(alias = dm_malloc(sizeof(*alias)))) {
|
||||||
return NULL;
|
log_error("struct str_list allocation failed");
|
||||||
}
|
dm_free(dev);
|
||||||
if (!(alias->str = dbg_strdup(filename))) {
|
return NULL;
|
||||||
log_error("filename strdup failed");
|
}
|
||||||
if (allocate) {
|
if (!(alias->str = dm_strdup(filename))) {
|
||||||
dbg_free(dev);
|
log_error("filename strdup failed");
|
||||||
dbg_free(alias);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
dev->flags = DEV_REGULAR;
|
|
||||||
if (allocate)
|
dev->flags |= DEV_REGULAR;
|
||||||
dev->flags |= DEV_ALLOCED;
|
|
||||||
list_init(&dev->aliases);
|
list_init(&dev->aliases);
|
||||||
list_add(&dev->aliases, &alias->list);
|
list_add(&dev->aliases, &alias->list);
|
||||||
dev->end = UINT64_C(0);
|
dev->end = UINT64_C(0);
|
||||||
dev->dev = 0;
|
dev->dev = 0;
|
||||||
dev->fd = -1;
|
dev->fd = -1;
|
||||||
dev->open_count = 0;
|
dev->open_count = 0;
|
||||||
|
dev->block_size = -1;
|
||||||
memset(dev->pvid, 0, sizeof(dev->pvid));
|
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||||
list_init(&dev->open_list);
|
list_init(&dev->open_list);
|
||||||
|
|
||||||
@@ -101,6 +121,7 @@ static struct device *_dev_create(dev_t d)
|
|||||||
dev->dev = d;
|
dev->dev = d;
|
||||||
dev->fd = -1;
|
dev->fd = -1;
|
||||||
dev->open_count = 0;
|
dev->open_count = 0;
|
||||||
|
dev->block_size = -1;
|
||||||
dev->end = UINT64_C(0);
|
dev->end = UINT64_C(0);
|
||||||
memset(dev->pvid, 0, sizeof(dev->pvid));
|
memset(dev->pvid, 0, sizeof(dev->pvid));
|
||||||
list_init(&dev->open_list);
|
list_init(&dev->open_list);
|
||||||
@@ -172,7 +193,7 @@ static int _compare_paths(const char *path0, const char *path1)
|
|||||||
static int _add_alias(struct device *dev, const char *path)
|
static int _add_alias(struct device *dev, const char *path)
|
||||||
{
|
{
|
||||||
struct str_list *sl = _alloc(sizeof(*sl));
|
struct str_list *sl = _alloc(sizeof(*sl));
|
||||||
struct list *ah;
|
struct str_list *strl;
|
||||||
const char *oldpath;
|
const char *oldpath;
|
||||||
int prefer_old = 1;
|
int prefer_old = 1;
|
||||||
|
|
||||||
@@ -182,14 +203,14 @@ static int _add_alias(struct device *dev, const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Is name already there? */
|
/* Is name already there? */
|
||||||
list_iterate(ah, &dev->aliases) {
|
list_iterate_items(strl, &dev->aliases) {
|
||||||
if (!strcmp(list_item(ah, struct str_list)->str, path)) {
|
if (!strcmp(strl->str, path)) {
|
||||||
stack;
|
log_debug("%s: Already in device cache", path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sl->str = pool_strdup(_cache.mem, path))) {
|
if (!(sl->str = dm_pool_strdup(_cache.mem, path))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -218,12 +239,27 @@ static int _add_alias(struct device *dev, const char *path)
|
|||||||
static int _insert_dev(const char *path, dev_t d)
|
static int _insert_dev(const char *path, dev_t d)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
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 ? */
|
/* is this device already registered ? */
|
||||||
if (!(dev = (struct device *) btree_lookup(_cache.devices,
|
if (!(dev = (struct device *) btree_lookup(_cache.devices,
|
||||||
(uint32_t) d))) {
|
(uint32_t) d))) {
|
||||||
/* create new device */
|
/* create new device */
|
||||||
if (!(dev = _dev_create(d))) {
|
if (loopfile) {
|
||||||
|
if (!(dev = dev_create_file(path, NULL, NULL, 0))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (!(dev = _dev_create(d))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -235,12 +271,12 @@ static int _insert_dev(const char *path, dev_t d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_add_alias(dev, path)) {
|
if (!loopfile && !_add_alias(dev, path)) {
|
||||||
log_err("Couldn't add alias to dev cache.");
|
log_err("Couldn't add alias to dev cache.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hash_insert(_cache.names, path, dev)) {
|
if (!dm_hash_insert(_cache.names, path, dev)) {
|
||||||
log_err("Couldn't add name to hash in dev cache.");
|
log_err("Couldn't add name to hash in dev cache.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -251,7 +287,7 @@ static int _insert_dev(const char *path, dev_t d)
|
|||||||
static char *_join(const char *dir, const char *name)
|
static char *_join(const char *dir, const char *name)
|
||||||
{
|
{
|
||||||
size_t len = strlen(dir) + strlen(name) + 2;
|
size_t len = strlen(dir) + strlen(name) + 2;
|
||||||
char *r = dbg_malloc(len);
|
char *r = dm_malloc(len);
|
||||||
if (r)
|
if (r)
|
||||||
snprintf(r, len, "%s/%s", dir, name);
|
snprintf(r, len, "%s/%s", dir, name);
|
||||||
|
|
||||||
@@ -301,7 +337,7 @@ static int _insert_dir(const char *dir)
|
|||||||
|
|
||||||
_collapse_slashes(path);
|
_collapse_slashes(path);
|
||||||
r &= _insert(path, 1);
|
r &= _insert(path, 1);
|
||||||
dbg_free(path);
|
dm_free(path);
|
||||||
|
|
||||||
free(dirent[n]);
|
free(dirent[n]);
|
||||||
}
|
}
|
||||||
@@ -311,6 +347,28 @@ static int _insert_dir(const char *dir)
|
|||||||
return r;
|
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)
|
static int _insert(const char *path, int rec)
|
||||||
{
|
{
|
||||||
struct stat info;
|
struct stat info;
|
||||||
@@ -353,19 +411,21 @@ static int _insert(const char *path, int rec)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _full_scan(void)
|
static void _full_scan(int dev_scan)
|
||||||
{
|
{
|
||||||
struct list *dh;
|
struct dir_list *dl;
|
||||||
|
|
||||||
if (_cache.has_scanned)
|
if (_cache.has_scanned && !dev_scan)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list_iterate(dh, &_cache.dirs) {
|
list_iterate_items(dl, &_cache.dirs)
|
||||||
struct dir_list *dl = list_item(dh, struct dir_list);
|
|
||||||
_insert_dir(dl->dir);
|
_insert_dir(dl->dir);
|
||||||
};
|
|
||||||
|
list_iterate_items(dl, &_cache.files)
|
||||||
|
_insert_file(dl->dir);
|
||||||
|
|
||||||
_cache.has_scanned = 1;
|
_cache.has_scanned = 1;
|
||||||
|
init_full_scan_done(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_cache_has_scanned(void)
|
int dev_cache_has_scanned(void)
|
||||||
@@ -377,24 +437,23 @@ void dev_cache_scan(int do_scan)
|
|||||||
{
|
{
|
||||||
if (!do_scan)
|
if (!do_scan)
|
||||||
_cache.has_scanned = 1;
|
_cache.has_scanned = 1;
|
||||||
else {
|
else
|
||||||
_cache.has_scanned = 0;
|
_full_scan(1);
|
||||||
_full_scan();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_cache_init(void)
|
int dev_cache_init(void)
|
||||||
{
|
{
|
||||||
_cache.names = NULL;
|
_cache.names = NULL;
|
||||||
|
_cache.has_scanned = 0;
|
||||||
|
|
||||||
if (!(_cache.mem = pool_create(10 * 1024))) {
|
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(_cache.names = hash_create(128))) {
|
if (!(_cache.names = dm_hash_create(128))) {
|
||||||
stack;
|
stack;
|
||||||
pool_destroy(_cache.mem);
|
dm_pool_destroy(_cache.mem);
|
||||||
_cache.mem = 0;
|
_cache.mem = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -405,6 +464,7 @@ int dev_cache_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_init(&_cache.dirs);
|
list_init(&_cache.dirs);
|
||||||
|
list_init(&_cache.files);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -421,7 +481,7 @@ static void _check_closed(struct device *dev)
|
|||||||
|
|
||||||
static inline void _check_for_open_devices(void)
|
static inline void _check_for_open_devices(void)
|
||||||
{
|
{
|
||||||
hash_iter(_cache.names, (iterate_fn) _check_closed);
|
dm_hash_iter(_cache.names, (dm_hash_iterate_fn) _check_closed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dev_cache_exit(void)
|
void dev_cache_exit(void)
|
||||||
@@ -430,18 +490,19 @@ void dev_cache_exit(void)
|
|||||||
_check_for_open_devices();
|
_check_for_open_devices();
|
||||||
|
|
||||||
if (_cache.mem) {
|
if (_cache.mem) {
|
||||||
pool_destroy(_cache.mem);
|
dm_pool_destroy(_cache.mem);
|
||||||
_cache.mem = NULL;
|
_cache.mem = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cache.names) {
|
if (_cache.names) {
|
||||||
hash_destroy(_cache.names);
|
dm_hash_destroy(_cache.names);
|
||||||
_cache.names = NULL;
|
_cache.names = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cache.devices = NULL;
|
_cache.devices = NULL;
|
||||||
_cache.has_scanned = 0;
|
_cache.has_scanned = 0;
|
||||||
list_init(&_cache.dirs);
|
list_init(&_cache.dirs);
|
||||||
|
list_init(&_cache.files);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dev_cache_add_dir(const char *path)
|
int dev_cache_add_dir(const char *path)
|
||||||
@@ -470,6 +531,32 @@ int dev_cache_add_dir(const char *path)
|
|||||||
return 1;
|
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 */
|
/* Check cached device name is still valid before returning it */
|
||||||
/* This should be a rare occurrence */
|
/* This should be a rare occurrence */
|
||||||
/* set quiet if the cache is expected to be out-of-date */
|
/* set quiet if the cache is expected to be out-of-date */
|
||||||
@@ -480,6 +567,9 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
|
|||||||
const char *name;
|
const char *name;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if ((dev->flags & DEV_REGULAR))
|
||||||
|
return dev_name(dev);
|
||||||
|
|
||||||
while ((r = stat(name = list_item(dev->aliases.n,
|
while ((r = stat(name = list_item(dev->aliases.n,
|
||||||
struct str_list)->str, &buf)) ||
|
struct str_list)->str, &buf)) ||
|
||||||
(buf.st_rdev != dev->dev)) {
|
(buf.st_rdev != dev->dev)) {
|
||||||
@@ -499,7 +589,7 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
|
|||||||
(int) MINOR(dev->dev));
|
(int) MINOR(dev->dev));
|
||||||
|
|
||||||
/* Remove the incorrect hash entry */
|
/* Remove the incorrect hash entry */
|
||||||
hash_remove(_cache.names, name);
|
dm_hash_remove(_cache.names, name);
|
||||||
|
|
||||||
/* Leave list alone if there isn't an alternative name */
|
/* Leave list alone if there isn't an alternative name */
|
||||||
/* so dev_name will always find something to return. */
|
/* so dev_name will always find something to return. */
|
||||||
@@ -522,32 +612,47 @@ const char *dev_name_confirmed(struct device *dev, int quiet)
|
|||||||
struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
struct device *dev_cache_get(const char *name, struct dev_filter *f)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
struct device *d = (struct device *) hash_lookup(_cache.names, name);
|
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 the entry's wrong, remove it */
|
||||||
if (d && (stat(name, &buf) || (buf.st_rdev != d->dev))) {
|
if (d && (stat(name, &buf) || (buf.st_rdev != d->dev))) {
|
||||||
hash_remove(_cache.names, name);
|
dm_hash_remove(_cache.names, name);
|
||||||
d = NULL;
|
d = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d) {
|
if (!d) {
|
||||||
_insert(name, 0);
|
_insert(name, 0);
|
||||||
d = (struct device *) hash_lookup(_cache.names, name);
|
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 || f->passes_filter(f, d))) ? d : NULL;
|
return (d && (!f || (d->flags & DEV_REGULAR) ||
|
||||||
|
f->passes_filter(f, d))) ? d : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_iter *dev_iter_create(struct dev_filter *f)
|
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan)
|
||||||
{
|
{
|
||||||
struct dev_iter *di = dbg_malloc(sizeof(*di));
|
struct dev_iter *di = dm_malloc(sizeof(*di));
|
||||||
|
|
||||||
if (!di) {
|
if (!di) {
|
||||||
log_error("dev_iter allocation failed");
|
log_error("dev_iter allocation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_full_scan();
|
|
||||||
|
if (dev_scan) {
|
||||||
|
/* 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->current = btree_first(_cache.devices);
|
||||||
di->filter = f;
|
di->filter = f;
|
||||||
|
|
||||||
@@ -556,7 +661,7 @@ struct dev_iter *dev_iter_create(struct dev_filter *f)
|
|||||||
|
|
||||||
void dev_iter_destroy(struct dev_iter *iter)
|
void dev_iter_destroy(struct dev_iter *iter)
|
||||||
{
|
{
|
||||||
dbg_free(iter);
|
dm_free(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct device *_iter_next(struct dev_iter *iter)
|
static inline struct device *_iter_next(struct dev_iter *iter)
|
||||||
@@ -570,7 +675,7 @@ struct device *dev_iter_get(struct dev_iter *iter)
|
|||||||
{
|
{
|
||||||
while (iter->current) {
|
while (iter->current) {
|
||||||
struct device *d = _iter_next(iter);
|
struct device *d = _iter_next(iter);
|
||||||
if (!iter->filter ||
|
if (!iter->filter || (d->flags & DEV_REGULAR) ||
|
||||||
iter->filter->passes_filter(iter->filter, d))
|
iter->filter->passes_filter(iter->filter, d))
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#ifndef _LVM_DEV_CACHE_H
|
#ifndef _LVM_DEV_CACHE_H
|
||||||
#define _LVM_DEV_CACHE_H
|
#define _LVM_DEV_CACHE_H
|
||||||
|
|
||||||
#include "lvm-types.h"
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -39,13 +38,14 @@ void dev_cache_scan(int do_scan);
|
|||||||
int dev_cache_has_scanned(void);
|
int dev_cache_has_scanned(void);
|
||||||
|
|
||||||
int dev_cache_add_dir(const char *path);
|
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);
|
struct device *dev_cache_get(const char *name, struct dev_filter *f);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Object for iterating through the cache.
|
* Object for iterating through the cache.
|
||||||
*/
|
*/
|
||||||
struct dev_iter;
|
struct dev_iter;
|
||||||
struct dev_iter *dev_iter_create(struct dev_filter *f);
|
struct dev_iter *dev_iter_create(struct dev_filter *f, int dev_scan);
|
||||||
void dev_iter_destroy(struct dev_iter *iter);
|
void dev_iter_destroy(struct dev_iter *iter);
|
||||||
struct device *dev_iter_get(struct dev_iter *iter);
|
struct device *dev_iter_get(struct dev_iter *iter);
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,9 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
|
if (lseek(fd, (off_t) where->start, SEEK_SET) < 0) {
|
||||||
log_sys_error("lseek", dev_name(where->dev));
|
log_error("%s: lseek %" PRIu64 " failed: %s",
|
||||||
|
dev_name(where->dev), (uint64_t) where->start,
|
||||||
|
strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,6 +94,14 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
|||||||
read(fd, buffer, (size_t) where->size - total);
|
read(fd, buffer, (size_t) where->size - total);
|
||||||
while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
|
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)
|
if (n <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -114,14 +124,18 @@ static int _io(struct device_area *where, void *buffer, int should_write)
|
|||||||
*/
|
*/
|
||||||
static int _get_block_size(struct device *dev, unsigned int *size)
|
static int _get_block_size(struct device *dev, unsigned int *size)
|
||||||
{
|
{
|
||||||
int s;
|
const char *name = dev_name(dev);
|
||||||
|
|
||||||
if (ioctl(dev_fd(dev), BLKBSZGET, &s) < 0) {
|
if ((dev->block_size == -1)) {
|
||||||
log_sys_error("ioctl BLKBSZGET", dev_name(dev));
|
if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) {
|
||||||
return 0;
|
log_sys_error("ioctl BLKBSZGET", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
log_debug("%s: block size is %u bytes", name, dev->block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
*size = (unsigned int) s;
|
*size = (unsigned int) dev->block_size;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,16 +222,29 @@ static int _aligned_io(struct device_area *where, void *buffer,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------
|
static int _dev_get_size_file(const struct device *dev, uint64_t *size)
|
||||||
* Public functions
|
{
|
||||||
*---------------------------------------------------------------*/
|
const char *name = dev_name(dev);
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
int dev_get_size(struct device *dev, uint64_t *size)
|
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;
|
int fd;
|
||||||
const char *name = dev_name(dev);
|
const char *name = dev_name(dev);
|
||||||
|
|
||||||
log_very_verbose("Getting size of %s", name);
|
|
||||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||||
log_sys_error("open", name);
|
log_sys_error("open", name);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -225,22 +252,39 @@ int dev_get_size(struct device *dev, uint64_t *size)
|
|||||||
|
|
||||||
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
|
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
|
||||||
log_sys_error("ioctl BLKGETSIZE64", name);
|
log_sys_error("ioctl BLKGETSIZE64", name);
|
||||||
close(fd);
|
if (close(fd))
|
||||||
|
log_sys_error("close", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*size >>= BLKSIZE_SHIFT; /* Convert to sectors */
|
*size >>= BLKSIZE_SHIFT; /* Convert to sectors */
|
||||||
close(fd);
|
if (close(fd))
|
||||||
|
log_sys_error("close", name);
|
||||||
|
|
||||||
|
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
|
||||||
|
|
||||||
return 1;
|
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 dev_get_sectsize(struct device *dev, uint32_t *size)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int s;
|
int s;
|
||||||
const char *name = dev_name(dev);
|
const char *name = dev_name(dev);
|
||||||
|
|
||||||
log_very_verbose("Getting size of %s", name);
|
|
||||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||||
log_sys_error("open", name);
|
log_sys_error("open", name);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -254,8 +298,12 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
|
|||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
*size = (uint32_t) s;
|
*size = (uint32_t) s;
|
||||||
|
|
||||||
|
log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void dev_flush(struct device *dev)
|
void dev_flush(struct device *dev)
|
||||||
{
|
{
|
||||||
@@ -272,10 +320,29 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
|||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
const char *name;
|
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->fd >= 0) {
|
||||||
dev->open_count++;
|
if (((dev->flags & DEV_OPENED_RW) || !need_rw) &&
|
||||||
return 1;
|
((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())
|
if (memlock())
|
||||||
@@ -296,23 +363,62 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef O_DIRECT_SUPPORT
|
#ifdef O_DIRECT_SUPPORT
|
||||||
if (direct)
|
if (direct) {
|
||||||
flags |= O_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
|
#endif
|
||||||
|
|
||||||
if ((dev->fd = open(name, flags, 0777)) < 0) {
|
if ((dev->fd = open(name, flags, 0777)) < 0) {
|
||||||
log_sys_error("open", name);
|
#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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->open_count = 1;
|
#ifdef O_DIRECT_SUPPORT
|
||||||
|
opened:
|
||||||
|
if (direct)
|
||||||
|
dev->flags |= DEV_O_DIRECT_TESTED;
|
||||||
|
#endif
|
||||||
|
dev->open_count++;
|
||||||
dev->flags &= ~DEV_ACCESSED_W;
|
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) &&
|
if (!(dev->flags & DEV_REGULAR) &&
|
||||||
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
|
((fstat(dev->fd, &buf) < 0) || (buf.st_rdev != dev->dev))) {
|
||||||
log_error("%s: fstat failed: Has device name changed?", name);
|
log_error("%s: fstat failed: Has device name changed?", name);
|
||||||
dev_close(dev);
|
dev_close_immediate(dev);
|
||||||
dev->fd = -1;
|
dev->open_count = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,12 +427,15 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
|
|||||||
dev_flush(dev);
|
dev_flush(dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((flags & O_CREAT) && !(flags & O_TRUNC)) {
|
if ((flags & O_CREAT) && !(flags & O_TRUNC))
|
||||||
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
|
dev->end = lseek(dev->fd, (off_t) 0, SEEK_END);
|
||||||
}
|
|
||||||
|
|
||||||
list_add(&_open_devices, &dev->open_list);
|
list_add(&_open_devices, &dev->open_list);
|
||||||
log_debug("Opened %s", dev_name(dev));
|
|
||||||
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -349,25 +458,43 @@ int dev_open(struct device *dev)
|
|||||||
return dev_open_flags(dev, flags, 1, 0);
|
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)
|
static void _close(struct device *dev)
|
||||||
{
|
{
|
||||||
if (close(dev->fd))
|
if (close(dev->fd))
|
||||||
log_sys_error("close", dev_name(dev));
|
log_sys_error("close", dev_name(dev));
|
||||||
dev->fd = -1;
|
dev->fd = -1;
|
||||||
|
dev->block_size = -1;
|
||||||
list_del(&dev->open_list);
|
list_del(&dev->open_list);
|
||||||
|
|
||||||
log_debug("Closed %s", dev_name(dev));
|
log_debug("Closed %s", dev_name(dev));
|
||||||
|
|
||||||
if (dev->flags & DEV_ALLOCED) {
|
if (dev->flags & DEV_ALLOCED) {
|
||||||
dbg_free((void *) list_item(dev->aliases.n, struct str_list)->
|
dm_free((void *) list_item(dev->aliases.n, struct str_list)->
|
||||||
str);
|
str);
|
||||||
dbg_free(dev->aliases.n);
|
dm_free(dev->aliases.n);
|
||||||
dbg_free(dev);
|
dm_free(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dev_close(struct device *dev, int immediate)
|
static int _dev_close(struct device *dev, int immediate)
|
||||||
{
|
{
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
if (dev->fd < 0) {
|
if (dev->fd < 0) {
|
||||||
log_error("Attempt to close device '%s' "
|
log_error("Attempt to close device '%s' "
|
||||||
"which is not open.", dev_name(dev));
|
"which is not open.", dev_name(dev));
|
||||||
@@ -379,8 +506,21 @@ static int _dev_close(struct device *dev, int immediate)
|
|||||||
dev_flush(dev);
|
dev_flush(dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* FIXME lookup device in cache to get vgname and see if it's locked? */
|
if (dev->open_count > 0)
|
||||||
if (--dev->open_count < 1 && (immediate || !vgs_locked()))
|
dev->open_count--;
|
||||||
|
|
||||||
|
if (immediate && dev->open_count) {
|
||||||
|
log_debug("%s: Immediate close attempt while still referenced",
|
||||||
|
dev_name(dev));
|
||||||
|
dev->open_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
_close(dev);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -412,8 +552,10 @@ int dev_read(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
|||||||
{
|
{
|
||||||
struct device_area where;
|
struct device_area where;
|
||||||
|
|
||||||
if (!dev->open_count)
|
if (!dev->open_count) {
|
||||||
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
where.dev = dev;
|
where.dev = dev;
|
||||||
where.start = offset;
|
where.start = offset;
|
||||||
@@ -431,8 +573,10 @@ int dev_append(struct device *dev, size_t len, void *buffer)
|
|||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!dev->open_count)
|
if (!dev->open_count) {
|
||||||
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
r = dev_write(dev, dev->end, len, buffer);
|
r = dev_write(dev, dev->end, len, buffer);
|
||||||
dev->end += (uint64_t) len;
|
dev->end += (uint64_t) len;
|
||||||
@@ -447,8 +591,10 @@ int dev_write(struct device *dev, uint64_t offset, size_t len, void *buffer)
|
|||||||
{
|
{
|
||||||
struct device_area where;
|
struct device_area where;
|
||||||
|
|
||||||
if (!dev->open_count)
|
if (!dev->open_count) {
|
||||||
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
where.dev = dev;
|
where.dev = dev;
|
||||||
where.start = offset;
|
where.start = offset;
|
||||||
@@ -495,6 +641,5 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len)
|
|||||||
if (!dev_close(dev))
|
if (!dev_close(dev))
|
||||||
stack;
|
stack;
|
||||||
|
|
||||||
/* FIXME: Always display error */
|
|
||||||
return (len == 0);
|
return (len == 0);
|
||||||
}
|
}
|
||||||
|
|||||||
69
lib/device/dev-md.c
Normal file
69
lib/device/dev-md.c
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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. */
|
||||||
|
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
|
||||||
|
(md_magic == xlate32(MD_SB_MAGIC))) {
|
||||||
|
if (sb)
|
||||||
|
*sb = sb_offset;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev_close(dev))
|
||||||
|
stack;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -13,6 +13,93 @@
|
|||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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;
|
||||||
|
uint8_t buf[SECTOR_SIZE];
|
||||||
|
uint16_t *part_magic;
|
||||||
|
struct partition *part;
|
||||||
|
|
||||||
|
if (!dev_open(dev)) {
|
||||||
|
stack;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev_read(dev, 0, sizeof(buf), &buf)) {
|
||||||
|
stack;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME Check for other types of partition table too */
|
||||||
|
|
||||||
|
/* Check for msdos partition table */
|
||||||
|
part_magic = (uint16_t *)(buf + PART_MAGIC_OFFSET);
|
||||||
|
if ((*part_magic == xlate16(PART_MAGIC))) {
|
||||||
|
part = (struct partition *) (buf + PART_OFFSET);
|
||||||
|
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
|
#if 0
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
@@ -27,24 +114,13 @@
|
|||||||
#include <linux/major.h>
|
#include <linux/major.h>
|
||||||
#include <linux/genhd.h>
|
#include <linux/genhd.h>
|
||||||
|
|
||||||
#include "dbg_malloc.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "dev-cache.h"
|
|
||||||
#include "metadata.h"
|
|
||||||
#include "device.h"
|
|
||||||
|
|
||||||
int _get_partition_type(struct dev_filter *filter, struct device *d);
|
int _get_partition_type(struct dev_filter *filter, struct device *d);
|
||||||
|
|
||||||
#define MINOR_PART(dm, d) (MINOR((d)->dev) % dev_max_partitions(dm, (d)->dev))
|
#define MINOR_PART(dev) (MINOR((dev)->dev) % max_partitions(MINOR((dev)->dev)))
|
||||||
|
|
||||||
int is_whole_disk(struct dev_filter *filter, struct device *d)
|
int is_extended_partition(struct device *d)
|
||||||
{
|
{
|
||||||
return (MINOR_PART(dm, d)) ? 0 : 1;
|
return (MINOR_PART(d) > 4) ? 1 : 0;
|
||||||
}
|
|
||||||
|
|
||||||
int is_extended_partition(struct dev_mgr *dm, struct device *d)
|
|
||||||
{
|
|
||||||
return (MINOR_PART(dm, d) > 4) ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct device *dev_primary(struct dev_mgr *dm, struct device *d)
|
struct device *dev_primary(struct dev_mgr *dm, struct device *d)
|
||||||
@@ -126,7 +202,7 @@ int _get_partition_type(struct dev_mgr *dm, struct device *d)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(buffer = dbg_malloc(SECTOR_SIZE))) {
|
if (!(buffer = dm_malloc(SECTOR_SIZE))) {
|
||||||
log_error("Failed to allocate partition table buffer");
|
log_error("Failed to allocate partition table buffer");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,16 @@
|
|||||||
#define _LVM_DEVICE_H
|
#define _LVM_DEVICE_H
|
||||||
|
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
|
#define DEV_ACCESSED_W 0x00000001 /* Device written to? */
|
||||||
#define DEV_REGULAR 0x00000002 /* Regular file? */
|
#define DEV_REGULAR 0x00000002 /* Regular file? */
|
||||||
#define DEV_ALLOCED 0x00000004 /* dbg_malloc used */
|
#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.
|
* All devices in LVM will be represented by one of these.
|
||||||
@@ -34,11 +39,13 @@ struct device {
|
|||||||
/* private */
|
/* private */
|
||||||
int fd;
|
int fd;
|
||||||
int open_count;
|
int open_count;
|
||||||
|
int block_size;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint64_t end;
|
uint64_t end;
|
||||||
struct list open_list;
|
struct list open_list;
|
||||||
|
|
||||||
char pvid[ID_LEN + 1];
|
char pvid[ID_LEN + 1];
|
||||||
|
char _padding[7];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device_list {
|
struct device_list {
|
||||||
@@ -55,16 +62,17 @@ struct device_area {
|
|||||||
/*
|
/*
|
||||||
* All io should use these routines.
|
* All io should use these routines.
|
||||||
*/
|
*/
|
||||||
int dev_get_size(struct device *dev, uint64_t *size);
|
int dev_get_size(const struct device *dev, uint64_t *size);
|
||||||
int dev_get_sectsize(struct device *dev, uint32_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 */
|
/* Use quiet version if device number could change e.g. when opening LV */
|
||||||
int dev_open(struct device *dev);
|
int dev_open(struct device *dev);
|
||||||
int dev_open_quiet(struct device *dev);
|
int dev_open_quiet(struct device *dev);
|
||||||
int dev_open_flags(struct device *dev, int flags, int append, int quiet);
|
int dev_open_flags(struct device *dev, int flags, int direct, int quiet);
|
||||||
int dev_close(struct device *dev);
|
int dev_close(struct device *dev);
|
||||||
int dev_close_immediate(struct device *dev);
|
int dev_close_immediate(struct device *dev);
|
||||||
void dev_close_all(void);
|
void dev_close_all(void);
|
||||||
|
int dev_test_excl(struct device *dev);
|
||||||
|
|
||||||
static inline int dev_fd(struct device *dev)
|
static inline int dev_fd(struct device *dev)
|
||||||
{
|
{
|
||||||
@@ -78,7 +86,7 @@ int dev_zero(struct device *dev, uint64_t offset, size_t len);
|
|||||||
void dev_flush(struct device *dev);
|
void dev_flush(struct device *dev);
|
||||||
|
|
||||||
struct device *dev_create_file(const char *filename, struct device *dev,
|
struct device *dev_create_file(const char *filename, struct device *dev,
|
||||||
struct str_list *alias);
|
struct str_list *alias, int use_malloc);
|
||||||
|
|
||||||
static inline const char *dev_name(const struct device *dev)
|
static inline const char *dev_name(const struct device *dev)
|
||||||
{
|
{
|
||||||
@@ -89,15 +97,14 @@ static inline const char *dev_name(const struct device *dev)
|
|||||||
/* Return a valid device name from the alias list; NULL otherwise */
|
/* Return a valid device name from the alias list; NULL otherwise */
|
||||||
const char *dev_name_confirmed(struct device *dev, int quiet);
|
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 */
|
/* FIXME Check partition type if appropriate */
|
||||||
|
|
||||||
#define is_lvm_partition(a) 1
|
#define is_lvm_partition(a) 1
|
||||||
|
/* int is_lvm_partition(const char *name); */
|
||||||
|
|
||||||
/*
|
int is_partitioned_dev(struct device *dev);
|
||||||
static inline int is_lvm_partition(const char *name)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "activate.h"
|
#include "activate.h"
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "segtypes.h"
|
#include "segtype.h"
|
||||||
|
|
||||||
#define SIZE_BUF 128
|
#define SIZE_BUF 128
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ const char *display_size(struct cmd_context *cmd, uint64_t size, size_len_t sl)
|
|||||||
{" ", " ", " "},
|
{" ", " ", " "},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(size_buf = pool_alloc(cmd->mem, SIZE_BUF))) {
|
if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
|
||||||
log_error("no memory for size display buffer");
|
log_error("no memory for size display buffer");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -258,7 +258,7 @@ void pvdisplay_full(struct cmd_context *cmd, struct physical_volume *pv,
|
|||||||
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
|
log_print("PV Size %s" " / not usable %s", /* [LVM: %s]", */
|
||||||
size,
|
size,
|
||||||
display_size(cmd, (pv->size -
|
display_size(cmd, (pv->size -
|
||||||
pv->pe_count * pv->pe_size),
|
(uint64_t) pv->pe_count * pv->pe_size),
|
||||||
SIZE_SHORT));
|
SIZE_SHORT));
|
||||||
|
|
||||||
} else
|
} else
|
||||||
@@ -317,7 +317,7 @@ void lvdisplay_colons(struct logical_volume *lv)
|
|||||||
{
|
{
|
||||||
int inkernel;
|
int inkernel;
|
||||||
struct lvinfo info;
|
struct lvinfo info;
|
||||||
inkernel = lv_info(lv, &info) && info.exists;
|
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",
|
log_print("%s%s/%s:%s:%d:%d:-1:%d:%" PRIu64 ":%d:-1:%d:%d:%d:%d",
|
||||||
lv->vg->cmd->dev_dir,
|
lv->vg->cmd->dev_dir,
|
||||||
@@ -337,10 +337,9 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
|||||||
void *handle)
|
void *handle)
|
||||||
{
|
{
|
||||||
struct lvinfo info;
|
struct lvinfo info;
|
||||||
int inkernel, snap_active;
|
int inkernel, snap_active = 0;
|
||||||
char uuid[64];
|
char uuid[64];
|
||||||
struct snapshot *snap = NULL;
|
struct lv_segment *snap_seg = NULL;
|
||||||
struct list *slh, *snaplist;
|
|
||||||
float snap_percent; /* fused, fsize; */
|
float snap_percent; /* fused, fsize; */
|
||||||
|
|
||||||
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
|
if (!id_write_format(&lv->lvid.id[1], uuid, sizeof(uuid))) {
|
||||||
@@ -348,7 +347,7 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inkernel = lv_info(lv, &info) && info.exists;
|
inkernel = lv_info(cmd, lv, &info, 1) && info.exists;
|
||||||
|
|
||||||
log_print("--- Logical volume ---");
|
log_print("--- Logical volume ---");
|
||||||
|
|
||||||
@@ -364,27 +363,30 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
|||||||
if (lv_is_origin(lv)) {
|
if (lv_is_origin(lv)) {
|
||||||
log_print("LV snapshot status source of");
|
log_print("LV snapshot status source of");
|
||||||
|
|
||||||
snaplist = find_snapshots(lv);
|
list_iterate_items_gen(snap_seg, &lv->snapshot_segs,
|
||||||
list_iterate(slh, snaplist) {
|
origin_list) {
|
||||||
snap = list_item(slh, struct snapshot_list)->snapshot;
|
if (inkernel &&
|
||||||
snap_active = lv_snapshot_percent(snap->cow,
|
(snap_active = lv_snapshot_percent(snap_seg->cow,
|
||||||
&snap_percent);
|
&snap_percent)))
|
||||||
if (!snap_active || snap_percent < 0 ||
|
if (snap_percent < 0 || snap_percent >= 100)
|
||||||
snap_percent >= 100) snap_active = 0;
|
snap_active = 0;
|
||||||
log_print(" %s%s/%s [%s]",
|
log_print(" %s%s/%s [%s]",
|
||||||
lv->vg->cmd->dev_dir, lv->vg->name,
|
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||||
snap->cow->name,
|
snap_seg->cow->name,
|
||||||
(snap_active > 0) ? "active" : "INACTIVE");
|
(snap_active > 0) ? "active" : "INACTIVE");
|
||||||
}
|
}
|
||||||
snap = NULL;
|
snap_seg = NULL;
|
||||||
} else if ((snap = find_cow(lv))) {
|
} else if ((snap_seg = find_cow(lv))) {
|
||||||
snap_active = lv_snapshot_percent(lv, &snap_percent);
|
if (inkernel &&
|
||||||
if (!snap_active || snap_percent < 0 || snap_percent >= 100)
|
(snap_active = lv_snapshot_percent(snap_seg->cow,
|
||||||
snap_active = 0;
|
&snap_percent)))
|
||||||
|
if (snap_percent < 0 || snap_percent >= 100)
|
||||||
|
snap_active = 0;
|
||||||
|
|
||||||
log_print("LV snapshot status %s destination for %s%s/%s",
|
log_print("LV snapshot status %s destination for %s%s/%s",
|
||||||
(snap_active > 0) ? "active" : "INACTIVE",
|
(snap_active > 0) ? "active" : "INACTIVE",
|
||||||
lv->vg->cmd->dev_dir, lv->vg->name,
|
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||||
snap->origin->name);
|
snap_seg->origin->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inkernel && info.suspended)
|
if (inkernel && info.suspended)
|
||||||
@@ -402,15 +404,24 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
|||||||
|
|
||||||
log_print("LV Size %s",
|
log_print("LV Size %s",
|
||||||
display_size(cmd,
|
display_size(cmd,
|
||||||
snap ? snap->origin->size : lv->size,
|
snap_seg ? snap_seg->origin->size : lv->size,
|
||||||
SIZE_SHORT));
|
SIZE_SHORT));
|
||||||
|
|
||||||
log_print("Current LE %u",
|
log_print("Current LE %u",
|
||||||
snap ? snap->origin->le_count : lv->le_count);
|
snap_seg ? snap_seg->origin->le_count : lv->le_count);
|
||||||
|
|
||||||
/********** FIXME allocation
|
if (snap_seg) {
|
||||||
log_print("Allocated LE %u", lv->allocated_le);
|
log_print("COW-table size %s",
|
||||||
**********/
|
display_size(cmd, (uint64_t) lv->size, SIZE_SHORT));
|
||||||
|
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,
|
||||||
|
SIZE_SHORT));
|
||||||
|
}
|
||||||
|
|
||||||
log_print("Segments %u", list_size(&lv->segments));
|
log_print("Segments %u", list_size(&lv->segments));
|
||||||
|
|
||||||
@@ -418,31 +429,6 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
|||||||
log_print("Stripe size (KByte) %u", lv->stripesize / 2);
|
log_print("Stripe size (KByte) %u", lv->stripesize / 2);
|
||||||
***********/
|
***********/
|
||||||
|
|
||||||
if (snap) {
|
|
||||||
if (snap_percent == -1)
|
|
||||||
snap_percent = 100;
|
|
||||||
|
|
||||||
log_print("Snapshot chunk size %s",
|
|
||||||
display_size(cmd, (uint64_t) snap->chunk_size,
|
|
||||||
SIZE_SHORT));
|
|
||||||
|
|
||||||
/*
|
|
||||||
size = display_size(lv->size, SIZE_SHORT);
|
|
||||||
sscanf(size, "%f", &fsize);
|
|
||||||
fused = fsize * snap_percent / 100;
|
|
||||||
*/
|
|
||||||
log_print("Allocated to snapshot %.2f%% ", /* [%.2f/%s]", */
|
|
||||||
snap_percent); /*, fused, size); */
|
|
||||||
/* dbg_free(size); */
|
|
||||||
}
|
|
||||||
|
|
||||||
/********** FIXME Snapshot
|
|
||||||
size = ???
|
|
||||||
log_print("Allocated to COW-table %s", size);
|
|
||||||
dbg_free(size);
|
|
||||||
}
|
|
||||||
******************/
|
|
||||||
|
|
||||||
log_print("Allocation %s", get_alloc_string(lv->alloc));
|
log_print("Allocation %s", get_alloc_string(lv->alloc));
|
||||||
log_print("Read ahead sectors %u", lv->read_ahead);
|
log_print("Read ahead sectors %u", lv->read_ahead);
|
||||||
|
|
||||||
@@ -463,27 +449,31 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
|||||||
|
|
||||||
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
|
void display_stripe(const struct lv_segment *seg, uint32_t s, const char *pre)
|
||||||
{
|
{
|
||||||
switch (seg->area[s].type) {
|
switch (seg_type(seg, s)) {
|
||||||
case AREA_PV:
|
case AREA_PV:
|
||||||
|
/* FIXME Re-check the conditions for 'Missing' */
|
||||||
log_print("%sPhysical volume\t%s", pre,
|
log_print("%sPhysical volume\t%s", pre,
|
||||||
seg->area[s].u.pv.pv ?
|
seg_pv(seg, s) ?
|
||||||
dev_name(seg->area[s].u.pv.pv->dev) : "Missing");
|
dev_name(seg_dev(seg, s)) :
|
||||||
|
"Missing");
|
||||||
|
|
||||||
if (seg->area[s].u.pv.pv)
|
if (seg_pv(seg, s))
|
||||||
log_print("%sPhysical extents\t%d to %d", pre,
|
log_print("%sPhysical extents\t%d to %d", pre,
|
||||||
seg->area[s].u.pv.pe,
|
seg_pe(seg, s),
|
||||||
seg->area[s].u.pv.pe + seg->area_len - 1);
|
seg_pe(seg, s) + seg->area_len - 1);
|
||||||
break;
|
break;
|
||||||
case AREA_LV:
|
case AREA_LV:
|
||||||
log_print("%sLogical volume\t%s", pre,
|
log_print("%sLogical volume\t%s", pre,
|
||||||
seg->area[s].u.lv.lv ?
|
seg_lv(seg, s) ?
|
||||||
seg->area[s].u.lv.lv->name : "Missing");
|
seg_lv(seg, s)->name : "Missing");
|
||||||
|
|
||||||
if (seg->area[s].u.lv.lv)
|
if (seg_lv(seg, s))
|
||||||
log_print("%sLogical extents\t%d to %d", pre,
|
log_print("%sLogical extents\t%d to %d", pre,
|
||||||
seg->area[s].u.lv.le,
|
seg_le(seg, s),
|
||||||
seg->area[s].u.lv.le + seg->area_len - 1);
|
seg_le(seg, s) + seg->area_len - 1);
|
||||||
|
break;
|
||||||
|
case AREA_UNASSIGNED:
|
||||||
|
log_print("%sUnassigned area", pre);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,7 +540,7 @@ void vgdisplay_full(struct volume_group *vg)
|
|||||||
vg->status & SHARED ? "yes" : "no");
|
vg->status & SHARED ? "yes" : "no");
|
||||||
}
|
}
|
||||||
log_print("MAX LV %u", vg->max_lv);
|
log_print("MAX LV %u", vg->max_lv);
|
||||||
log_print("Cur LV %u", vg->lv_count);
|
log_print("Cur LV %u", vg->lv_count + vg->snapshot_count);
|
||||||
log_print("Open LV %u", lvs_in_vg_opened(vg));
|
log_print("Open LV %u", lvs_in_vg_opened(vg));
|
||||||
/****** FIXME Max LV Size
|
/****** FIXME Max LV Size
|
||||||
log_print ( "MAX LV Size %s",
|
log_print ( "MAX LV Size %s",
|
||||||
@@ -662,3 +652,22 @@ void vgdisplay_short(struct volume_group *vg)
|
|||||||
SIZE_SHORT));
|
SIZE_SHORT));
|
||||||
return;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ void vgdisplay_full(struct volume_group *vg);
|
|||||||
void vgdisplay_colons(struct volume_group *vg);
|
void vgdisplay_colons(struct volume_group *vg);
|
||||||
void vgdisplay_short(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.
|
* Allocation policy display conversion routines.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -13,10 +13,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "segtypes.h"
|
#include "segtype.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "text_export.h"
|
#include "text_export.h"
|
||||||
#include "text_import.h"
|
#include "text_import.h"
|
||||||
@@ -40,18 +38,13 @@ static int _merge_segments(struct lv_segment *seg1, struct lv_segment *seg2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEVMAPPER_SUPPORT
|
#ifdef DEVMAPPER_SUPPORT
|
||||||
static int _compose_target_line(struct dev_manager *dm, struct pool *mem,
|
static int _add_target_line(struct dev_manager *dm, struct dm_pool *mem,
|
||||||
struct config_tree *cft, void **target_state,
|
struct config_tree *cft, void **target_state,
|
||||||
struct lv_segment *seg, char *params,
|
struct lv_segment *seg,
|
||||||
size_t paramsize, const char **target, int *pos,
|
struct dm_tree_node *node, uint64_t len,
|
||||||
uint32_t *pvmove_mirror_count)
|
uint32_t *pvmove_mirror_count)
|
||||||
{
|
{
|
||||||
/* error */
|
return dm_tree_node_add_error_target(node, len);
|
||||||
|
|
||||||
*target = "error";
|
|
||||||
*params = '\0';
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _target_present(void)
|
static int _target_present(void)
|
||||||
@@ -59,8 +52,10 @@ static int _target_present(void)
|
|||||||
static int checked = 0;
|
static int checked = 0;
|
||||||
static int present = 0;
|
static int present = 0;
|
||||||
|
|
||||||
if (!checked)
|
/* Reported truncated in older kernels */
|
||||||
present = target_present("error");
|
if (!checked &&
|
||||||
|
(target_present("error", 0) || target_present("erro", 0)))
|
||||||
|
present = 1;
|
||||||
|
|
||||||
checked = 1;
|
checked = 1;
|
||||||
return present;
|
return present;
|
||||||
@@ -69,14 +64,14 @@ static int _target_present(void)
|
|||||||
|
|
||||||
static void _destroy(const struct segment_type *segtype)
|
static void _destroy(const struct segment_type *segtype)
|
||||||
{
|
{
|
||||||
dbg_free((void *) segtype);
|
dm_free((void *) segtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct segtype_handler _error_ops = {
|
static struct segtype_handler _error_ops = {
|
||||||
name:_name,
|
name:_name,
|
||||||
merge_segments:_merge_segments,
|
merge_segments:_merge_segments,
|
||||||
#ifdef DEVMAPPER_SUPPORT
|
#ifdef DEVMAPPER_SUPPORT
|
||||||
compose_target_line:_compose_target_line,
|
add_target_line:_add_target_line,
|
||||||
target_present:_target_present,
|
target_present:_target_present,
|
||||||
#endif
|
#endif
|
||||||
destroy:_destroy,
|
destroy:_destroy,
|
||||||
@@ -84,18 +79,18 @@ static struct segtype_handler _error_ops = {
|
|||||||
|
|
||||||
struct segment_type *init_error_segtype(struct cmd_context *cmd)
|
struct segment_type *init_error_segtype(struct cmd_context *cmd)
|
||||||
{
|
{
|
||||||
struct segment_type *segtype = dbg_malloc(sizeof(*segtype));
|
struct segment_type *segtype = dm_malloc(sizeof(*segtype));
|
||||||
|
|
||||||
if (!segtype) {
|
if (!segtype)
|
||||||
stack;
|
return_NULL;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
segtype->cmd = cmd;
|
segtype->cmd = cmd;
|
||||||
segtype->ops = &_error_ops;
|
segtype->ops = &_error_ops;
|
||||||
segtype->name = "error";
|
segtype->name = "error";
|
||||||
segtype->private = NULL;
|
segtype->private = NULL;
|
||||||
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL;
|
segtype->flags = SEG_CAN_SPLIT | SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
|
||||||
|
|
||||||
|
log_very_verbose("Initialised segtype: %s", segtype->name);
|
||||||
|
|
||||||
return segtype;
|
return segtype;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ static void _destroy(struct dev_filter *f)
|
|||||||
filters++;
|
filters++;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg_free(f->private);
|
dm_free(f->private);
|
||||||
dbg_free(f);
|
dm_free(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
||||||
@@ -55,7 +55,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(filters_copy = dbg_malloc(sizeof(*filters) * (n + 1)))) {
|
if (!(filters_copy = dm_malloc(sizeof(*filters) * (n + 1)))) {
|
||||||
log_error("composite filters allocation failed");
|
log_error("composite filters allocation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -63,9 +63,9 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
|
|||||||
memcpy(filters_copy, filters, sizeof(*filters) * n);
|
memcpy(filters_copy, filters, sizeof(*filters) * n);
|
||||||
filters_copy[n] = NULL;
|
filters_copy[n] = NULL;
|
||||||
|
|
||||||
if (!(cft = dbg_malloc(sizeof(*cft)))) {
|
if (!(cft = dm_malloc(sizeof(*cft)))) {
|
||||||
log_error("compsoite filters allocation failed");
|
log_error("compsoite filters allocation failed");
|
||||||
dbg_free(filters_copy);
|
dm_free(filters_copy);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,55 +28,37 @@
|
|||||||
|
|
||||||
static int _ignore_md(struct dev_filter *f, struct device *dev)
|
static int _ignore_md(struct dev_filter *f, struct device *dev)
|
||||||
{
|
{
|
||||||
uint64_t size, sector;
|
int ret;
|
||||||
uint32_t md_magic;
|
|
||||||
|
if (!md_filtering())
|
||||||
if (!dev_get_size(dev, &size)) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size < MD_RESERVED_SECTORS * 2)
|
|
||||||
/*
|
|
||||||
* We could ignore it since it is obviously too
|
|
||||||
* small, but that's not our job.
|
|
||||||
*/
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
ret = dev_is_md(dev, NULL);
|
||||||
|
|
||||||
if (!dev_open(dev)) {
|
if (ret == 1) {
|
||||||
stack;
|
log_debug("%s: Skipping md component device", dev_name(dev));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sector = MD_NEW_SIZE_SECTORS(size);
|
if (ret < 0) {
|
||||||
|
log_debug("%s: Skipping: error in md component detection",
|
||||||
/* Check if it is an md component device. */
|
dev_name(dev));
|
||||||
if (dev_read(dev, sector << SECTOR_SHIFT, sizeof(uint32_t), &md_magic)) {
|
return 0;
|
||||||
if (md_magic == MD_SB_MAGIC) {
|
|
||||||
log_debug("%s: Skipping md component device",
|
|
||||||
dev_name(dev));
|
|
||||||
if (!dev_close(dev))
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev_close(dev))
|
|
||||||
stack;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _destroy(struct dev_filter *f)
|
static void _destroy(struct dev_filter *f)
|
||||||
{
|
{
|
||||||
dbg_free(f);
|
dm_free(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_filter *md_filter_create(void)
|
struct dev_filter *md_filter_create(void)
|
||||||
{
|
{
|
||||||
struct dev_filter *f;
|
struct dev_filter *f;
|
||||||
|
|
||||||
if (!(f = dbg_malloc(sizeof(*f)))) {
|
if (!(f = dm_malloc(sizeof(*f)))) {
|
||||||
log_error("md filter allocation failed");
|
log_error("md filter allocation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "dev-cache.h"
|
#include "dev-cache.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "filter-persistent.h"
|
#include "filter-persistent.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -25,7 +24,7 @@
|
|||||||
|
|
||||||
struct pfilter {
|
struct pfilter {
|
||||||
char *file;
|
char *file;
|
||||||
struct hash_table *devices;
|
struct dm_hash_table *devices;
|
||||||
struct dev_filter *real;
|
struct dev_filter *real;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,9 +38,9 @@ struct pfilter {
|
|||||||
static int _init_hash(struct pfilter *pf)
|
static int _init_hash(struct pfilter *pf)
|
||||||
{
|
{
|
||||||
if (pf->devices)
|
if (pf->devices)
|
||||||
hash_destroy(pf->devices);
|
dm_hash_destroy(pf->devices);
|
||||||
|
|
||||||
if (!(pf->devices = hash_create(128))) {
|
if (!(pf->devices = dm_hash_create(128))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -53,7 +52,9 @@ int persistent_filter_wipe(struct dev_filter *f)
|
|||||||
{
|
{
|
||||||
struct pfilter *pf = (struct pfilter *) f->private;
|
struct pfilter *pf = (struct pfilter *) f->private;
|
||||||
|
|
||||||
hash_wipe(pf->devices);
|
log_verbose("Wiping cache of LVM-capable devices");
|
||||||
|
dm_hash_wipe(pf->devices);
|
||||||
|
|
||||||
/* Trigger complete device scan */
|
/* Trigger complete device scan */
|
||||||
dev_cache_scan(1);
|
dev_cache_scan(1);
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ static int _read_array(struct pfilter *pf, struct config_tree *cft,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hash_insert(pf->devices, cv->v.str, data))
|
if (!dm_hash_insert(pf->devices, cv->v.str, data))
|
||||||
log_verbose("Couldn't add '%s' to filter ... ignoring",
|
log_verbose("Couldn't add '%s' to filter ... ignoring",
|
||||||
cv->v.str);
|
cv->v.str);
|
||||||
/* Populate dev_cache ourselves */
|
/* Populate dev_cache ourselves */
|
||||||
@@ -116,7 +117,7 @@ int persistent_filter_load(struct dev_filter *f)
|
|||||||
PF_BAD_DEVICE); */
|
PF_BAD_DEVICE); */
|
||||||
|
|
||||||
/* Did we find anything? */
|
/* Did we find anything? */
|
||||||
if (hash_get_num_entries(pf->devices)) {
|
if (dm_hash_get_num_entries(pf->devices)) {
|
||||||
/* We populated dev_cache ourselves */
|
/* We populated dev_cache ourselves */
|
||||||
dev_cache_scan(0);
|
dev_cache_scan(0);
|
||||||
r = 1;
|
r = 1;
|
||||||
@@ -134,11 +135,11 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
|
|||||||
{
|
{
|
||||||
void *d;
|
void *d;
|
||||||
int first = 1;
|
int first = 1;
|
||||||
struct hash_node *n;
|
struct dm_hash_node *n;
|
||||||
|
|
||||||
for (n = hash_get_first(pf->devices); n;
|
for (n = dm_hash_get_first(pf->devices); n;
|
||||||
n = hash_get_next(pf->devices, n)) {
|
n = dm_hash_get_next(pf->devices, n)) {
|
||||||
d = hash_get_data(pf->devices, n);
|
d = dm_hash_get_data(pf->devices, n);
|
||||||
|
|
||||||
if (d != data)
|
if (d != data)
|
||||||
continue;
|
continue;
|
||||||
@@ -150,7 +151,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
|
|||||||
first = 0;
|
first = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "\t\t\"%s\"", hash_get_key(pf->devices, n));
|
fprintf(fp, "\t\t\"%s\"", dm_hash_get_key(pf->devices, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first)
|
if (!first)
|
||||||
@@ -165,7 +166,7 @@ int persistent_filter_dump(struct dev_filter *f)
|
|||||||
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (!hash_get_num_entries(pf->devices)) {
|
if (!dm_hash_get_num_entries(pf->devices)) {
|
||||||
log_very_verbose("Internal persistent device cache empty "
|
log_very_verbose("Internal persistent device cache empty "
|
||||||
"- not writing to %s", pf->file);
|
"- not writing to %s", pf->file);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -200,36 +201,31 @@ int persistent_filter_dump(struct dev_filter *f)
|
|||||||
static int _lookup_p(struct dev_filter *f, struct device *dev)
|
static int _lookup_p(struct dev_filter *f, struct device *dev)
|
||||||
{
|
{
|
||||||
struct pfilter *pf = (struct pfilter *) f->private;
|
struct pfilter *pf = (struct pfilter *) f->private;
|
||||||
void *l = hash_lookup(pf->devices, dev_name(dev));
|
void *l = dm_hash_lookup(pf->devices, dev_name(dev));
|
||||||
struct str_list *sl;
|
struct str_list *sl;
|
||||||
struct list *ah;
|
|
||||||
|
|
||||||
if (!l) {
|
if (!l) {
|
||||||
l = pf->real->passes_filter(pf->real, dev) ?
|
l = pf->real->passes_filter(pf->real, dev) ?
|
||||||
PF_GOOD_DEVICE : PF_BAD_DEVICE;
|
PF_GOOD_DEVICE : PF_BAD_DEVICE;
|
||||||
|
|
||||||
list_iterate(ah, &dev->aliases) {
|
list_iterate_items(sl, &dev->aliases)
|
||||||
sl = list_item(ah, struct str_list);
|
dm_hash_insert(pf->devices, sl->str, l);
|
||||||
hash_insert(pf->devices, sl->str, l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l == PF_BAD_DEVICE) {
|
} else if (l == PF_BAD_DEVICE)
|
||||||
log_debug("%s: Skipping (cached)", dev_name(dev));
|
log_debug("%s: Skipping (cached)", dev_name(dev));
|
||||||
return 0;
|
|
||||||
} else
|
return (l == PF_BAD_DEVICE) ? 0 : 1;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _destroy(struct dev_filter *f)
|
static void _destroy(struct dev_filter *f)
|
||||||
{
|
{
|
||||||
struct pfilter *pf = (struct pfilter *) f->private;
|
struct pfilter *pf = (struct pfilter *) f->private;
|
||||||
|
|
||||||
hash_destroy(pf->devices);
|
dm_hash_destroy(pf->devices);
|
||||||
dbg_free(pf->file);
|
dm_free(pf->file);
|
||||||
pf->real->destroy(pf->real);
|
pf->real->destroy(pf->real);
|
||||||
dbg_free(pf);
|
dm_free(pf);
|
||||||
dbg_free(f);
|
dm_free(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
||||||
@@ -238,13 +234,13 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
|||||||
struct pfilter *pf;
|
struct pfilter *pf;
|
||||||
struct dev_filter *f = NULL;
|
struct dev_filter *f = NULL;
|
||||||
|
|
||||||
if (!(pf = dbg_malloc(sizeof(*pf)))) {
|
if (!(pf = dm_malloc(sizeof(*pf)))) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(pf, 0, sizeof(*pf));
|
memset(pf, 0, sizeof(*pf));
|
||||||
|
|
||||||
if (!(pf->file = dbg_malloc(strlen(file) + 1))) {
|
if (!(pf->file = dm_malloc(strlen(file) + 1))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -256,7 +252,7 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(f = dbg_malloc(sizeof(*f)))) {
|
if (!(f = dm_malloc(sizeof(*f)))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -268,10 +264,10 @@ struct dev_filter *persistent_filter_create(struct dev_filter *real,
|
|||||||
return f;
|
return f;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
dbg_free(pf->file);
|
dm_free(pf->file);
|
||||||
if (pf->devices)
|
if (pf->devices)
|
||||||
hash_destroy(pf->devices);
|
dm_hash_destroy(pf->devices);
|
||||||
dbg_free(pf);
|
dm_free(pf);
|
||||||
dbg_free(f);
|
dm_free(f);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,21 +14,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "filter-regex.h"
|
#include "filter-regex.h"
|
||||||
#include "matcher.h"
|
#include "matcher.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "bitset.h"
|
|
||||||
#include "list.h"
|
|
||||||
|
|
||||||
struct rfilter {
|
struct rfilter {
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
bitset_t accept;
|
dm_bitset_t accept;
|
||||||
struct matcher *engine;
|
struct matcher *engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int _extract_pattern(struct pool *mem, const char *pat,
|
static int _extract_pattern(struct dm_pool *mem, const char *pat,
|
||||||
char **regex, bitset_t accept, int ix)
|
char **regex, dm_bitset_t accept, int ix)
|
||||||
{
|
{
|
||||||
char sep, *r, *ptr;
|
char sep, *r, *ptr;
|
||||||
|
|
||||||
@@ -37,11 +34,11 @@ static int _extract_pattern(struct pool *mem, const char *pat,
|
|||||||
*/
|
*/
|
||||||
switch (*pat) {
|
switch (*pat) {
|
||||||
case 'a':
|
case 'a':
|
||||||
bit_set(accept, ix);
|
dm_bit_set(accept, ix);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
bit_clear(accept, ix);
|
dm_bit_clear(accept, ix);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -74,7 +71,7 @@ static int _extract_pattern(struct pool *mem, const char *pat,
|
|||||||
/*
|
/*
|
||||||
* copy the regex
|
* copy the regex
|
||||||
*/
|
*/
|
||||||
if (!(r = pool_strdup(mem, pat))) {
|
if (!(r = dm_pool_strdup(mem, pat))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -95,13 +92,13 @@ static int _extract_pattern(struct pool *mem, const char *pat,
|
|||||||
|
|
||||||
static int _build_matcher(struct rfilter *rf, struct config_value *val)
|
static int _build_matcher(struct rfilter *rf, struct config_value *val)
|
||||||
{
|
{
|
||||||
struct pool *scratch;
|
struct dm_pool *scratch;
|
||||||
struct config_value *v;
|
struct config_value *v;
|
||||||
char **regex;
|
char **regex;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
int i, r = 0;
|
int i, r = 0;
|
||||||
|
|
||||||
if (!(scratch = pool_create(1024))) {
|
if (!(scratch = dm_pool_create("filter matcher", 1024))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -122,7 +119,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
|
|||||||
/*
|
/*
|
||||||
* allocate space for them
|
* allocate space for them
|
||||||
*/
|
*/
|
||||||
if (!(regex = pool_alloc(scratch, sizeof(*regex) * count))) {
|
if (!(regex = dm_pool_alloc(scratch, sizeof(*regex) * count))) {
|
||||||
stack;
|
stack;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -130,7 +127,7 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
|
|||||||
/*
|
/*
|
||||||
* create the accept/reject bitset
|
* create the accept/reject bitset
|
||||||
*/
|
*/
|
||||||
rf->accept = bitset_create(rf->mem, count);
|
rf->accept = dm_bitset_create(rf->mem, count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fill the array back to front because we
|
* fill the array back to front because we
|
||||||
@@ -152,23 +149,21 @@ static int _build_matcher(struct rfilter *rf, struct config_value *val)
|
|||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pool_destroy(scratch);
|
dm_pool_destroy(scratch);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _accept_p(struct dev_filter *f, struct device *dev)
|
static int _accept_p(struct dev_filter *f, struct device *dev)
|
||||||
{
|
{
|
||||||
struct list *ah;
|
|
||||||
int m, first = 1, rejected = 0;
|
int m, first = 1, rejected = 0;
|
||||||
struct rfilter *rf = (struct rfilter *) f->private;
|
struct rfilter *rf = (struct rfilter *) f->private;
|
||||||
struct str_list *sl;
|
struct str_list *sl;
|
||||||
|
|
||||||
list_iterate(ah, &dev->aliases) {
|
list_iterate_items(sl, &dev->aliases) {
|
||||||
sl = list_item(ah, struct str_list);
|
|
||||||
m = matcher_run(rf->engine, sl->str);
|
m = matcher_run(rf->engine, sl->str);
|
||||||
|
|
||||||
if (m >= 0) {
|
if (m >= 0) {
|
||||||
if (bit(rf->accept, m)) {
|
if (dm_bit(rf->accept, m)) {
|
||||||
|
|
||||||
if (!first) {
|
if (!first) {
|
||||||
log_debug("%s: New preferred name",
|
log_debug("%s: New preferred name",
|
||||||
@@ -186,6 +181,9 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
|||||||
first = 0;
|
first = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rejected)
|
||||||
|
log_debug("%s: Skipping (regex)", dev_name(dev));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pass everything that doesn't match
|
* pass everything that doesn't match
|
||||||
* anything.
|
* anything.
|
||||||
@@ -196,12 +194,12 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
|||||||
static void _destroy(struct dev_filter *f)
|
static void _destroy(struct dev_filter *f)
|
||||||
{
|
{
|
||||||
struct rfilter *rf = (struct rfilter *) f->private;
|
struct rfilter *rf = (struct rfilter *) f->private;
|
||||||
pool_destroy(rf->mem);
|
dm_pool_destroy(rf->mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_filter *regex_filter_create(struct config_value *patterns)
|
struct dev_filter *regex_filter_create(struct config_value *patterns)
|
||||||
{
|
{
|
||||||
struct pool *mem = pool_create(10 * 1024);
|
struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024);
|
||||||
struct rfilter *rf;
|
struct rfilter *rf;
|
||||||
struct dev_filter *f;
|
struct dev_filter *f;
|
||||||
|
|
||||||
@@ -210,7 +208,7 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(rf = pool_alloc(mem, sizeof(*rf)))) {
|
if (!(rf = dm_pool_alloc(mem, sizeof(*rf)))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -222,7 +220,7 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
|
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -233,6 +231,6 @@ struct dev_filter *regex_filter_create(struct config_value *patterns)
|
|||||||
return f;
|
return f;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "filter-sysfs.h"
|
#include "filter-sysfs.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
#include "pool.h"
|
|
||||||
|
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
|
|
||||||
@@ -69,21 +68,21 @@ struct entry {
|
|||||||
|
|
||||||
#define SET_BUCKETS 64
|
#define SET_BUCKETS 64
|
||||||
struct dev_set {
|
struct dev_set {
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
const char *sys_block;
|
const char *sys_block;
|
||||||
int initialised;
|
int initialised;
|
||||||
struct entry *slots[SET_BUCKETS];
|
struct entry *slots[SET_BUCKETS];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dev_set *_dev_set_create(struct pool *mem, const char *sys_block)
|
static struct dev_set *_dev_set_create(struct dm_pool *mem, const char *sys_block)
|
||||||
{
|
{
|
||||||
struct dev_set *ds;
|
struct dev_set *ds;
|
||||||
|
|
||||||
if (!(ds = pool_zalloc(mem, sizeof(*ds))))
|
if (!(ds = dm_pool_zalloc(mem, sizeof(*ds))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ds->mem = mem;
|
ds->mem = mem;
|
||||||
ds->sys_block = pool_strdup(mem, sys_block);
|
ds->sys_block = dm_pool_strdup(mem, sys_block);
|
||||||
ds->initialised = 0;
|
ds->initialised = 0;
|
||||||
|
|
||||||
return ds;
|
return ds;
|
||||||
@@ -102,7 +101,7 @@ static int _set_insert(struct dev_set *ds, dev_t dev)
|
|||||||
struct entry *e;
|
struct entry *e;
|
||||||
unsigned h = _hash_dev(dev);
|
unsigned h = _hash_dev(dev);
|
||||||
|
|
||||||
if (!(e = pool_alloc(ds->mem, sizeof(*e))))
|
if (!(e = dm_pool_alloc(ds->mem, sizeof(*e))))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
e->next = ds->slots[h];
|
e->next = ds->slots[h];
|
||||||
@@ -169,8 +168,10 @@ static int _read_devs(struct dev_set *ds, const char *dir)
|
|||||||
{
|
{
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
DIR *dr;
|
DIR *dr;
|
||||||
|
unsigned char dtype;
|
||||||
|
struct stat info;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
dev_t dev;
|
dev_t dev = { 0 };
|
||||||
int r = 1;
|
int r = 1;
|
||||||
|
|
||||||
if (!(dr = opendir(dir))) {
|
if (!(dr = opendir(dir))) {
|
||||||
@@ -189,19 +190,31 @@ static int _read_devs(struct dev_set *ds, const char *dir)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->d_type == DT_DIR) {
|
dtype = d->d_type;
|
||||||
|
|
||||||
|
if (dtype == DT_UNKNOWN) {
|
||||||
|
if (lstat(path, &info) >= 0) {
|
||||||
|
if (S_ISLNK(info.st_mode))
|
||||||
|
dtype = DT_LNK;
|
||||||
|
else if (S_ISDIR(info.st_mode))
|
||||||
|
dtype = DT_DIR;
|
||||||
|
else if (S_ISREG(info.st_mode))
|
||||||
|
dtype = DT_REG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dtype == DT_DIR) {
|
||||||
if (!_read_devs(ds, path)) {
|
if (!_read_devs(ds, path)) {
|
||||||
r = 0;
|
r = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((d->d_type == DT_REG && !strcmp(d->d_name, "dev")))
|
if ((dtype == DT_REG && !strcmp(d->d_name, "dev")))
|
||||||
if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
|
if (!_read_dev(path, &dev) || !_set_insert(ds, dev)) {
|
||||||
r = 0;
|
r = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closedir(dr))
|
if (closedir(dr))
|
||||||
@@ -234,26 +247,30 @@ static int _accept_p(struct dev_filter *f, struct device *dev)
|
|||||||
if (ds->initialised != 1)
|
if (ds->initialised != 1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return _set_lookup(ds, dev->dev);
|
if (!_set_lookup(ds, dev->dev)) {
|
||||||
|
log_debug("%s: Skipping (sysfs)", dev_name(dev));
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _destroy(struct dev_filter *f)
|
static void _destroy(struct dev_filter *f)
|
||||||
{
|
{
|
||||||
struct dev_set *ds = (struct dev_set *) f->private;
|
struct dev_set *ds = (struct dev_set *) f->private;
|
||||||
pool_destroy(ds->mem);
|
dm_pool_destroy(ds->mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_filter *sysfs_filter_create(const char *proc)
|
struct dev_filter *sysfs_filter_create(const char *proc)
|
||||||
{
|
{
|
||||||
char sys_block[PATH_MAX];
|
char sys_block[PATH_MAX];
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
struct dev_set *ds;
|
struct dev_set *ds;
|
||||||
struct dev_filter *f;
|
struct dev_filter *f;
|
||||||
|
|
||||||
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
|
if (!_locate_sysfs_blocks(proc, sys_block, sizeof(sys_block)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!(mem = pool_create(256))) {
|
if (!(mem = dm_pool_create("sysfs", 256))) {
|
||||||
log_error("sysfs pool creation failed");
|
log_error("sysfs pool creation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -263,7 +280,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(f = pool_zalloc(mem, sizeof(*f)))) {
|
if (!(f = dm_pool_zalloc(mem, sizeof(*f)))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -274,7 +291,7 @@ struct dev_filter *sysfs_filter_create(const char *proc)
|
|||||||
return f;
|
return f;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "metadata.h"
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -25,7 +26,10 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#define NUMBER_OF_MAJORS 256
|
#define NUMBER_OF_MAJORS 4096
|
||||||
|
|
||||||
|
/* 0 means LVM won't use this major number. */
|
||||||
|
static int _max_partitions_by_major[NUMBER_OF_MAJORS];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -39,12 +43,19 @@ int md_major(void)
|
|||||||
return _md_major;
|
return _md_major;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This list can be supplemented with devices/types in the config file */
|
/*
|
||||||
|
* Devices are only checked for partition tables if their minor number
|
||||||
|
* is a multiple of the number corresponding to their type below
|
||||||
|
* i.e. this gives the granularity of whole-device minor numbers.
|
||||||
|
* Use 1 if the device is not partitionable.
|
||||||
|
*
|
||||||
|
* The list can be supplemented with devices/types in the config file.
|
||||||
|
*/
|
||||||
static const device_info_t device_info[] = {
|
static const device_info_t device_info[] = {
|
||||||
{"ide", 16}, /* IDE disk */
|
{"ide", 64}, /* IDE disk */
|
||||||
{"sd", 16}, /* SCSI disk */
|
{"sd", 16}, /* SCSI disk */
|
||||||
{"md", 16}, /* Multiple Disk driver (SoftRAID) */
|
{"md", 1}, /* Multiple Disk driver (SoftRAID) */
|
||||||
{"loop", 16}, /* Loop device */
|
{"loop", 1}, /* Loop device */
|
||||||
{"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
|
{"dasd", 4}, /* DASD disk (IBM S/390, zSeries) */
|
||||||
{"dac960", 8}, /* DAC960 */
|
{"dac960", 8}, /* DAC960 */
|
||||||
{"nbd", 16}, /* Network Block Device */
|
{"nbd", 16}, /* Network Block Device */
|
||||||
@@ -53,37 +64,64 @@ static const device_info_t device_info[] = {
|
|||||||
{"ubd", 16}, /* User-mode virtual block device */
|
{"ubd", 16}, /* User-mode virtual block device */
|
||||||
{"ataraid", 16}, /* ATA Raid */
|
{"ataraid", 16}, /* ATA Raid */
|
||||||
{"drbd", 16}, /* Distributed Replicated Block Device */
|
{"drbd", 16}, /* Distributed Replicated Block Device */
|
||||||
|
{"emcpower", 16}, /* EMC Powerpath */
|
||||||
{"power2", 16}, /* EMC Powerpath */
|
{"power2", 16}, /* EMC Powerpath */
|
||||||
{"i2o_block", 16}, /* i2o Block Disk */
|
{"i2o_block", 16}, /* i2o Block Disk */
|
||||||
|
{"iseries/vd", 8}, /* iSeries disks */
|
||||||
|
{"gnbd", 1}, /* Network block device */
|
||||||
|
{"ramdisk", 1}, /* RAM disk */
|
||||||
|
{"aoe", 16}, /* ATA over Ethernet */
|
||||||
|
{"device-mapper", 1}, /* Other mapped devices */
|
||||||
|
{"xvd", 16}, /* Xen virtual block device */
|
||||||
{NULL, 0}
|
{NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int _passes_lvm_type_device_filter(struct dev_filter *f,
|
static int _passes_lvm_type_device_filter(struct dev_filter *f,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
int fd;
|
|
||||||
const char *name = dev_name(dev);
|
const char *name = dev_name(dev);
|
||||||
|
int ret = 0;
|
||||||
|
uint64_t size;
|
||||||
|
|
||||||
/* Is this a recognised device type? */
|
/* Is this a recognised device type? */
|
||||||
if (!(((int *) f->private)[MAJOR(dev->dev)])) {
|
if (!_max_partitions_by_major[MAJOR(dev->dev)]) {
|
||||||
log_debug("%s: Skipping: Unrecognised LVM device type %"
|
log_debug("%s: Skipping: Unrecognised LVM device type %"
|
||||||
PRIu64, name, (uint64_t) MAJOR(dev->dev));
|
PRIu64, name, (uint64_t) MAJOR(dev->dev));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check it's accessible */
|
/* Check it's accessible */
|
||||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
|
||||||
log_debug("%s: Skipping: open failed: %s", name,
|
log_debug("%s: Skipping: open failed", name);
|
||||||
strerror(errno));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check it's not too small */
|
||||||
|
if (!dev_get_size(dev, &size)) {
|
||||||
|
log_debug("%s: Skipping: dev_get_size failed", name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
close(fd);
|
if (size < PV_MIN_SIZE) {
|
||||||
|
log_debug("%s: Skipping: Too small to hold a PV", name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
if (is_partitioned_dev(dev)) {
|
||||||
|
log_debug("%s: Skipping: Partition table signature found",
|
||||||
|
name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
dev_close(dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
static int _scan_proc_dev(const char *proc, const struct config_node *cn)
|
||||||
{
|
{
|
||||||
char line[80];
|
char line[80];
|
||||||
char proc_devices[PATH_MAX];
|
char proc_devices[PATH_MAX];
|
||||||
@@ -93,35 +131,31 @@ static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
|||||||
int blocksection = 0;
|
int blocksection = 0;
|
||||||
size_t dev_len = 0;
|
size_t dev_len = 0;
|
||||||
struct config_value *cv;
|
struct config_value *cv;
|
||||||
int *max_partitions_by_major;
|
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (!(max_partitions_by_major =
|
|
||||||
dbg_malloc(sizeof(int) * NUMBER_OF_MAJORS))) {
|
|
||||||
log_error("Filter failed to allocate max_partitions_by_major");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*proc) {
|
if (!*proc) {
|
||||||
log_verbose("No proc filesystem found: using all block device "
|
log_verbose("No proc filesystem found: using all block device "
|
||||||
"types");
|
"types");
|
||||||
for (i = 0; i < NUMBER_OF_MAJORS; i++)
|
for (i = 0; i < NUMBER_OF_MAJORS; i++)
|
||||||
max_partitions_by_major[i] = 1;
|
_max_partitions_by_major[i] = 1;
|
||||||
return max_partitions_by_major;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* All types unrecognised initially */
|
||||||
|
memset(_max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
|
||||||
|
|
||||||
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
|
if (lvm_snprintf(proc_devices, sizeof(proc_devices),
|
||||||
"%s/devices", proc) < 0) {
|
"%s/devices", proc) < 0) {
|
||||||
log_error("Failed to create /proc/devices string");
|
log_error("Failed to create /proc/devices string");
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pd = fopen(proc_devices, "r"))) {
|
if (!(pd = fopen(proc_devices, "r"))) {
|
||||||
log_sys_error("fopen", proc_devices);
|
log_sys_error("fopen", proc_devices);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(max_partitions_by_major, 0, sizeof(int) * NUMBER_OF_MAJORS);
|
|
||||||
while (fgets(line, 80, pd) != NULL) {
|
while (fgets(line, 80, pd) != NULL) {
|
||||||
i = 0;
|
i = 0;
|
||||||
while (line[i] == ' ' && line[i] != '\0')
|
while (line[i] == ' ' && line[i] != '\0')
|
||||||
@@ -156,13 +190,13 @@ static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
|||||||
if (dev_len <= strlen(line + i) &&
|
if (dev_len <= strlen(line + i) &&
|
||||||
!strncmp(device_info[j].name, line + i, dev_len) &&
|
!strncmp(device_info[j].name, line + i, dev_len) &&
|
||||||
(line_maj < NUMBER_OF_MAJORS)) {
|
(line_maj < NUMBER_OF_MAJORS)) {
|
||||||
max_partitions_by_major[line_maj] =
|
_max_partitions_by_major[line_maj] =
|
||||||
device_info[j].max_partitions;
|
device_info[j].max_partitions;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_partitions_by_major[line_maj] || !cn)
|
if (!cn)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Check devices/types for local variations */
|
/* Check devices/types for local variations */
|
||||||
@@ -170,7 +204,7 @@ static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
|||||||
if (cv->type != CFG_STRING) {
|
if (cv->type != CFG_STRING) {
|
||||||
log_error("Expecting string in devices/types "
|
log_error("Expecting string in devices/types "
|
||||||
"in config file");
|
"in config file");
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
dev_len = strlen(cv->v.str);
|
dev_len = strlen(cv->v.str);
|
||||||
name = cv->v.str;
|
name = cv->v.str;
|
||||||
@@ -179,24 +213,29 @@ static int *_scan_proc_dev(const char *proc, const struct config_node *cn)
|
|||||||
log_error("Max partition count missing for %s "
|
log_error("Max partition count missing for %s "
|
||||||
"in devices/types in config file",
|
"in devices/types in config file",
|
||||||
name);
|
name);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!cv->v.i) {
|
if (!cv->v.i) {
|
||||||
log_error("Zero partition count invalid for "
|
log_error("Zero partition count invalid for "
|
||||||
"%s in devices/types in config file",
|
"%s in devices/types in config file",
|
||||||
name);
|
name);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
if (dev_len <= strlen(line + i) &&
|
if (dev_len <= strlen(line + i) &&
|
||||||
!strncmp(name, line + i, dev_len) &&
|
!strncmp(name, line + i, dev_len) &&
|
||||||
(line_maj < NUMBER_OF_MAJORS)) {
|
(line_maj < NUMBER_OF_MAJORS)) {
|
||||||
max_partitions_by_major[line_maj] = cv->v.i;
|
_max_partitions_by_major[line_maj] = cv->v.i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(pd);
|
fclose(pd);
|
||||||
return max_partitions_by_major;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int max_partitions(int major)
|
||||||
|
{
|
||||||
|
return _max_partitions_by_major[major];
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dev_filter *lvm_type_filter_create(const char *proc,
|
struct dev_filter *lvm_type_filter_create(const char *proc,
|
||||||
@@ -204,15 +243,16 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
|||||||
{
|
{
|
||||||
struct dev_filter *f;
|
struct dev_filter *f;
|
||||||
|
|
||||||
if (!(f = dbg_malloc(sizeof(struct dev_filter)))) {
|
if (!(f = dm_malloc(sizeof(struct dev_filter)))) {
|
||||||
log_error("LVM type filter allocation failed");
|
log_error("LVM type filter allocation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->passes_filter = _passes_lvm_type_device_filter;
|
f->passes_filter = _passes_lvm_type_device_filter;
|
||||||
f->destroy = lvm_type_filter_destroy;
|
f->destroy = lvm_type_filter_destroy;
|
||||||
|
f->private = NULL;
|
||||||
|
|
||||||
if (!(f->private = _scan_proc_dev(proc, cn))) {
|
if (!_scan_proc_dev(proc, cn)) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -222,7 +262,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
|||||||
|
|
||||||
void lvm_type_filter_destroy(struct dev_filter *f)
|
void lvm_type_filter_destroy(struct dev_filter *f)
|
||||||
{
|
{
|
||||||
dbg_free(f->private);
|
dm_free(f);
|
||||||
dbg_free(f);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,9 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
# include <linux/kdev_t.h>
|
# define MAJOR(dev) ((dev & 0xfff00) >> 8)
|
||||||
|
# define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00))
|
||||||
|
# define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
|
||||||
#else
|
#else
|
||||||
# define MAJOR(x) major((x))
|
# define MAJOR(x) major((x))
|
||||||
# define MINOR(x) minor((x))
|
# define MINOR(x) minor((x))
|
||||||
@@ -34,5 +36,6 @@ struct dev_filter *lvm_type_filter_create(const char *proc,
|
|||||||
void lvm_type_filter_destroy(struct dev_filter *f);
|
void lvm_type_filter_destroy(struct dev_filter *f);
|
||||||
|
|
||||||
int md_major(void);
|
int md_major(void);
|
||||||
|
int max_partitions(int major);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ SOURCES =\
|
|||||||
|
|
||||||
LIB_SHARED = liblvm2format1.so
|
LIB_SHARED = liblvm2format1.so
|
||||||
|
|
||||||
include ../../make.tmpl
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
.PHONY: install
|
|
||||||
|
|
||||||
install: liblvm2format1.so
|
install: liblvm2format1.so
|
||||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "disk-rep.h"
|
#include "disk-rep.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "xlate.h"
|
#include "xlate.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
@@ -255,7 +254,7 @@ static int _read_uuids(struct disk_list *data)
|
|||||||
if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
|
if (!dev_read(data->dev, pos, sizeof(buffer), buffer))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
if (!(ul = pool_alloc(data->mem, sizeof(*ul))))
|
if (!(ul = dm_pool_alloc(data->mem, sizeof(*ul))))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
memcpy(ul->uuid, buffer, NAME_LEN);
|
memcpy(ul->uuid, buffer, NAME_LEN);
|
||||||
@@ -284,7 +283,7 @@ static int _read_lvs(struct disk_list *data)
|
|||||||
|
|
||||||
for (i = 0; (i < vgd->lv_max) && (read < vgd->lv_cur); i++) {
|
for (i = 0; (i < vgd->lv_max) && (read < vgd->lv_cur); i++) {
|
||||||
pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
|
pos = data->pvd.lv_on_disk.base + (i * sizeof(struct lv_disk));
|
||||||
ll = pool_alloc(data->mem, sizeof(*ll));
|
ll = dm_pool_alloc(data->mem, sizeof(*ll));
|
||||||
|
|
||||||
if (!ll)
|
if (!ll)
|
||||||
fail;
|
fail;
|
||||||
@@ -305,7 +304,7 @@ static int _read_lvs(struct disk_list *data)
|
|||||||
static int _read_extents(struct disk_list *data)
|
static int _read_extents(struct disk_list *data)
|
||||||
{
|
{
|
||||||
size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
|
size_t len = sizeof(struct pe_disk) * data->pvd.pe_total;
|
||||||
struct pe_disk *extents = pool_alloc(data->mem, len);
|
struct pe_disk *extents = dm_pool_alloc(data->mem, len);
|
||||||
uint64_t pos = data->pvd.pe_on_disk.base;
|
uint64_t pos = data->pvd.pe_on_disk.base;
|
||||||
|
|
||||||
if (!extents)
|
if (!extents)
|
||||||
@@ -321,10 +320,10 @@ static int _read_extents(struct disk_list *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct disk_list *__read_disk(const struct format_type *fmt,
|
static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||||
struct device *dev, struct pool *mem,
|
struct device *dev, struct dm_pool *mem,
|
||||||
const char *vg_name)
|
const char *vg_name)
|
||||||
{
|
{
|
||||||
struct disk_list *dl = pool_alloc(mem, sizeof(*dl));
|
struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
|
||||||
const char *name = dev_name(dev);
|
const char *name = dev_name(dev);
|
||||||
struct lvmcache_info *info;
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
@@ -400,12 +399,12 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
|||||||
return dl;
|
return dl;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
pool_free(dl->mem, dl);
|
dm_pool_free(dl->mem, dl);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
|
struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
|
||||||
struct pool *mem, const char *vg_name)
|
struct dm_pool *mem, const char *vg_name)
|
||||||
{
|
{
|
||||||
struct disk_list *r;
|
struct disk_list *r;
|
||||||
|
|
||||||
@@ -424,11 +423,11 @@ struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
|
|||||||
|
|
||||||
static void _add_pv_to_list(struct list *head, struct disk_list *data)
|
static void _add_pv_to_list(struct list *head, struct disk_list *data)
|
||||||
{
|
{
|
||||||
struct list *pvdh;
|
|
||||||
struct pv_disk *pvd;
|
struct pv_disk *pvd;
|
||||||
|
struct disk_list *diskl;
|
||||||
|
|
||||||
list_iterate(pvdh, head) {
|
list_iterate_items(diskl, head) {
|
||||||
pvd = &list_item(pvdh, struct disk_list)->pvd;
|
pvd = &diskl->pvd;
|
||||||
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
|
if (!strncmp(data->pvd.pv_uuid, pvd->pv_uuid,
|
||||||
sizeof(pvd->pv_uuid))) {
|
sizeof(pvd->pv_uuid))) {
|
||||||
if (MAJOR(data->dev->dev) != md_major()) {
|
if (MAJOR(data->dev->dev) != md_major()) {
|
||||||
@@ -439,7 +438,7 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
|
|||||||
}
|
}
|
||||||
log_very_verbose("Duplicate PV %s - using md %s",
|
log_very_verbose("Duplicate PV %s - using md %s",
|
||||||
pvd->pv_uuid, dev_name(data->dev));
|
pvd->pv_uuid, dev_name(data->dev));
|
||||||
list_del(pvdh);
|
list_del(&diskl->list);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -452,20 +451,20 @@ static void _add_pv_to_list(struct list *head, struct disk_list *data)
|
|||||||
* so we can free off all the memory if something goes wrong.
|
* so we can free off all the memory if something goes wrong.
|
||||||
*/
|
*/
|
||||||
int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
||||||
struct dev_filter *filter, struct pool *mem,
|
struct dev_filter *filter, struct dm_pool *mem,
|
||||||
struct list *head)
|
struct list *head)
|
||||||
{
|
{
|
||||||
struct dev_iter *iter;
|
struct dev_iter *iter;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct disk_list *data = NULL;
|
struct disk_list *data = NULL;
|
||||||
struct list *vgih;
|
|
||||||
struct lvmcache_vginfo *vginfo;
|
struct lvmcache_vginfo *vginfo;
|
||||||
|
struct lvmcache_info *info;
|
||||||
|
|
||||||
/* Fast path if we already saw this VG and cached the list of PVs */
|
/* Fast path if we already saw this VG and cached the list of PVs */
|
||||||
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
if (vg_name && (vginfo = vginfo_from_vgname(vg_name)) &&
|
||||||
vginfo->infos.n) {
|
vginfo->infos.n) {
|
||||||
list_iterate(vgih, &vginfo->infos) {
|
list_iterate_items(info, &vginfo->infos) {
|
||||||
dev = list_item(vgih, struct lvmcache_info)->dev;
|
dev = info->dev;
|
||||||
if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
|
if (dev && !(data = read_disk(fmt, dev, mem, vg_name)))
|
||||||
break;
|
break;
|
||||||
_add_pv_to_list(head, data);
|
_add_pv_to_list(head, data);
|
||||||
@@ -482,7 +481,7 @@ int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
|||||||
/* vgcache_del(vg_name); */
|
/* vgcache_del(vg_name); */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(iter = dev_iter_create(filter))) {
|
if (!(iter = dev_iter_create(filter, 1))) {
|
||||||
log_error("read_pvs_in_vg: dev_iter_create failed");
|
log_error("read_pvs_in_vg: dev_iter_create failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -506,6 +505,9 @@ static int _write_vgd(struct disk_list *data)
|
|||||||
struct vg_disk *vgd = &data->vgd;
|
struct vg_disk *vgd = &data->vgd;
|
||||||
uint64_t pos = data->pvd.vg_on_disk.base;
|
uint64_t pos = data->pvd.vg_on_disk.base;
|
||||||
|
|
||||||
|
log_debug("Writing %s VG metadata to %s at %" PRIu64 " len %" PRIsize_t,
|
||||||
|
data->pvd.vg_name, dev_name(data->dev), pos, sizeof(*vgd));
|
||||||
|
|
||||||
_xlate_vgd(vgd);
|
_xlate_vgd(vgd);
|
||||||
if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
|
if (!dev_write(data->dev, pos, sizeof(*vgd), vgd))
|
||||||
fail;
|
fail;
|
||||||
@@ -518,18 +520,20 @@ static int _write_vgd(struct disk_list *data)
|
|||||||
static int _write_uuids(struct disk_list *data)
|
static int _write_uuids(struct disk_list *data)
|
||||||
{
|
{
|
||||||
struct uuid_list *ul;
|
struct uuid_list *ul;
|
||||||
struct list *uh;
|
|
||||||
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
|
uint64_t pos = data->pvd.pv_uuidlist_on_disk.base;
|
||||||
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
|
uint64_t end = pos + data->pvd.pv_uuidlist_on_disk.size;
|
||||||
|
|
||||||
list_iterate(uh, &data->uuids) {
|
list_iterate_items(ul, &data->uuids) {
|
||||||
if (pos >= end) {
|
if (pos >= end) {
|
||||||
log_error("Too many uuids to fit on %s",
|
log_error("Too many uuids to fit on %s",
|
||||||
dev_name(data->dev));
|
dev_name(data->dev));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul = list_item(uh, struct uuid_list);
|
log_debug("Writing %s uuidlist to %s at %" PRIu64 " len %d",
|
||||||
|
data->pvd.vg_name, dev_name(data->dev),
|
||||||
|
pos, NAME_LEN);
|
||||||
|
|
||||||
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
|
if (!dev_write(data->dev, pos, NAME_LEN, ul->uuid))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
@@ -541,6 +545,10 @@ static int _write_uuids(struct disk_list *data)
|
|||||||
|
|
||||||
static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
||||||
{
|
{
|
||||||
|
log_debug("Writing %s LV %s metadata to %s at %" PRIu64 " len %"
|
||||||
|
PRIsize_t, disk->vg_name, disk->lv_name, dev_name(dev),
|
||||||
|
pos, sizeof(*disk));
|
||||||
|
|
||||||
_xlate_lvd(disk);
|
_xlate_lvd(disk);
|
||||||
if (!dev_write(dev, pos, sizeof(*disk), disk))
|
if (!dev_write(dev, pos, sizeof(*disk), disk))
|
||||||
fail;
|
fail;
|
||||||
@@ -552,7 +560,7 @@ static int _write_lvd(struct device *dev, uint64_t pos, struct lv_disk *disk)
|
|||||||
|
|
||||||
static int _write_lvs(struct disk_list *data)
|
static int _write_lvs(struct disk_list *data)
|
||||||
{
|
{
|
||||||
struct list *lvh;
|
struct lvd_list *ll;
|
||||||
uint64_t pos, offset;
|
uint64_t pos, offset;
|
||||||
|
|
||||||
pos = data->pvd.lv_on_disk.base;
|
pos = data->pvd.lv_on_disk.base;
|
||||||
@@ -563,9 +571,7 @@ static int _write_lvs(struct disk_list *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_iterate(lvh, &data->lvds) {
|
list_iterate_items(ll, &data->lvds) {
|
||||||
struct lvd_list *ll = list_item(lvh, struct lvd_list);
|
|
||||||
|
|
||||||
offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
|
offset = sizeof(struct lv_disk) * ll->lvd.lv_number;
|
||||||
if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
|
if (offset + sizeof(struct lv_disk) > data->pvd.lv_on_disk.size) {
|
||||||
log_error("lv_number %d too large", ll->lvd.lv_number);
|
log_error("lv_number %d too large", ll->lvd.lv_number);
|
||||||
@@ -585,6 +591,10 @@ static int _write_extents(struct disk_list *data)
|
|||||||
struct pe_disk *extents = data->extents;
|
struct pe_disk *extents = data->extents;
|
||||||
uint64_t pos = data->pvd.pe_on_disk.base;
|
uint64_t pos = data->pvd.pe_on_disk.base;
|
||||||
|
|
||||||
|
log_debug("Writing %s extents metadata to %s at %" PRIu64 " len %"
|
||||||
|
PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
|
||||||
|
pos, len);
|
||||||
|
|
||||||
_xlate_extents(extents, data->pvd.pe_total);
|
_xlate_extents(extents, data->pvd.pe_total);
|
||||||
if (!dev_write(data->dev, pos, len, extents))
|
if (!dev_write(data->dev, pos, len, extents))
|
||||||
fail;
|
fail;
|
||||||
@@ -608,7 +618,7 @@ static int _write_pvd(struct disk_list *data)
|
|||||||
/* Make sure that the gap between the PV structure and
|
/* Make sure that the gap between the PV structure and
|
||||||
the next one is zeroed in order to make non LVM tools
|
the next one is zeroed in order to make non LVM tools
|
||||||
happy (idea from AED) */
|
happy (idea from AED) */
|
||||||
buf = dbg_malloc(size);
|
buf = dm_malloc(size);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
log_err("Couldn't allocate temporary PV buffer.");
|
log_err("Couldn't allocate temporary PV buffer.");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -617,13 +627,17 @@ static int _write_pvd(struct disk_list *data)
|
|||||||
memset(buf, 0, size);
|
memset(buf, 0, size);
|
||||||
memcpy(buf, &data->pvd, sizeof(struct pv_disk));
|
memcpy(buf, &data->pvd, sizeof(struct pv_disk));
|
||||||
|
|
||||||
|
log_debug("Writing %s PV metadata to %s at %" PRIu64 " len %"
|
||||||
|
PRIsize_t, data->pvd.vg_name, dev_name(data->dev),
|
||||||
|
pos, size);
|
||||||
|
|
||||||
_xlate_pvd((struct pv_disk *) buf);
|
_xlate_pvd((struct pv_disk *) buf);
|
||||||
if (!dev_write(data->dev, pos, size, buf)) {
|
if (!dev_write(data->dev, pos, size, buf)) {
|
||||||
dbg_free(buf);
|
dm_free(buf);
|
||||||
fail;
|
fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg_free(buf);
|
dm_free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,11 +718,9 @@ static int _write_all_pvd(const struct format_type *fmt, struct disk_list *data)
|
|||||||
*/
|
*/
|
||||||
int write_disks(const struct format_type *fmt, struct list *pvs)
|
int write_disks(const struct format_type *fmt, struct list *pvs)
|
||||||
{
|
{
|
||||||
struct list *pvh;
|
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
|
|
||||||
list_iterate(pvh, pvs) {
|
list_iterate_items(dl, pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
|
||||||
if (!(_write_all_pvd(fmt, dl)))
|
if (!(_write_all_pvd(fmt, dl)))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#include "lvm-types.h"
|
#include "lvm-types.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
|
|
||||||
#define MAX_PV 256
|
#define MAX_PV 256
|
||||||
@@ -159,7 +158,7 @@ struct lvd_list {
|
|||||||
|
|
||||||
struct disk_list {
|
struct disk_list {
|
||||||
struct list list;
|
struct list list;
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
struct pv_disk pvd;
|
struct pv_disk pvd;
|
||||||
@@ -191,11 +190,11 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
|
struct disk_list *read_disk(const struct format_type *fmt, struct device *dev,
|
||||||
struct pool *mem, const char *vg_name);
|
struct dm_pool *mem, const char *vg_name);
|
||||||
|
|
||||||
int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
int read_pvs_in_vg(const struct format_type *fmt, const char *vg_name,
|
||||||
struct dev_filter *filter,
|
struct dev_filter *filter,
|
||||||
struct pool *mem, struct list *results);
|
struct dm_pool *mem, struct list *results);
|
||||||
|
|
||||||
int write_disks(const struct format_type *fmt, struct list *pvds);
|
int write_disks(const struct format_type *fmt, struct list *pvds);
|
||||||
|
|
||||||
@@ -203,33 +202,33 @@ int write_disks(const struct format_type *fmt, struct list *pvds);
|
|||||||
* Functions to translate to between disk and in
|
* Functions to translate to between disk and in
|
||||||
* core structures.
|
* core structures.
|
||||||
*/
|
*/
|
||||||
int import_pv(struct pool *mem, struct device *dev,
|
int import_pv(struct dm_pool *mem, struct device *dev,
|
||||||
struct volume_group *vg,
|
struct volume_group *vg,
|
||||||
struct physical_volume *pv, struct pv_disk *pvd);
|
struct physical_volume *pv, struct pv_disk *pvd);
|
||||||
int export_pv(struct cmd_context *cmd, struct pool *mem,
|
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
|
||||||
struct volume_group *vg,
|
struct volume_group *vg,
|
||||||
struct pv_disk *pvd, struct physical_volume *pv);
|
struct pv_disk *pvd, struct physical_volume *pv);
|
||||||
|
|
||||||
int import_vg(struct pool *mem,
|
int import_vg(struct dm_pool *mem,
|
||||||
struct volume_group *vg, struct disk_list *dl, int partial);
|
struct volume_group *vg, struct disk_list *dl, int partial);
|
||||||
int export_vg(struct vg_disk *vgd, struct volume_group *vg);
|
int export_vg(struct vg_disk *vgd, struct volume_group *vg);
|
||||||
|
|
||||||
int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
|
int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lvd);
|
||||||
|
|
||||||
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
||||||
struct list *pvds);
|
struct list *pvds);
|
||||||
int export_extents(struct disk_list *dl, uint32_t lv_num,
|
int export_extents(struct disk_list *dl, uint32_t lv_num,
|
||||||
struct logical_volume *lv, struct physical_volume *pv);
|
struct logical_volume *lv, struct physical_volume *pv);
|
||||||
|
|
||||||
int import_pvs(const struct format_type *fmt, struct pool *mem,
|
int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
|
||||||
struct volume_group *vg,
|
struct volume_group *vg,
|
||||||
struct list *pvds, struct list *results, int *count);
|
struct list *pvds, struct list *results, int *count);
|
||||||
|
|
||||||
int import_lvs(struct pool *mem, struct volume_group *vg, struct list *pvds);
|
int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds);
|
||||||
int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
||||||
struct physical_volume *pv, const char *dev_dir);
|
struct physical_volume *pv, const char *dev_dir);
|
||||||
|
|
||||||
int import_snapshots(struct pool *mem, struct volume_group *vg,
|
int import_snapshots(struct dm_pool *mem, struct volume_group *vg,
|
||||||
struct list *pvds);
|
struct list *pvds);
|
||||||
|
|
||||||
int export_uuids(struct disk_list *dl, struct volume_group *vg);
|
int export_uuids(struct disk_list *dl, struct volume_group *vg);
|
||||||
|
|||||||
@@ -15,15 +15,13 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "disk-rep.h"
|
#include "disk-rep.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "hash.h"
|
|
||||||
#include "limits.h"
|
#include "limits.h"
|
||||||
#include "list.h"
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
#include "lvm1-label.h"
|
#include "lvm1-label.h"
|
||||||
#include "format1.h"
|
#include "format1.h"
|
||||||
|
#include "segtype.h"
|
||||||
|
|
||||||
#define FMT_LVM1_NAME "lvm1"
|
#define FMT_LVM1_NAME "lvm1"
|
||||||
|
|
||||||
@@ -45,9 +43,7 @@ static int _check_vgs(struct list *pvs, int *partial)
|
|||||||
* This means an active VG won't be affected if disks are inserted
|
* This means an active VG won't be affected if disks are inserted
|
||||||
* bearing an exported VG with the same name.
|
* bearing an exported VG with the same name.
|
||||||
*/
|
*/
|
||||||
list_iterate(pvh, pvs) {
|
list_iterate_items(dl, pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
|
||||||
|
|
||||||
if (first_time) {
|
if (first_time) {
|
||||||
exported = dl->pvd.pv_status & VG_EXPORTED;
|
exported = dl->pvd.pv_status & VG_EXPORTED;
|
||||||
first_time = 0;
|
first_time = 0;
|
||||||
@@ -129,8 +125,8 @@ static int _check_vgs(struct list *pvs, int *partial)
|
|||||||
static struct volume_group *_build_vg(struct format_instance *fid,
|
static struct volume_group *_build_vg(struct format_instance *fid,
|
||||||
struct list *pvs)
|
struct list *pvs)
|
||||||
{
|
{
|
||||||
struct pool *mem = fid->fmt->cmd->mem;
|
struct dm_pool *mem = fid->fmt->cmd->mem;
|
||||||
struct volume_group *vg = pool_alloc(mem, sizeof(*vg));
|
struct volume_group *vg = dm_pool_alloc(mem, sizeof(*vg));
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
int partial;
|
int partial;
|
||||||
|
|
||||||
@@ -147,7 +143,6 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
|||||||
vg->seqno = 0;
|
vg->seqno = 0;
|
||||||
list_init(&vg->pvs);
|
list_init(&vg->pvs);
|
||||||
list_init(&vg->lvs);
|
list_init(&vg->lvs);
|
||||||
list_init(&vg->snapshots);
|
|
||||||
list_init(&vg->tags);
|
list_init(&vg->tags);
|
||||||
|
|
||||||
if (!_check_vgs(pvs, &partial))
|
if (!_check_vgs(pvs, &partial))
|
||||||
@@ -174,7 +169,7 @@ static struct volume_group *_build_vg(struct format_instance *fid,
|
|||||||
|
|
||||||
bad:
|
bad:
|
||||||
stack;
|
stack;
|
||||||
pool_free(mem, vg);
|
dm_pool_free(mem, vg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +177,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
|||||||
const char *vg_name,
|
const char *vg_name,
|
||||||
struct metadata_area *mda)
|
struct metadata_area *mda)
|
||||||
{
|
{
|
||||||
struct pool *mem = pool_create(1024 * 10);
|
struct dm_pool *mem = dm_pool_create("lvm1 vg_read", 1024 * 10);
|
||||||
struct list pvs;
|
struct list pvs;
|
||||||
struct volume_group *vg = NULL;
|
struct volume_group *vg = NULL;
|
||||||
list_init(&pvs);
|
list_init(&pvs);
|
||||||
@@ -207,16 +202,16 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return vg;
|
return vg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct disk_list *_flatten_pv(struct format_instance *fid,
|
static struct disk_list *_flatten_pv(struct format_instance *fid,
|
||||||
struct pool *mem, struct volume_group *vg,
|
struct dm_pool *mem, struct volume_group *vg,
|
||||||
struct physical_volume *pv,
|
struct physical_volume *pv,
|
||||||
const char *dev_dir)
|
const char *dev_dir)
|
||||||
{
|
{
|
||||||
struct disk_list *dl = pool_alloc(mem, sizeof(*dl));
|
struct disk_list *dl = dm_pool_alloc(mem, sizeof(*dl));
|
||||||
|
|
||||||
if (!dl) {
|
if (!dl) {
|
||||||
stack;
|
stack;
|
||||||
@@ -234,25 +229,22 @@ static struct disk_list *_flatten_pv(struct format_instance *fid,
|
|||||||
!export_uuids(dl, vg) ||
|
!export_uuids(dl, vg) ||
|
||||||
!export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
|
!export_lvs(dl, vg, pv, dev_dir) || !calculate_layout(dl)) {
|
||||||
stack;
|
stack;
|
||||||
pool_free(mem, dl);
|
dm_pool_free(mem, dl);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dl;
|
return dl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _flatten_vg(struct format_instance *fid, struct pool *mem,
|
static int _flatten_vg(struct format_instance *fid, struct dm_pool *mem,
|
||||||
struct volume_group *vg,
|
struct volume_group *vg,
|
||||||
struct list *pvds, const char *dev_dir,
|
struct list *pvds, const char *dev_dir,
|
||||||
struct dev_filter *filter)
|
struct dev_filter *filter)
|
||||||
{
|
{
|
||||||
struct list *pvh;
|
|
||||||
struct pv_list *pvl;
|
struct pv_list *pvl;
|
||||||
struct disk_list *data;
|
struct disk_list *data;
|
||||||
|
|
||||||
list_iterate(pvh, &vg->pvs) {
|
list_iterate_items(pvl, &vg->pvs) {
|
||||||
pvl = list_item(pvh, struct pv_list);
|
|
||||||
|
|
||||||
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
|
if (!(data = _flatten_pv(fid, mem, vg, pvl->pv, dev_dir))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -275,7 +267,7 @@ static int _flatten_vg(struct format_instance *fid, struct pool *mem,
|
|||||||
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
||||||
struct metadata_area *mda)
|
struct metadata_area *mda)
|
||||||
{
|
{
|
||||||
struct pool *mem = pool_create(1024 * 10);
|
struct dm_pool *mem = dm_pool_create("lvm1 vg_write", 1024 * 10);
|
||||||
struct list pvds;
|
struct list pvds;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
@@ -291,14 +283,14 @@ static int _vg_write(struct format_instance *fid, struct volume_group *vg,
|
|||||||
write_disks(fid->fmt, &pvds));
|
write_disks(fid->fmt, &pvds));
|
||||||
|
|
||||||
lvmcache_update_vg(vg);
|
lvmcache_update_vg(vg);
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||||
struct physical_volume *pv, struct list *mdas)
|
struct physical_volume *pv, struct list *mdas)
|
||||||
{
|
{
|
||||||
struct pool *mem = pool_create(1024);
|
struct dm_pool *mem = dm_pool_create("lvm1 pv_read", 1024);
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@@ -330,7 +322,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
|||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +389,7 @@ static int _lv_setup(struct format_instance *fid, struct logical_volume *lv)
|
|||||||
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
||||||
struct list *mdas, int64_t sector)
|
struct list *mdas, int64_t sector)
|
||||||
{
|
{
|
||||||
struct pool *mem;
|
struct dm_pool *mem;
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
struct list pvs;
|
struct list pvs;
|
||||||
struct label *label;
|
struct label *label;
|
||||||
@@ -420,12 +412,12 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
|||||||
pv->pe_size = pv->pe_count = 0;
|
pv->pe_size = pv->pe_count = 0;
|
||||||
pv->pe_start = PE_ALIGN;
|
pv->pe_start = PE_ALIGN;
|
||||||
|
|
||||||
if (!(mem = pool_create(1024))) {
|
if (!(mem = dm_pool_create("lvm1 pv_write", 1024))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dl = pool_alloc(mem, sizeof(*dl)))) {
|
if (!(dl = dm_pool_alloc(mem, sizeof(*dl)))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -449,11 +441,11 @@ static int _pv_write(const struct format_type *fmt, struct physical_volume *pv,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,6 +484,17 @@ static int _vg_setup(struct format_instance *fid, struct volume_group *vg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _segtype_supported (struct format_instance *fid,
|
||||||
|
struct segment_type *segtype)
|
||||||
|
{
|
||||||
|
if (!(segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static struct metadata_area_ops _metadata_format1_ops = {
|
static struct metadata_area_ops _metadata_format1_ops = {
|
||||||
vg_read:_vg_read,
|
vg_read:_vg_read,
|
||||||
vg_write:_vg_write,
|
vg_write:_vg_write,
|
||||||
@@ -504,7 +507,7 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
|
|||||||
struct format_instance *fid;
|
struct format_instance *fid;
|
||||||
struct metadata_area *mda;
|
struct metadata_area *mda;
|
||||||
|
|
||||||
if (!(fid = pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
|
if (!(fid = dm_pool_alloc(fmt->cmd->mem, sizeof(*fid)))) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -513,9 +516,9 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
|
|||||||
list_init(&fid->metadata_areas);
|
list_init(&fid->metadata_areas);
|
||||||
|
|
||||||
/* Define a NULL metadata area */
|
/* Define a NULL metadata area */
|
||||||
if (!(mda = pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
|
if (!(mda = dm_pool_alloc(fmt->cmd->mem, sizeof(*mda)))) {
|
||||||
stack;
|
stack;
|
||||||
pool_free(fmt->cmd->mem, fid);
|
dm_pool_free(fmt->cmd->mem, fid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,7 +536,7 @@ static void _destroy_instance(struct format_instance *fid)
|
|||||||
|
|
||||||
static void _destroy(const struct format_type *fmt)
|
static void _destroy(const struct format_type *fmt)
|
||||||
{
|
{
|
||||||
dbg_free((void *) fmt);
|
dm_free((void *) fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct format_handler _format1_ops = {
|
static struct format_handler _format1_ops = {
|
||||||
@@ -542,6 +545,7 @@ static struct format_handler _format1_ops = {
|
|||||||
pv_write:_pv_write,
|
pv_write:_pv_write,
|
||||||
lv_setup:_lv_setup,
|
lv_setup:_lv_setup,
|
||||||
vg_setup:_vg_setup,
|
vg_setup:_vg_setup,
|
||||||
|
segtype_supported:_segtype_supported,
|
||||||
create_instance:_create_instance,
|
create_instance:_create_instance,
|
||||||
destroy_instance:_destroy_instance,
|
destroy_instance:_destroy_instance,
|
||||||
destroy:_destroy,
|
destroy:_destroy,
|
||||||
@@ -554,7 +558,7 @@ struct format_type *init_format(struct cmd_context *cmd);
|
|||||||
struct format_type *init_format(struct cmd_context *cmd)
|
struct format_type *init_format(struct cmd_context *cmd)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct format_type *fmt = dbg_malloc(sizeof(*fmt));
|
struct format_type *fmt = dm_malloc(sizeof(*fmt));
|
||||||
|
|
||||||
if (!fmt) {
|
if (!fmt) {
|
||||||
stack;
|
stack;
|
||||||
@@ -578,5 +582,7 @@ struct format_type *init_format(struct cmd_context *cmd)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_very_verbose("Initialised format: %s", fmt->name);
|
||||||
|
|
||||||
return fmt;
|
return fmt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,11 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "disk-rep.h"
|
#include "disk-rep.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "hash.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "segtypes.h"
|
#include "segtype.h"
|
||||||
|
#include "pv_alloc.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@@ -37,7 +35,7 @@ static int _check_vg_name(const char *name)
|
|||||||
/*
|
/*
|
||||||
* Extracts the last part of a path.
|
* Extracts the last part of a path.
|
||||||
*/
|
*/
|
||||||
static char *_create_lv_name(struct pool *mem, const char *full_name)
|
static char *_create_lv_name(struct dm_pool *mem, const char *full_name)
|
||||||
{
|
{
|
||||||
const char *ptr = strrchr(full_name, '/');
|
const char *ptr = strrchr(full_name, '/');
|
||||||
|
|
||||||
@@ -46,10 +44,10 @@ static char *_create_lv_name(struct pool *mem, const char *full_name)
|
|||||||
else
|
else
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
return pool_strdup(mem, ptr);
|
return dm_pool_strdup(mem, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_pv(struct pool *mem, struct device *dev,
|
int import_pv(struct dm_pool *mem, struct device *dev,
|
||||||
struct volume_group *vg,
|
struct volume_group *vg,
|
||||||
struct physical_volume *pv, struct pv_disk *pvd)
|
struct physical_volume *pv, struct pv_disk *pvd)
|
||||||
{
|
{
|
||||||
@@ -57,7 +55,7 @@ int import_pv(struct pool *mem, struct device *dev,
|
|||||||
memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
|
memcpy(&pv->id, pvd->pv_uuid, ID_LEN);
|
||||||
|
|
||||||
pv->dev = dev;
|
pv->dev = dev;
|
||||||
if (!(pv->vg_name = pool_strdup(mem, pvd->vg_name))) {
|
if (!(pv->vg_name = dm_pool_strdup(mem, pvd->vg_name))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -86,9 +84,15 @@ int import_pv(struct pool *mem, struct device *dev,
|
|||||||
pv->pe_size = pvd->pe_size;
|
pv->pe_size = pvd->pe_size;
|
||||||
pv->pe_start = pvd->pe_start;
|
pv->pe_start = pvd->pe_start;
|
||||||
pv->pe_count = pvd->pe_total;
|
pv->pe_count = pvd->pe_total;
|
||||||
pv->pe_alloc_count = pvd->pe_allocated;
|
pv->pe_alloc_count = 0;
|
||||||
|
|
||||||
list_init(&pv->tags);
|
list_init(&pv->tags);
|
||||||
|
list_init(&pv->segments);
|
||||||
|
|
||||||
|
if (!alloc_pv_segment_whole_pv(mem, pv)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -105,7 +109,7 @@ static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int export_pv(struct cmd_context *cmd, struct pool *mem,
|
int export_pv(struct cmd_context *cmd, struct dm_pool *mem,
|
||||||
struct volume_group *vg,
|
struct volume_group *vg,
|
||||||
struct pv_disk *pvd, struct physical_volume *pv)
|
struct pv_disk *pvd, struct physical_volume *pv)
|
||||||
{
|
{
|
||||||
@@ -191,7 +195,7 @@ int export_pv(struct cmd_context *cmd, struct pool *mem,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_vg(struct pool *mem,
|
int import_vg(struct dm_pool *mem,
|
||||||
struct volume_group *vg, struct disk_list *dl, int partial)
|
struct volume_group *vg, struct disk_list *dl, int partial)
|
||||||
{
|
{
|
||||||
struct vg_disk *vgd = &dl->vgd;
|
struct vg_disk *vgd = &dl->vgd;
|
||||||
@@ -202,12 +206,12 @@ int import_vg(struct pool *mem,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vg->name = pool_strdup(mem, dl->pvd.vg_name))) {
|
if (!(vg->name = dm_pool_strdup(mem, dl->pvd.vg_name))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vg->system_id = pool_alloc(mem, NAME_LEN))) {
|
if (!(vg->system_id = dm_pool_alloc(mem, NAME_LEN))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -234,7 +238,7 @@ int import_vg(struct pool *mem,
|
|||||||
|
|
||||||
vg->extent_size = vgd->pe_size;
|
vg->extent_size = vgd->pe_size;
|
||||||
vg->extent_count = vgd->pe_total;
|
vg->extent_count = vgd->pe_total;
|
||||||
vg->free_count = vgd->pe_total - vgd->pe_allocated;
|
vg->free_count = vgd->pe_total;
|
||||||
vg->max_lv = vgd->lv_max;
|
vg->max_lv = vgd->lv_max;
|
||||||
vg->max_pv = vgd->pv_max;
|
vg->max_pv = vgd->pv_max;
|
||||||
vg->alloc = ALLOC_NORMAL;
|
vg->alloc = ALLOC_NORMAL;
|
||||||
@@ -281,7 +285,7 @@ int export_vg(struct vg_disk *vgd, struct volume_group *vg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
|
int import_lv(struct dm_pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
|
||||||
{
|
{
|
||||||
lvid_from_lvnum(&lv->lvid, &lv->vg->id, lvd->lv_number);
|
lvid_from_lvnum(&lv->lvid, &lv->vg->id, lvd->lv_number);
|
||||||
|
|
||||||
@@ -323,6 +327,8 @@ int import_lv(struct pool *mem, struct logical_volume *lv, struct lv_disk *lvd)
|
|||||||
lv->size = lvd->lv_size;
|
lv->size = lvd->lv_size;
|
||||||
lv->le_count = lvd->lv_allocated_le;
|
lv->le_count = lvd->lv_allocated_le;
|
||||||
|
|
||||||
|
lv->snapshot = NULL;
|
||||||
|
list_init(&lv->snapshot_segs);
|
||||||
list_init(&lv->segments);
|
list_init(&lv->segments);
|
||||||
list_init(&lv->tags);
|
list_init(&lv->tags);
|
||||||
|
|
||||||
@@ -373,14 +379,11 @@ static void _export_lv(struct lv_disk *lvd, struct volume_group *vg,
|
|||||||
int export_extents(struct disk_list *dl, uint32_t lv_num,
|
int export_extents(struct disk_list *dl, uint32_t lv_num,
|
||||||
struct logical_volume *lv, struct physical_volume *pv)
|
struct logical_volume *lv, struct physical_volume *pv)
|
||||||
{
|
{
|
||||||
struct list *segh;
|
|
||||||
struct pe_disk *ped;
|
struct pe_disk *ped;
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
uint32_t pe, s;
|
uint32_t pe, s;
|
||||||
|
|
||||||
list_iterate(segh, &lv->segments) {
|
list_iterate_items(seg, &lv->segments) {
|
||||||
seg = list_item(segh, struct lv_segment);
|
|
||||||
|
|
||||||
for (s = 0; s < seg->area_count; s++) {
|
for (s = 0; s < seg->area_count; s++) {
|
||||||
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
if (!(seg->segtype->flags & SEG_FORMAT1_SUPPORT)) {
|
||||||
log_error("Segment type %s in LV %s: "
|
log_error("Segment type %s in LV %s: "
|
||||||
@@ -388,16 +391,16 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
|
|||||||
seg->segtype->name, lv->name);
|
seg->segtype->name, lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (seg->area[s].type != AREA_PV) {
|
if (seg_type(seg, s) != AREA_PV) {
|
||||||
log_error("LV stripe found in LV %s: "
|
log_error("Non-PV stripe found in LV %s: "
|
||||||
"unsupported by format1", lv->name);
|
"unsupported by format1", lv->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (seg->area[s].u.pv.pv != pv)
|
if (seg_pv(seg, s) != pv)
|
||||||
continue; /* not our pv */
|
continue; /* not our pv */
|
||||||
|
|
||||||
for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
|
for (pe = 0; pe < (seg->len / seg->area_count); pe++) {
|
||||||
ped = &dl->extents[pe + seg->area[s].u.pv.pe];
|
ped = &dl->extents[pe + seg_pe(seg, s)];
|
||||||
ped->lv_num = lv_num;
|
ped->lv_num = lv_num;
|
||||||
ped->le_num = (seg->le / seg->area_count) + pe +
|
ped->le_num = (seg->le / seg->area_count) + pe +
|
||||||
s * (lv->le_count / seg->area_count);
|
s * (lv->le_count / seg->area_count);
|
||||||
@@ -408,21 +411,17 @@ int export_extents(struct disk_list *dl, uint32_t lv_num,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_pvs(const struct format_type *fmt, struct pool *mem,
|
int import_pvs(const struct format_type *fmt, struct dm_pool *mem,
|
||||||
struct volume_group *vg,
|
struct volume_group *vg,
|
||||||
struct list *pvds, struct list *results, int *count)
|
struct list *pvds, struct list *results, int *count)
|
||||||
{
|
{
|
||||||
struct list *pvdh;
|
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
struct pv_list *pvl;
|
struct pv_list *pvl;
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds) {
|
||||||
|
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
|
||||||
dl = list_item(pvdh, struct disk_list);
|
!(pvl->pv = dm_pool_alloc(mem, sizeof(*pvl->pv)))) {
|
||||||
|
|
||||||
if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) ||
|
|
||||||
!(pvl->pv = pool_alloc(mem, sizeof(*pvl->pv)))) {
|
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -440,15 +439,15 @@ int import_pvs(const struct format_type *fmt, struct pool *mem,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct logical_volume *_add_lv(struct pool *mem,
|
static struct logical_volume *_add_lv(struct dm_pool *mem,
|
||||||
struct volume_group *vg,
|
struct volume_group *vg,
|
||||||
struct lv_disk *lvd)
|
struct lv_disk *lvd)
|
||||||
{
|
{
|
||||||
struct lv_list *ll;
|
struct lv_list *ll;
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
|
|
||||||
if (!(ll = pool_zalloc(mem, sizeof(*ll))) ||
|
if (!(ll = dm_pool_zalloc(mem, sizeof(*ll))) ||
|
||||||
!(ll->lv = pool_zalloc(mem, sizeof(*ll->lv)))) {
|
!(ll->lv = dm_pool_zalloc(mem, sizeof(*ll->lv)))) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -466,17 +465,14 @@ static struct logical_volume *_add_lv(struct pool *mem,
|
|||||||
return lv;
|
return lv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_lvs(struct pool *mem, struct volume_group *vg, struct list *pvds)
|
int import_lvs(struct dm_pool *mem, struct volume_group *vg, struct list *pvds)
|
||||||
{
|
{
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
struct lvd_list *ll;
|
struct lvd_list *ll;
|
||||||
struct lv_disk *lvd;
|
struct lv_disk *lvd;
|
||||||
struct list *pvdh, *lvdh;
|
|
||||||
|
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds) {
|
||||||
dl = list_item(pvdh, struct disk_list);
|
list_iterate_items(ll, &dl->lvds) {
|
||||||
list_iterate(lvdh, &dl->lvds) {
|
|
||||||
ll = list_item(lvdh, struct lvd_list);
|
|
||||||
lvd = &ll->lvd;
|
lvd = &ll->lvd;
|
||||||
|
|
||||||
if (!find_lv(vg, lvd->lv_name) &&
|
if (!find_lv(vg, lvd->lv_name) &&
|
||||||
@@ -495,19 +491,18 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
|||||||
struct physical_volume *pv, const char *dev_dir)
|
struct physical_volume *pv, const char *dev_dir)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
struct list *lvh, *sh;
|
|
||||||
struct lv_list *ll;
|
struct lv_list *ll;
|
||||||
struct lvd_list *lvdl;
|
struct lvd_list *lvdl;
|
||||||
size_t len;
|
size_t len;
|
||||||
uint32_t lv_num;
|
uint32_t lv_num;
|
||||||
struct hash_table *lvd_hash;
|
struct dm_hash_table *lvd_hash;
|
||||||
|
|
||||||
if (!_check_vg_name(vg->name)) {
|
if (!_check_vg_name(vg->name)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(lvd_hash = hash_create(32))) {
|
if (!(lvd_hash = dm_hash_create(32))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -516,15 +511,17 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
|||||||
* setup the pv's extents array
|
* setup the pv's extents array
|
||||||
*/
|
*/
|
||||||
len = sizeof(struct pe_disk) * dl->pvd.pe_total;
|
len = sizeof(struct pe_disk) * dl->pvd.pe_total;
|
||||||
if (!(dl->extents = pool_alloc(dl->mem, len))) {
|
if (!(dl->extents = dm_pool_alloc(dl->mem, len))) {
|
||||||
stack;
|
stack;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
memset(dl->extents, 0, len);
|
memset(dl->extents, 0, len);
|
||||||
|
|
||||||
list_iterate(lvh, &vg->lvs) {
|
list_iterate_items(ll, &vg->lvs) {
|
||||||
ll = list_item(lvh, struct lv_list);
|
if (ll->lv->status & SNAPSHOT)
|
||||||
if (!(lvdl = pool_alloc(dl->mem, sizeof(*lvdl)))) {
|
continue;
|
||||||
|
|
||||||
|
if (!(lvdl = dm_pool_alloc(dl->mem, sizeof(*lvdl)))) {
|
||||||
stack;
|
stack;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -532,10 +529,9 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
|||||||
_export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
|
_export_lv(&lvdl->lvd, vg, ll->lv, dev_dir);
|
||||||
|
|
||||||
lv_num = lvnum_from_lvid(&ll->lv->lvid);
|
lv_num = lvnum_from_lvid(&ll->lv->lvid);
|
||||||
|
|
||||||
lvdl->lvd.lv_number = lv_num;
|
lvdl->lvd.lv_number = lv_num;
|
||||||
|
|
||||||
if (!hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd)) {
|
if (!dm_hash_insert(lvd_hash, ll->lv->name, &lvdl->lvd)) {
|
||||||
stack;
|
stack;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -545,64 +541,45 @@ int export_lvs(struct disk_list *dl, struct volume_group *vg,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lv_is_origin(ll->lv))
|
||||||
|
lvdl->lvd.lv_access |= LV_SNAPSHOT_ORG;
|
||||||
|
|
||||||
|
if (lv_is_cow(ll->lv)) {
|
||||||
|
lvdl->lvd.lv_access |= LV_SNAPSHOT;
|
||||||
|
lvdl->lvd.lv_chunk_size = ll->lv->snapshot->chunk_size;
|
||||||
|
lvdl->lvd.lv_snapshot_minor =
|
||||||
|
lvnum_from_lvid(&ll->lv->snapshot->origin->lvid);
|
||||||
|
}
|
||||||
|
|
||||||
list_add(&dl->lvds, &lvdl->list);
|
list_add(&dl->lvds, &lvdl->list);
|
||||||
dl->pvd.lv_cur++;
|
dl->pvd.lv_cur++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Now we need to run through the snapshots, exporting
|
|
||||||
* the SNAPSHOT_ORG flags etc.
|
|
||||||
*/
|
|
||||||
list_iterate(sh, &vg->snapshots) {
|
|
||||||
struct lv_disk *org, *cow;
|
|
||||||
struct snapshot *s = list_item(sh,
|
|
||||||
struct snapshot_list)->snapshot;
|
|
||||||
|
|
||||||
if (!(org = hash_lookup(lvd_hash, s->origin->name))) {
|
|
||||||
log_err("Couldn't find snapshot origin '%s'.",
|
|
||||||
s->origin->name);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(cow = hash_lookup(lvd_hash, s->cow->name))) {
|
|
||||||
log_err("Couldn't find snapshot cow store '%s'.",
|
|
||||||
s->cow->name);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
org->lv_access |= LV_SNAPSHOT_ORG;
|
|
||||||
cow->lv_access |= LV_SNAPSHOT;
|
|
||||||
cow->lv_snapshot_minor = org->lv_number;
|
|
||||||
cow->lv_chunk_size = s->chunk_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
hash_destroy(lvd_hash);
|
dm_hash_destroy(lvd_hash);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: More inefficient code.
|
* FIXME: More inefficient code.
|
||||||
*/
|
*/
|
||||||
int import_snapshots(struct pool *mem, struct volume_group *vg,
|
int import_snapshots(struct dm_pool *mem, struct volume_group *vg,
|
||||||
struct list *pvds)
|
struct list *pvds)
|
||||||
{
|
{
|
||||||
struct logical_volume *lvs[MAX_LV];
|
struct logical_volume *lvs[MAX_LV];
|
||||||
struct list *pvdh, *lvdh;
|
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
|
struct lvd_list *ll;
|
||||||
struct lv_disk *lvd;
|
struct lv_disk *lvd;
|
||||||
int lvnum;
|
int lvnum;
|
||||||
struct logical_volume *org, *cow;
|
struct logical_volume *org, *cow;
|
||||||
|
|
||||||
/* build an index of lv numbers */
|
/* build an index of lv numbers */
|
||||||
memset(lvs, 0, sizeof(lvs));
|
memset(lvs, 0, sizeof(lvs));
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds) {
|
||||||
dl = list_item(pvdh, struct disk_list);
|
list_iterate_items(ll, &dl->lvds) {
|
||||||
|
lvd = &ll->lvd;
|
||||||
list_iterate(lvdh, &dl->lvds) {
|
|
||||||
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
|
|
||||||
|
|
||||||
lvnum = lvd->lv_number;
|
lvnum = lvd->lv_number;
|
||||||
|
|
||||||
@@ -624,11 +601,9 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
|
|||||||
/*
|
/*
|
||||||
* Now iterate through yet again adding the snapshots.
|
* Now iterate through yet again adding the snapshots.
|
||||||
*/
|
*/
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds) {
|
||||||
dl = list_item(pvdh, struct disk_list);
|
list_iterate_items(ll, &dl->lvds) {
|
||||||
|
lvd = &ll->lvd;
|
||||||
list_iterate(lvdh, &dl->lvds) {
|
|
||||||
lvd = &(list_item(lvdh, struct lvd_list)->lvd);
|
|
||||||
|
|
||||||
if (!(lvd->lv_access & LV_SNAPSHOT))
|
if (!(lvd->lv_access & LV_SNAPSHOT))
|
||||||
continue;
|
continue;
|
||||||
@@ -646,7 +621,8 @@ int import_snapshots(struct pool *mem, struct volume_group *vg,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* insert the snapshot */
|
/* insert the snapshot */
|
||||||
if (!vg_add_snapshot(org, cow, 1, NULL,
|
if (!vg_add_snapshot(vg->fid, NULL, org, cow, NULL,
|
||||||
|
org->le_count,
|
||||||
lvd->lv_chunk_size)) {
|
lvd->lv_chunk_size)) {
|
||||||
log_err("Couldn't add snapshot.");
|
log_err("Couldn't add snapshot.");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -661,11 +637,9 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
|
|||||||
{
|
{
|
||||||
struct uuid_list *ul;
|
struct uuid_list *ul;
|
||||||
struct pv_list *pvl;
|
struct pv_list *pvl;
|
||||||
struct list *pvh;
|
|
||||||
|
|
||||||
list_iterate(pvh, &vg->pvs) {
|
list_iterate_items(pvl, &vg->pvs) {
|
||||||
pvl = list_item(pvh, struct pv_list);
|
if (!(ul = dm_pool_alloc(dl->mem, sizeof(*ul)))) {
|
||||||
if (!(ul = pool_alloc(dl->mem, sizeof(*ul)))) {
|
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -684,14 +658,11 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg)
|
|||||||
*/
|
*/
|
||||||
void export_numbers(struct list *pvds, struct volume_group *vg)
|
void export_numbers(struct list *pvds, struct volume_group *vg)
|
||||||
{
|
{
|
||||||
struct list *pvdh;
|
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
int pv_num = 1;
|
int pv_num = 1;
|
||||||
|
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds)
|
||||||
dl = list_item(pvdh, struct disk_list);
|
|
||||||
dl->pvd.pv_number = pv_num++;
|
dl->pvd.pv_number = pv_num++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -699,26 +670,20 @@ void export_numbers(struct list *pvds, struct volume_group *vg)
|
|||||||
*/
|
*/
|
||||||
void export_pv_act(struct list *pvds)
|
void export_pv_act(struct list *pvds)
|
||||||
{
|
{
|
||||||
struct list *pvdh;
|
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
int act = 0;
|
int act = 0;
|
||||||
|
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds)
|
||||||
dl = list_item(pvdh, struct disk_list);
|
|
||||||
if (dl->pvd.pv_status & PV_ACTIVE)
|
if (dl->pvd.pv_status & PV_ACTIVE)
|
||||||
act++;
|
act++;
|
||||||
}
|
|
||||||
|
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds)
|
||||||
dl = list_item(pvdh, struct disk_list);
|
|
||||||
dl->vgd.pv_act = act;
|
dl->vgd.pv_act = act;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int export_vg_number(struct format_instance *fid, struct list *pvds,
|
int export_vg_number(struct format_instance *fid, struct list *pvds,
|
||||||
const char *vg_name, struct dev_filter *filter)
|
const char *vg_name, struct dev_filter *filter)
|
||||||
{
|
{
|
||||||
struct list *pvdh;
|
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
int vg_num;
|
int vg_num;
|
||||||
|
|
||||||
@@ -727,10 +692,8 @@ int export_vg_number(struct format_instance *fid, struct list *pvds,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds)
|
||||||
dl = list_item(pvdh, struct disk_list);
|
|
||||||
dl->vgd.vg_number = vg_num;
|
dl->vgd.vg_number = vg_num;
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,10 @@
|
|||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "pool.h"
|
|
||||||
#include "disk-rep.h"
|
#include "disk-rep.h"
|
||||||
#include "lv_alloc.h"
|
#include "lv_alloc.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "segtypes.h"
|
#include "segtype.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After much thought I have decided it is easier,
|
* After much thought I have decided it is easier,
|
||||||
@@ -44,11 +42,10 @@ struct lv_map {
|
|||||||
struct pe_specifier *map;
|
struct pe_specifier *map;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hash_table *_create_lv_maps(struct pool *mem,
|
static struct dm_hash_table *_create_lv_maps(struct dm_pool *mem,
|
||||||
struct volume_group *vg)
|
struct volume_group *vg)
|
||||||
{
|
{
|
||||||
struct hash_table *maps = hash_create(32);
|
struct dm_hash_table *maps = dm_hash_create(32);
|
||||||
struct list *llh;
|
|
||||||
struct lv_list *ll;
|
struct lv_list *ll;
|
||||||
struct lv_map *lvm;
|
struct lv_map *lvm;
|
||||||
|
|
||||||
@@ -58,22 +55,23 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_iterate(llh, &vg->lvs) {
|
list_iterate_items(ll, &vg->lvs) {
|
||||||
ll = list_item(llh, struct lv_list);
|
if (ll->lv->status & SNAPSHOT)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!(lvm = pool_alloc(mem, sizeof(*lvm)))) {
|
if (!(lvm = dm_pool_alloc(mem, sizeof(*lvm)))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
lvm->lv = ll->lv;
|
lvm->lv = ll->lv;
|
||||||
if (!(lvm->map = pool_zalloc(mem, sizeof(*lvm->map)
|
if (!(lvm->map = dm_pool_zalloc(mem, sizeof(*lvm->map)
|
||||||
* ll->lv->le_count))) {
|
* ll->lv->le_count))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hash_insert(maps, ll->lv->name, lvm)) {
|
if (!dm_hash_insert(maps, ll->lv->name, lvm)) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -82,21 +80,20 @@ static struct hash_table *_create_lv_maps(struct pool *mem,
|
|||||||
return maps;
|
return maps;
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
hash_destroy(maps);
|
dm_hash_destroy(maps);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fill_lv_array(struct lv_map **lvs,
|
static int _fill_lv_array(struct lv_map **lvs,
|
||||||
struct hash_table *maps, struct disk_list *dl)
|
struct dm_hash_table *maps, struct disk_list *dl)
|
||||||
{
|
{
|
||||||
struct list *lvh;
|
struct lvd_list *ll;
|
||||||
struct lv_map *lvm;
|
struct lv_map *lvm;
|
||||||
|
|
||||||
memset(lvs, 0, sizeof(*lvs) * MAX_LV);
|
memset(lvs, 0, sizeof(*lvs) * MAX_LV);
|
||||||
list_iterate(lvh, &dl->lvds) {
|
|
||||||
struct lvd_list *ll = list_item(lvh, struct lvd_list);
|
|
||||||
|
|
||||||
if (!(lvm = hash_lookup(maps, strrchr(ll->lvd.lv_name, '/')
|
list_iterate_items(ll, &dl->lvds) {
|
||||||
|
if (!(lvm = dm_hash_lookup(maps, strrchr(ll->lvd.lv_name, '/')
|
||||||
+ 1))) {
|
+ 1))) {
|
||||||
log_err("Physical volume (%s) contains an "
|
log_err("Physical volume (%s) contains an "
|
||||||
"unknown logical volume (%s).",
|
"unknown logical volume (%s).",
|
||||||
@@ -113,18 +110,16 @@ static int _fill_lv_array(struct lv_map **lvs,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _fill_maps(struct hash_table *maps, struct volume_group *vg,
|
static int _fill_maps(struct dm_hash_table *maps, struct volume_group *vg,
|
||||||
struct list *pvds)
|
struct list *pvds)
|
||||||
{
|
{
|
||||||
struct list *pvdh;
|
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
struct physical_volume *pv;
|
struct physical_volume *pv;
|
||||||
struct lv_map *lvms[MAX_LV], *lvm;
|
struct lv_map *lvms[MAX_LV], *lvm;
|
||||||
struct pe_disk *e;
|
struct pe_disk *e;
|
||||||
uint32_t i, lv_num, le;
|
uint32_t i, lv_num, le;
|
||||||
|
|
||||||
list_iterate(pvdh, pvds) {
|
list_iterate_items(dl, pvds) {
|
||||||
dl = list_item(pvdh, struct disk_list);
|
|
||||||
pv = find_pv(vg, dl->dev);
|
pv = find_pv(vg, dl->dev);
|
||||||
e = dl->extents;
|
e = dl->extents;
|
||||||
|
|
||||||
@@ -187,13 +182,13 @@ static int _check_single_map(struct lv_map *lvm)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _check_maps_are_complete(struct hash_table *maps)
|
static int _check_maps_are_complete(struct dm_hash_table *maps)
|
||||||
{
|
{
|
||||||
struct hash_node *n;
|
struct dm_hash_node *n;
|
||||||
struct lv_map *lvm;
|
struct lv_map *lvm;
|
||||||
|
|
||||||
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
|
for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
|
||||||
lvm = (struct lv_map *) hash_get_data(maps, n);
|
lvm = (struct lv_map *) dm_hash_get_data(maps, n);
|
||||||
|
|
||||||
if (!_check_single_map(lvm)) {
|
if (!_check_single_map(lvm)) {
|
||||||
stack;
|
stack;
|
||||||
@@ -205,58 +200,59 @@ static int _check_maps_are_complete(struct hash_table *maps)
|
|||||||
|
|
||||||
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
|
static int _read_linear(struct cmd_context *cmd, struct lv_map *lvm)
|
||||||
{
|
{
|
||||||
uint32_t le = 0;
|
uint32_t le = 0, len;
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
|
struct segment_type *segtype;
|
||||||
|
|
||||||
|
if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
while (le < lvm->lv->le_count) {
|
while (le < lvm->lv->le_count) {
|
||||||
seg = alloc_lv_segment(cmd->mem, 1);
|
len = 0;
|
||||||
|
|
||||||
seg->lv = lvm->lv;
|
do
|
||||||
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
|
len++;
|
||||||
|
while ((lvm->map[le + len].pv == lvm->map[le].pv) &&
|
||||||
|
(lvm->map[le].pv &&
|
||||||
|
lvm->map[le + len].pe == lvm->map[le].pe + len));
|
||||||
|
|
||||||
|
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv, le,
|
||||||
|
len, 0, 0, NULL, 1, len, 0, 0, 0))) {
|
||||||
|
log_error("Failed to allocate linear segment.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!set_lv_segment_area_pv(seg, 0, lvm->map[le].pv,
|
||||||
|
lvm->map[le].pe)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
seg->le = le;
|
list_add(&lvm->lv->segments, &seg->list);
|
||||||
seg->len = 0;
|
|
||||||
seg->area_len = 0;
|
|
||||||
seg->stripe_size = 0;
|
|
||||||
|
|
||||||
seg->area[0].type = AREA_PV;
|
|
||||||
seg->area[0].u.pv.pv = lvm->map[le].pv;
|
|
||||||
seg->area[0].u.pv.pe = lvm->map[le].pe;
|
|
||||||
|
|
||||||
do {
|
|
||||||
seg->len++;
|
|
||||||
seg->area_len++;
|
|
||||||
} while ((lvm->map[le + seg->len].pv == seg->area[0].u.pv.pv) &&
|
|
||||||
(seg->area[0].u.pv.pv &&
|
|
||||||
lvm->map[le + seg->len].pe == seg->area[0].u.pv.pe +
|
|
||||||
seg->len));
|
|
||||||
|
|
||||||
le += seg->len;
|
le += seg->len;
|
||||||
|
|
||||||
list_add(&lvm->lv->segments, &seg->list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
|
static int _check_stripe(struct lv_map *lvm, uint32_t area_count,
|
||||||
uint32_t base_le, uint32_t len)
|
uint32_t seg_len, uint32_t base_le, uint32_t len)
|
||||||
{
|
{
|
||||||
uint32_t le, st;
|
uint32_t st;
|
||||||
|
|
||||||
le = base_le + seg->len;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is the next physical extent in every stripe adjacent to the last?
|
* Is the next physical extent in every stripe adjacent to the last?
|
||||||
*/
|
*/
|
||||||
for (st = 0; st < seg->area_count; st++)
|
for (st = 0; st < area_count; st++)
|
||||||
if ((lvm->map[le + st * len].pv != seg->area[st].u.pv.pv) ||
|
if ((lvm->map[base_le + st * len + seg_len].pv !=
|
||||||
(seg->area[st].u.pv.pv &&
|
lvm->map[base_le + st * len].pv) ||
|
||||||
lvm->map[le + st * len].pe !=
|
(lvm->map[base_le + st * len].pv &&
|
||||||
seg->area[st].u.pv.pe + seg->len)) return 0;
|
lvm->map[base_le + st * len + seg_len].pe !=
|
||||||
|
lvm->map[base_le + st * len].pe + seg_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -264,7 +260,9 @@ static int _check_stripe(struct lv_map *lvm, struct lv_segment *seg,
|
|||||||
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
|
static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
|
||||||
{
|
{
|
||||||
uint32_t st, le = 0, len;
|
uint32_t st, le = 0, len;
|
||||||
|
uint32_t area_len;
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
|
struct segment_type *segtype;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Work out overall striped length
|
* Work out overall striped length
|
||||||
@@ -276,43 +274,46 @@ static int _read_stripes(struct cmd_context *cmd, struct lv_map *lvm)
|
|||||||
}
|
}
|
||||||
len = lvm->lv->le_count / lvm->stripes;
|
len = lvm->lv->le_count / lvm->stripes;
|
||||||
|
|
||||||
|
if (!(segtype = get_segtype_from_string(cmd, "striped"))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
while (le < len) {
|
while (le < len) {
|
||||||
if (!(seg = alloc_lv_segment(cmd->mem, lvm->stripes))) {
|
area_len = 1;
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
seg->lv = lvm->lv;
|
|
||||||
if (!(seg->segtype = get_segtype_from_string(cmd, "striped"))) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
seg->stripe_size = lvm->stripe_size;
|
|
||||||
seg->le = seg->area_count * le;
|
|
||||||
seg->len = 1;
|
|
||||||
seg->area_len = 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set up start positions of each stripe in this segment
|
|
||||||
*/
|
|
||||||
for (st = 0; st < seg->area_count; st++) {
|
|
||||||
seg->area[st].u.pv.pv = lvm->map[le + st * len].pv;
|
|
||||||
seg->area[st].u.pv.pe = lvm->map[le + st * len].pe;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find how many blocks are contiguous in all stripes
|
* Find how many blocks are contiguous in all stripes
|
||||||
* and so can form part of this segment
|
* and so can form part of this segment
|
||||||
*/
|
*/
|
||||||
while (_check_stripe(lvm, seg, le, len)) {
|
while (_check_stripe(lvm, lvm->stripes,
|
||||||
seg->len++;
|
area_len * lvm->stripes, le, len))
|
||||||
seg->area_len++;
|
area_len++;
|
||||||
|
|
||||||
|
if (!(seg = alloc_lv_segment(cmd->mem, segtype, lvm->lv,
|
||||||
|
lvm->stripes * le,
|
||||||
|
lvm->stripes * area_len,
|
||||||
|
0, lvm->stripe_size, NULL,
|
||||||
|
lvm->stripes,
|
||||||
|
area_len, 0, 0, 0))) {
|
||||||
|
log_error("Failed to allocate striped segment.");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
le += seg->len;
|
/*
|
||||||
seg->len *= seg->area_count;
|
* Set up start positions of each stripe in this segment
|
||||||
|
*/
|
||||||
|
for (st = 0; st < seg->area_count; st++)
|
||||||
|
if (!set_lv_segment_area_pv(seg, st,
|
||||||
|
lvm->map[le + st * len].pv,
|
||||||
|
lvm->map[le + st * len].pe)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
list_add(&lvm->lv->segments, &seg->list);
|
list_add(&lvm->lv->segments, &seg->list);
|
||||||
|
|
||||||
|
le += seg->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -324,13 +325,13 @@ static int _build_segments(struct cmd_context *cmd, struct lv_map *lvm)
|
|||||||
_read_linear(cmd, lvm));
|
_read_linear(cmd, lvm));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _build_all_segments(struct cmd_context *cmd, struct hash_table *maps)
|
static int _build_all_segments(struct cmd_context *cmd, struct dm_hash_table *maps)
|
||||||
{
|
{
|
||||||
struct hash_node *n;
|
struct dm_hash_node *n;
|
||||||
struct lv_map *lvm;
|
struct lv_map *lvm;
|
||||||
|
|
||||||
for (n = hash_get_first(maps); n; n = hash_get_next(maps, n)) {
|
for (n = dm_hash_get_first(maps); n; n = dm_hash_get_next(maps, n)) {
|
||||||
lvm = (struct lv_map *) hash_get_data(maps, n);
|
lvm = (struct lv_map *) dm_hash_get_data(maps, n);
|
||||||
if (!_build_segments(cmd, lvm)) {
|
if (!_build_segments(cmd, lvm)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -344,8 +345,8 @@ int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
|||||||
struct list *pvds)
|
struct list *pvds)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
struct pool *scratch = pool_create(10 * 1024);
|
struct dm_pool *scratch = dm_pool_create("lvm1 import_extents", 10 * 1024);
|
||||||
struct hash_table *maps;
|
struct dm_hash_table *maps;
|
||||||
|
|
||||||
if (!scratch) {
|
if (!scratch) {
|
||||||
stack;
|
stack;
|
||||||
@@ -375,7 +376,7 @@ int import_extents(struct cmd_context *cmd, struct volume_group *vg,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
if (maps)
|
if (maps)
|
||||||
hash_destroy(maps);
|
dm_hash_destroy(maps);
|
||||||
pool_destroy(scratch);
|
dm_pool_destroy(scratch);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ int calculate_layout(struct disk_list *dl)
|
|||||||
int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
||||||
uint32_t max_extent_count, uint64_t pe_start)
|
uint32_t max_extent_count, uint64_t pe_start)
|
||||||
{
|
{
|
||||||
struct pv_disk *pvd = dbg_malloc(sizeof(*pvd));
|
struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
|
||||||
uint32_t end;
|
uint32_t end;
|
||||||
|
|
||||||
if (!pvd) {
|
if (!pvd) {
|
||||||
@@ -138,7 +138,7 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
|||||||
if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
|
if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
|
||||||
log_error("Too few extents on %s. Try smaller extent size.",
|
log_error("Too few extents on %s. Try smaller extent size.",
|
||||||
dev_name(pv->dev));
|
dev_name(pv->dev));
|
||||||
dbg_free(pvd);
|
dm_free(pvd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,13 +160,13 @@ int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
|
|||||||
log_error("Metadata extent limit (%u) exceeded for %s - "
|
log_error("Metadata extent limit (%u) exceeded for %s - "
|
||||||
"%u required", MAX_PE_TOTAL, dev_name(pv->dev),
|
"%u required", MAX_PE_TOTAL, dev_name(pv->dev),
|
||||||
pvd->pe_total);
|
pvd->pe_total);
|
||||||
dbg_free(pvd);
|
dm_free(pvd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pv->pe_count = pvd->pe_total;
|
pv->pe_count = pvd->pe_total;
|
||||||
pv->pe_start = pvd->pe_start;
|
pv->pe_start = pvd->pe_start;
|
||||||
/* We can't set pe_size here without breaking LVM1 compatibility */
|
/* We can't set pe_size here without breaking LVM1 compatibility */
|
||||||
dbg_free(pvd);
|
dm_free(pvd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ static void _destroy_label(struct labeller *l, struct label *label)
|
|||||||
|
|
||||||
static void _destroy(struct labeller *l)
|
static void _destroy(struct labeller *l)
|
||||||
{
|
{
|
||||||
dbg_free(l);
|
dm_free(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct label_ops _lvm1_ops = {
|
struct label_ops _lvm1_ops = {
|
||||||
@@ -107,7 +107,7 @@ struct labeller *lvm1_labeller_create(struct format_type *fmt)
|
|||||||
{
|
{
|
||||||
struct labeller *l;
|
struct labeller *l;
|
||||||
|
|
||||||
if (!(l = dbg_malloc(sizeof(*l)))) {
|
if (!(l = dm_malloc(sizeof(*l)))) {
|
||||||
log_err("Couldn't allocate labeller object.");
|
log_err("Couldn't allocate labeller object.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "disk-rep.h"
|
#include "disk-rep.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -27,10 +26,9 @@
|
|||||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||||
const char *candidate_vg, int *result)
|
const char *candidate_vg, int *result)
|
||||||
{
|
{
|
||||||
struct list *pvh;
|
|
||||||
struct list all_pvs;
|
struct list all_pvs;
|
||||||
struct disk_list *dl;
|
struct disk_list *dl;
|
||||||
struct pool *mem = pool_create(10 * 1024);
|
struct dm_pool *mem = dm_pool_create("lvm1 vg_number", 10 * 1024);
|
||||||
int numbers[MAX_VG], i, r = 0;
|
int numbers[MAX_VG], i, r = 0;
|
||||||
|
|
||||||
list_init(&all_pvs);
|
list_init(&all_pvs);
|
||||||
@@ -47,8 +45,7 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
|||||||
|
|
||||||
memset(numbers, 0, sizeof(numbers));
|
memset(numbers, 0, sizeof(numbers));
|
||||||
|
|
||||||
list_iterate(pvh, &all_pvs) {
|
list_iterate_items(dl, &all_pvs) {
|
||||||
dl = list_item(pvh, struct disk_list);
|
|
||||||
if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
|
if (!*dl->pvd.vg_name || !strcmp(dl->pvd.vg_name, candidate_vg))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -64,6 +61,6 @@ int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ SOURCES =\
|
|||||||
|
|
||||||
LIB_SHARED = liblvm2formatpool.so
|
LIB_SHARED = liblvm2formatpool.so
|
||||||
|
|
||||||
include ../../make.tmpl
|
include $(top_srcdir)/make.tmpl
|
||||||
|
|
||||||
.PHONY: install
|
|
||||||
|
|
||||||
install: liblvm2formatpool.so
|
install: liblvm2formatpool.so
|
||||||
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
$(INSTALL) -D $(OWNER) $(GROUP) -m 555 $(STRIP) $< \
|
||||||
|
|||||||
@@ -14,12 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "list.h"
|
|
||||||
#include "xlate.h"
|
#include "xlate.h"
|
||||||
|
|
||||||
#include "disk_rep.h"
|
#include "disk_rep.h"
|
||||||
@@ -35,7 +33,7 @@
|
|||||||
#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
|
#define CPOUT_64(x, y) {(y) = xlate64_be((x));}
|
||||||
|
|
||||||
static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
|
static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
|
||||||
struct pool *mem, struct pool_list *pl,
|
struct dm_pool *mem, struct pool_list *pl,
|
||||||
const char *vg_name)
|
const char *vg_name)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
@@ -57,12 +55,9 @@ static int __read_pool_disk(const struct format_type *fmt, struct device *dev,
|
|||||||
|
|
||||||
static void _add_pl_to_list(struct list *head, struct pool_list *data)
|
static void _add_pl_to_list(struct list *head, struct pool_list *data)
|
||||||
{
|
{
|
||||||
struct list *pvdh;
|
|
||||||
struct pool_list *pl;
|
struct pool_list *pl;
|
||||||
|
|
||||||
list_iterate(pvdh, head) {
|
list_iterate_items(pl, head) {
|
||||||
pl = list_item(pvdh, struct pool_list);
|
|
||||||
|
|
||||||
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
|
if (id_equal(&data->pv_uuid, &pl->pv_uuid)) {
|
||||||
char uuid[ID_LEN + 7];
|
char uuid[ID_LEN + 7];
|
||||||
|
|
||||||
@@ -76,7 +71,7 @@ static void _add_pl_to_list(struct list *head, struct pool_list *data)
|
|||||||
}
|
}
|
||||||
log_very_verbose("Duplicate PV %s - using md %s",
|
log_very_verbose("Duplicate PV %s - using md %s",
|
||||||
uuid, dev_name(data->dev));
|
uuid, dev_name(data->dev));
|
||||||
list_del(pvdh);
|
list_del(&pl->list);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,15 +238,13 @@ void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
static int _read_vg_pds(const struct format_type *fmt, struct dm_pool *mem,
|
||||||
struct lvmcache_vginfo *vginfo, struct list *head,
|
struct lvmcache_vginfo *vginfo, struct list *head,
|
||||||
uint32_t *devcount)
|
uint32_t *devcount)
|
||||||
{
|
{
|
||||||
|
struct lvmcache_info *info;
|
||||||
struct list *vgih = NULL;
|
|
||||||
struct device *dev;
|
|
||||||
struct pool_list *pl = NULL;
|
struct pool_list *pl = NULL;
|
||||||
struct pool *tmpmem = NULL;
|
struct dm_pool *tmpmem;
|
||||||
|
|
||||||
uint32_t sp_count = 0;
|
uint32_t sp_count = 0;
|
||||||
uint32_t *sp_devs = NULL;
|
uint32_t *sp_devs = NULL;
|
||||||
@@ -259,28 +252,28 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
|||||||
|
|
||||||
/* FIXME: maybe should return a different error in memory
|
/* FIXME: maybe should return a different error in memory
|
||||||
* allocation failure */
|
* allocation failure */
|
||||||
if (!(tmpmem = pool_create(512))) {
|
if (!(tmpmem = dm_pool_create("pool read_vg", 512))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_iterate(vgih, &vginfo->infos) {
|
list_iterate_items(info, &vginfo->infos) {
|
||||||
dev = list_item(vgih, struct lvmcache_info)->dev;
|
if (info->dev &&
|
||||||
if (dev &&
|
!(pl = read_pool_disk(fmt, info->dev, mem, vginfo->vgname)))
|
||||||
!(pl = read_pool_disk(fmt, dev, mem, vginfo->vgname)))
|
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
* We need to keep track of the total expected number
|
* We need to keep track of the total expected number
|
||||||
* of devices per subpool
|
* of devices per subpool
|
||||||
*/
|
*/
|
||||||
if (!sp_count) {
|
if (!sp_count) {
|
||||||
|
/* FIXME pl left uninitialised if !info->dev */
|
||||||
sp_count = pl->pd.pl_subpools;
|
sp_count = pl->pd.pl_subpools;
|
||||||
if (!(sp_devs =
|
if (!(sp_devs =
|
||||||
pool_zalloc(tmpmem,
|
dm_pool_zalloc(tmpmem,
|
||||||
sizeof(uint32_t) * sp_count))) {
|
sizeof(uint32_t) * sp_count))) {
|
||||||
log_error("Unable to allocate %d 32-bit uints",
|
log_error("Unable to allocate %d 32-bit uints",
|
||||||
sp_count);
|
sp_count);
|
||||||
pool_destroy(tmpmem);
|
dm_pool_destroy(tmpmem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,11 +291,10 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*devcount = 0;
|
*devcount = 0;
|
||||||
for (i = 0; i < sp_count; i++) {
|
for (i = 0; i < sp_count; i++)
|
||||||
*devcount += sp_devs[i];
|
*devcount += sp_devs[i];
|
||||||
}
|
|
||||||
|
|
||||||
pool_destroy(tmpmem);
|
dm_pool_destroy(tmpmem);
|
||||||
|
|
||||||
if (pl && *pl->pd.pl_pool_name)
|
if (pl && *pl->pd.pl_pool_name)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -312,7 +304,7 @@ static int _read_vg_pds(const struct format_type *fmt, struct pool *mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int read_pool_pds(const struct format_type *fmt, const char *vg_name,
|
int read_pool_pds(const struct format_type *fmt, const char *vg_name,
|
||||||
struct pool *mem, struct list *pdhead)
|
struct dm_pool *mem, struct list *pdhead)
|
||||||
{
|
{
|
||||||
struct lvmcache_vginfo *vginfo;
|
struct lvmcache_vginfo *vginfo;
|
||||||
uint32_t totaldevs;
|
uint32_t totaldevs;
|
||||||
@@ -357,7 +349,7 @@ int read_pool_pds(const struct format_type *fmt, const char *vg_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct pool_list *read_pool_disk(const struct format_type *fmt,
|
struct pool_list *read_pool_disk(const struct format_type *fmt,
|
||||||
struct device *dev, struct pool *mem,
|
struct device *dev, struct dm_pool *mem,
|
||||||
const char *vg_name)
|
const char *vg_name)
|
||||||
{
|
{
|
||||||
struct pool_list *pl;
|
struct pool_list *pl;
|
||||||
@@ -367,7 +359,7 @@ struct pool_list *read_pool_disk(const struct format_type *fmt,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pl = pool_zalloc(mem, sizeof(*pl)))) {
|
if (!(pl = dm_pool_zalloc(mem, sizeof(*pl)))) {
|
||||||
log_error("Unable to allocate pool list structure");
|
log_error("Unable to allocate pool list structure");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "pool.h"
|
|
||||||
|
#define MINOR_OFFSET 65536
|
||||||
|
|
||||||
/* From NSP.cf */
|
/* From NSP.cf */
|
||||||
#define NSPMajorVersion 4
|
#define NSPMajorVersion 4
|
||||||
@@ -66,29 +67,6 @@ struct pool_list;
|
|||||||
struct user_subpool;
|
struct user_subpool;
|
||||||
struct user_device;
|
struct user_device;
|
||||||
|
|
||||||
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
|
|
||||||
|
|
||||||
/* Generic Labels */
|
|
||||||
#define SPTYPE_DATA (0x00000000)
|
|
||||||
|
|
||||||
/* GFS specific labels */
|
|
||||||
#define SPTYPE_GFS_DATA (0x68011670)
|
|
||||||
#define SPTYPE_GFS_JOURNAL (0x69011670)
|
|
||||||
|
|
||||||
struct sptype_name {
|
|
||||||
const char *name;
|
|
||||||
uint32_t label;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct sptype_name sptype_names[] = {
|
|
||||||
{"data", SPTYPE_DATA},
|
|
||||||
|
|
||||||
{"gfs_data", SPTYPE_GFS_DATA},
|
|
||||||
{"gfs_journal", SPTYPE_GFS_JOURNAL},
|
|
||||||
|
|
||||||
{"", 0x0} /* This must be the last flag. */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pool_disk {
|
struct pool_disk {
|
||||||
uint64_t pl_magic; /* Pool magic number */
|
uint64_t pl_magic; /* Pool magic number */
|
||||||
uint64_t pl_pool_id; /* Unique pool identifier */
|
uint64_t pl_pool_id; /* Unique pool identifier */
|
||||||
@@ -159,20 +137,20 @@ int read_pool_label(struct pool_list *pl, struct labeller *l,
|
|||||||
void pool_label_out(struct pool_disk *pl, char *buf);
|
void pool_label_out(struct pool_disk *pl, char *buf);
|
||||||
void pool_label_in(struct pool_disk *pl, char *buf);
|
void pool_label_in(struct pool_disk *pl, char *buf);
|
||||||
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
|
void get_pool_uuid(char *uuid, uint64_t poolid, uint32_t spid, uint32_t devid);
|
||||||
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls);
|
int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct list *pls);
|
||||||
int import_pool_lvs(struct volume_group *vg, struct pool *mem,
|
int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem,
|
||||||
struct list *pls);
|
struct list *pls);
|
||||||
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
|
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
|
||||||
struct list *pvs, struct pool *mem, struct list *pls);
|
struct list *pvs, struct dm_pool *mem, struct list *pls);
|
||||||
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
|
int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||||
struct volume_group *vg, struct physical_volume *pv,
|
struct volume_group *vg, struct physical_volume *pv,
|
||||||
struct pool_list *pl);
|
struct pool_list *pl);
|
||||||
int import_pool_segments(struct list *lvs, struct pool *mem,
|
int import_pool_segments(struct list *lvs, struct dm_pool *mem,
|
||||||
struct user_subpool *usp, int sp_count);
|
struct user_subpool *usp, int sp_count);
|
||||||
int read_pool_pds(const struct format_type *fmt, const char *vgname,
|
int read_pool_pds(const struct format_type *fmt, const char *vgname,
|
||||||
struct pool *mem, struct list *head);
|
struct dm_pool *mem, struct list *head);
|
||||||
struct pool_list *read_pool_disk(const struct format_type *fmt,
|
struct pool_list *read_pool_disk(const struct format_type *fmt,
|
||||||
struct device *dev, struct pool *mem,
|
struct device *dev, struct dm_pool *mem,
|
||||||
const char *vg_name);
|
const char *vg_name);
|
||||||
|
|
||||||
#endif /* DISK_REP_POOL_FORMAT_H */
|
#endif /* DISK_REP_POOL_FORMAT_H */
|
||||||
|
|||||||
@@ -14,12 +14,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "limits.h"
|
#include "limits.h"
|
||||||
#include "list.h"
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
@@ -30,11 +27,9 @@
|
|||||||
#define FMT_POOL_NAME "pool"
|
#define FMT_POOL_NAME "pool"
|
||||||
|
|
||||||
/* Must be called after pvs are imported */
|
/* Must be called after pvs are imported */
|
||||||
static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
|
static struct user_subpool *_build_usp(struct list *pls, struct dm_pool *mem,
|
||||||
int *sps)
|
int *sps)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct list *plhs;
|
|
||||||
struct pool_list *pl;
|
struct pool_list *pl;
|
||||||
struct user_subpool *usp = NULL, *cur_sp = NULL;
|
struct user_subpool *usp = NULL, *cur_sp = NULL;
|
||||||
struct user_device *cur_dev = NULL;
|
struct user_device *cur_dev = NULL;
|
||||||
@@ -43,11 +38,9 @@ static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
|
|||||||
* FIXME: Need to do some checks here - I'm tempted to add a
|
* FIXME: Need to do some checks here - I'm tempted to add a
|
||||||
* user_pool structure and build the entire thing to check against.
|
* user_pool structure and build the entire thing to check against.
|
||||||
*/
|
*/
|
||||||
list_iterate(plhs, pls) {
|
list_iterate_items(pl, pls) {
|
||||||
pl = list_item(plhs, struct pool_list);
|
|
||||||
|
|
||||||
*sps = pl->pd.pl_subpools;
|
*sps = pl->pd.pl_subpools;
|
||||||
if (!usp && (!(usp = pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
|
if (!usp && (!(usp = dm_pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
|
||||||
log_error("Unable to allocate %d subpool structures",
|
log_error("Unable to allocate %d subpool structures",
|
||||||
*sps);
|
*sps);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -65,20 +58,20 @@ static struct user_subpool *_build_usp(struct list *pls, struct pool *mem,
|
|||||||
|
|
||||||
if (!cur_sp->devs &&
|
if (!cur_sp->devs &&
|
||||||
(!(cur_sp->devs =
|
(!(cur_sp->devs =
|
||||||
pool_zalloc(mem,
|
dm_pool_zalloc(mem,
|
||||||
sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
|
sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
|
||||||
|
|
||||||
log_error("Unable to allocate %d pool_device "
|
log_error("Unable to allocate %d pool_device "
|
||||||
"structures", pl->pd.pl_sp_devs);
|
"structures", pl->pd.pl_sp_devs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
|
cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
|
||||||
cur_dev->sp_id = cur_sp->id;
|
cur_dev->sp_id = cur_sp->id;
|
||||||
cur_dev->devid = pl->pd.pl_sp_id;
|
cur_dev->devid = pl->pd.pl_sp_id;
|
||||||
cur_dev->blocks = pl->pd.pl_blocks;
|
cur_dev->blocks = pl->pd.pl_blocks;
|
||||||
cur_dev->pv = pl->pv;
|
cur_dev->pv = pl->pv;
|
||||||
cur_dev->initialized = 1;
|
cur_dev->initialized = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return usp;
|
return usp;
|
||||||
@@ -107,15 +100,15 @@ static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct volume_group *_build_vg_from_pds(struct format_instance
|
static struct volume_group *_build_vg_from_pds(struct format_instance
|
||||||
*fid, struct pool *mem,
|
*fid, struct dm_pool *mem,
|
||||||
struct list *pds)
|
struct list *pds)
|
||||||
{
|
{
|
||||||
struct pool *smem = fid->fmt->cmd->mem;
|
struct dm_pool *smem = fid->fmt->cmd->mem;
|
||||||
struct volume_group *vg = NULL;
|
struct volume_group *vg = NULL;
|
||||||
struct user_subpool *usp = NULL;
|
struct user_subpool *usp = NULL;
|
||||||
int sp_count;
|
int sp_count;
|
||||||
|
|
||||||
if (!(vg = pool_zalloc(smem, sizeof(*vg)))) {
|
if (!(vg = dm_pool_zalloc(smem, sizeof(*vg)))) {
|
||||||
log_error("Unable to allocate volume group structure");
|
log_error("Unable to allocate volume group structure");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -132,7 +125,6 @@ static struct volume_group *_build_vg_from_pds(struct format_instance
|
|||||||
vg->system_id = NULL;
|
vg->system_id = NULL;
|
||||||
list_init(&vg->pvs);
|
list_init(&vg->pvs);
|
||||||
list_init(&vg->lvs);
|
list_init(&vg->lvs);
|
||||||
list_init(&vg->snapshots);
|
|
||||||
list_init(&vg->tags);
|
list_init(&vg->tags);
|
||||||
|
|
||||||
if (!import_pool_vg(vg, smem, pds)) {
|
if (!import_pool_vg(vg, smem, pds)) {
|
||||||
@@ -181,7 +173,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
|||||||
const char *vg_name,
|
const char *vg_name,
|
||||||
struct metadata_area *mda)
|
struct metadata_area *mda)
|
||||||
{
|
{
|
||||||
struct pool *mem = pool_create(1024);
|
struct dm_pool *mem = dm_pool_create("pool vg_read", 1024);
|
||||||
struct list pds;
|
struct list pds;
|
||||||
struct volume_group *vg = NULL;
|
struct volume_group *vg = NULL;
|
||||||
|
|
||||||
@@ -210,7 +202,7 @@ static struct volume_group *_vg_read(struct format_instance *fid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return vg;
|
return vg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +219,7 @@ static int _pv_setup(const struct format_type *fmt,
|
|||||||
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
||||||
struct physical_volume *pv, struct list *mdas)
|
struct physical_volume *pv, struct list *mdas)
|
||||||
{
|
{
|
||||||
struct pool *mem = pool_create(1024);
|
struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
|
||||||
struct pool_list *pl;
|
struct pool_list *pl;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@@ -264,7 +256,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name,
|
|||||||
r = 1;
|
r = 1;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pool_destroy(mem);
|
dm_pool_destroy(mem);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +273,7 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
|
|||||||
struct format_instance *fid;
|
struct format_instance *fid;
|
||||||
struct metadata_area *mda;
|
struct metadata_area *mda;
|
||||||
|
|
||||||
if (!(fid = pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
|
if (!(fid = dm_pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
|
||||||
log_error("Unable to allocate format instance structure for "
|
log_error("Unable to allocate format instance structure for "
|
||||||
"pool format");
|
"pool format");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -291,10 +283,10 @@ static struct format_instance *_create_instance(const struct format_type *fmt,
|
|||||||
list_init(&fid->metadata_areas);
|
list_init(&fid->metadata_areas);
|
||||||
|
|
||||||
/* Define a NULL metadata area */
|
/* Define a NULL metadata area */
|
||||||
if (!(mda = pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
|
if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
|
||||||
log_error("Unable to allocate metadata area structure "
|
log_error("Unable to allocate metadata area structure "
|
||||||
"for pool format");
|
"for pool format");
|
||||||
pool_free(fmt->cmd->mem, fid);
|
dm_pool_free(fmt->cmd->mem, fid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +304,7 @@ static void _destroy_instance(struct format_instance *fid)
|
|||||||
|
|
||||||
static void _destroy(const struct format_type *fmt)
|
static void _destroy(const struct format_type *fmt)
|
||||||
{
|
{
|
||||||
dbg_free((void *) fmt);
|
dm_free((void *) fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
@@ -332,7 +324,7 @@ struct format_type *init_format(struct cmd_context *cmd);
|
|||||||
struct format_type *init_format(struct cmd_context *cmd)
|
struct format_type *init_format(struct cmd_context *cmd)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct format_type *fmt = dbg_malloc(sizeof(*fmt));
|
struct format_type *fmt = dm_malloc(sizeof(*fmt));
|
||||||
|
|
||||||
if (!fmt) {
|
if (!fmt) {
|
||||||
log_error("Unable to allocate format type structure for pool "
|
log_error("Unable to allocate format type structure for pool "
|
||||||
@@ -357,5 +349,7 @@ struct format_type *init_format(struct cmd_context *cmd)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_very_verbose("Initialised format: %s", fmt->name);
|
||||||
|
|
||||||
return fmt;
|
return fmt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,26 +14,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
#include "disk_rep.h"
|
#include "disk_rep.h"
|
||||||
|
#include "sptype_names.h"
|
||||||
#include "lv_alloc.h"
|
#include "lv_alloc.h"
|
||||||
|
#include "pv_alloc.h"
|
||||||
#include "str_list.h"
|
#include "str_list.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "segtypes.h"
|
#include "segtype.h"
|
||||||
|
|
||||||
/* This file contains only imports at the moment... */
|
/* This file contains only imports at the moment... */
|
||||||
|
|
||||||
int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
|
int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct list *pls)
|
||||||
{
|
{
|
||||||
struct list *plhs;
|
|
||||||
struct pool_list *pl;
|
struct pool_list *pl;
|
||||||
|
|
||||||
list_iterate(plhs, pls) {
|
list_iterate_items(pl, pls) {
|
||||||
pl = list_item(plhs, struct pool_list);
|
|
||||||
|
|
||||||
vg->extent_count +=
|
vg->extent_count +=
|
||||||
((pl->pd.pl_blocks) / POOL_PE_SIZE);
|
((pl->pd.pl_blocks) / POOL_PE_SIZE);
|
||||||
|
|
||||||
@@ -42,11 +40,11 @@ int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
|
|||||||
if (vg->name)
|
if (vg->name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
vg->name = pool_strdup(mem, pl->pd.pl_pool_name);
|
vg->name = dm_pool_strdup(mem, pl->pd.pl_pool_name);
|
||||||
get_pool_vg_uuid(&vg->id, &pl->pd);
|
get_pool_vg_uuid(&vg->id, &pl->pd);
|
||||||
vg->extent_size = POOL_PE_SIZE;
|
vg->extent_size = POOL_PE_SIZE;
|
||||||
vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
|
vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
|
||||||
vg->free_count = 0;
|
vg->free_count = vg->extent_count;
|
||||||
vg->max_lv = 1;
|
vg->max_lv = 1;
|
||||||
vg->max_pv = POOL_MAX_DEVICES;
|
vg->max_pv = POOL_MAX_DEVICES;
|
||||||
vg->alloc = ALLOC_NORMAL;
|
vg->alloc = ALLOC_NORMAL;
|
||||||
@@ -56,11 +54,10 @@ int import_pool_vg(struct volume_group *vg, struct pool *mem, struct list *pls)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
|
int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem, struct list *pls)
|
||||||
{
|
{
|
||||||
struct pool_list *pl;
|
struct pool_list *pl;
|
||||||
struct list *plhs;
|
struct lv_list *lvl = dm_pool_zalloc(mem, sizeof(*lvl));
|
||||||
struct lv_list *lvl = pool_zalloc(mem, sizeof(*lvl));
|
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
|
|
||||||
if (!lvl) {
|
if (!lvl) {
|
||||||
@@ -68,7 +65,7 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(lvl->lv = pool_zalloc(mem, sizeof(*lvl->lv)))) {
|
if (!(lvl->lv = dm_pool_zalloc(mem, sizeof(*lvl->lv)))) {
|
||||||
log_error("Unable to allocate logical volume structure");
|
log_error("Unable to allocate logical volume structure");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -81,18 +78,18 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
|
|||||||
lv->name = NULL;
|
lv->name = NULL;
|
||||||
lv->le_count = 0;
|
lv->le_count = 0;
|
||||||
lv->read_ahead = 0;
|
lv->read_ahead = 0;
|
||||||
|
lv->snapshot = NULL;
|
||||||
|
list_init(&lv->snapshot_segs);
|
||||||
list_init(&lv->segments);
|
list_init(&lv->segments);
|
||||||
list_init(&lv->tags);
|
list_init(&lv->tags);
|
||||||
|
|
||||||
list_iterate(plhs, pls) {
|
list_iterate_items(pl, pls) {
|
||||||
pl = list_item(plhs, struct pool_list);
|
|
||||||
|
|
||||||
lv->size += pl->pd.pl_blocks;
|
lv->size += pl->pd.pl_blocks;
|
||||||
|
|
||||||
if (lv->name)
|
if (lv->name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(lv->name = pool_strdup(mem, pl->pd.pl_pool_name))) {
|
if (!(lv->name = dm_pool_strdup(mem, pl->pd.pl_pool_name))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -107,10 +104,12 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
|
|||||||
/* for pool a minor of 0 is dynamic */
|
/* for pool a minor of 0 is dynamic */
|
||||||
if (pl->pd.pl_minor) {
|
if (pl->pd.pl_minor) {
|
||||||
lv->status |= FIXED_MINOR;
|
lv->status |= FIXED_MINOR;
|
||||||
lv->minor = pl->pd.pl_minor;
|
lv->minor = pl->pd.pl_minor + MINOR_OFFSET;
|
||||||
} else {
|
} else {
|
||||||
lv->minor = -1;
|
lv->minor = -1;
|
||||||
}
|
}
|
||||||
|
lv->snapshot = NULL;
|
||||||
|
list_init(&lv->snapshot_segs);
|
||||||
list_init(&lv->segments);
|
list_init(&lv->segments);
|
||||||
list_init(&lv->tags);
|
list_init(&lv->tags);
|
||||||
}
|
}
|
||||||
@@ -124,20 +123,17 @@ int import_pool_lvs(struct volume_group *vg, struct pool *mem, struct list *pls)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
|
int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
|
||||||
struct list *pvs, struct pool *mem, struct list *pls)
|
struct list *pvs, struct dm_pool *mem, struct list *pls)
|
||||||
{
|
{
|
||||||
struct pv_list *pvl;
|
struct pv_list *pvl;
|
||||||
struct pool_list *pl;
|
struct pool_list *pl;
|
||||||
struct list *plhs;
|
|
||||||
|
|
||||||
list_iterate(plhs, pls) {
|
list_iterate_items(pl, pls) {
|
||||||
pl = list_item(plhs, struct pool_list);
|
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
|
||||||
|
|
||||||
if (!(pvl = pool_zalloc(mem, sizeof(*pvl)))) {
|
|
||||||
log_error("Unable to allocate pv list structure");
|
log_error("Unable to allocate pv list structure");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!(pvl->pv = pool_zalloc(mem, sizeof(*pvl->pv)))) {
|
if (!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
|
||||||
log_error("Unable to allocate pv structure");
|
log_error("Unable to allocate pv structure");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -146,14 +142,14 @@ int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
|
|||||||
}
|
}
|
||||||
pl->pv = pvl->pv;
|
pl->pv = pvl->pv;
|
||||||
pvl->mdas = NULL;
|
pvl->mdas = NULL;
|
||||||
pvl->alloc_areas = NULL;
|
pvl->pe_ranges = NULL;
|
||||||
list_add(pvs, &pvl->list);
|
list_add(pvs, &pvl->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_pool_pv(const struct format_type *fmt, struct pool *mem,
|
int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
|
||||||
struct volume_group *vg, struct physical_volume *pv,
|
struct volume_group *vg, struct physical_volume *pv,
|
||||||
struct pool_list *pl)
|
struct pool_list *pl)
|
||||||
{
|
{
|
||||||
@@ -165,7 +161,7 @@ int import_pool_pv(const struct format_type *fmt, struct pool *mem,
|
|||||||
pv->fmt = fmt;
|
pv->fmt = fmt;
|
||||||
|
|
||||||
pv->dev = pl->dev;
|
pv->dev = pl->dev;
|
||||||
if (!(pv->vg_name = pool_strdup(mem, pd->pl_pool_name))) {
|
if (!(pv->vg_name = dm_pool_strdup(mem, pd->pl_pool_name))) {
|
||||||
log_error("Unable to duplicate vg_name string");
|
log_error("Unable to duplicate vg_name string");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -174,9 +170,15 @@ int import_pool_pv(const struct format_type *fmt, struct pool *mem,
|
|||||||
pv->pe_size = POOL_PE_SIZE;
|
pv->pe_size = POOL_PE_SIZE;
|
||||||
pv->pe_start = POOL_PE_START;
|
pv->pe_start = POOL_PE_START;
|
||||||
pv->pe_count = pv->size / POOL_PE_SIZE;
|
pv->pe_count = pv->size / POOL_PE_SIZE;
|
||||||
pv->pe_alloc_count = pv->pe_count;
|
pv->pe_alloc_count = 0;
|
||||||
|
|
||||||
list_init(&pv->tags);
|
list_init(&pv->tags);
|
||||||
|
list_init(&pv->segments);
|
||||||
|
|
||||||
|
if (!alloc_pv_segment_whole_pv(mem, pv)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -194,101 +196,107 @@ static const char *_cvt_sptype(uint32_t sptype)
|
|||||||
return sptype_names[i].name;
|
return sptype_names[i].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _add_stripe_seg(struct pool *mem,
|
static int _add_stripe_seg(struct dm_pool *mem,
|
||||||
struct user_subpool *usp, struct logical_volume *lv,
|
struct user_subpool *usp, struct logical_volume *lv,
|
||||||
uint32_t *le_cur)
|
uint32_t *le_cur)
|
||||||
{
|
{
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
|
struct segment_type *segtype;
|
||||||
int j;
|
int j;
|
||||||
|
uint32_t area_len;
|
||||||
|
|
||||||
if (!(seg = alloc_lv_segment(mem, usp->num_devs))) {
|
if (usp->striping & (usp->striping - 1)) {
|
||||||
log_error("Unable to allocate striped lv_segment structure");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(usp->striping & (usp->striping - 1)) {
|
|
||||||
log_error("Stripe size must be a power of 2");
|
log_error("Stripe size must be a power of 2");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
seg->stripe_size = usp->striping;
|
|
||||||
seg->status |= 0;
|
area_len = (usp->devs[0].blocks) / POOL_PE_SIZE;
|
||||||
seg->le += *le_cur;
|
|
||||||
|
if (!(segtype = get_segtype_from_string(lv->vg->cmd,
|
||||||
|
"striped"))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
|
||||||
|
area_len * usp->num_devs, 0,
|
||||||
|
usp->striping, NULL, usp->num_devs,
|
||||||
|
area_len, 0, 0, 0))) {
|
||||||
|
log_error("Unable to allocate striped lv_segment structure");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < usp->num_devs; j++)
|
||||||
|
if (!set_lv_segment_area_pv(seg, j, usp->devs[j].pv, 0)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* add the subpool type to the segment tag list */
|
/* add the subpool type to the segment tag list */
|
||||||
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
|
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
|
||||||
|
|
||||||
for (j = 0; j < usp->num_devs; j++) {
|
|
||||||
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
|
|
||||||
"striped"))) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
|
||||||
seg->len += seg->area_len;
|
|
||||||
*le_cur += seg->area_len;
|
|
||||||
seg->lv = lv;
|
|
||||||
|
|
||||||
seg->area[j].type = AREA_PV;
|
|
||||||
seg->area[j].u.pv.pv = usp->devs[j].pv;
|
|
||||||
seg->area[j].u.pv.pe = 0;
|
|
||||||
}
|
|
||||||
list_add(&lv->segments, &seg->list);
|
list_add(&lv->segments, &seg->list);
|
||||||
|
|
||||||
|
*le_cur += seg->len;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _add_linear_seg(struct pool *mem,
|
static int _add_linear_seg(struct dm_pool *mem,
|
||||||
struct user_subpool *usp, struct logical_volume *lv,
|
struct user_subpool *usp, struct logical_volume *lv,
|
||||||
uint32_t *le_cur)
|
uint32_t *le_cur)
|
||||||
{
|
{
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
|
struct segment_type *segtype;
|
||||||
int j;
|
int j;
|
||||||
|
uint32_t area_len;
|
||||||
|
|
||||||
|
if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped"))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (j = 0; j < usp->num_devs; j++) {
|
for (j = 0; j < usp->num_devs; j++) {
|
||||||
/* linear segments only have 1 data area */
|
area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
||||||
if (!(seg = alloc_lv_segment(mem, 1))) {
|
|
||||||
|
if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
|
||||||
|
area_len, 0, usp->striping,
|
||||||
|
NULL, 1, area_len,
|
||||||
|
POOL_PE_SIZE, 0, 0))) {
|
||||||
log_error("Unable to allocate linear lv_segment "
|
log_error("Unable to allocate linear lv_segment "
|
||||||
"structure");
|
"structure");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
seg->stripe_size = usp->striping;
|
|
||||||
seg->le += *le_cur;
|
|
||||||
seg->chunk_size = POOL_PE_SIZE;
|
|
||||||
seg->status |= 0;
|
|
||||||
if (!(seg->segtype = get_segtype_from_string(lv->vg->cmd,
|
|
||||||
"striped"))) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* add the subpool type to the segment tag list */
|
/* add the subpool type to the segment tag list */
|
||||||
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
|
str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
|
||||||
|
|
||||||
seg->lv = lv;
|
if (!set_lv_segment_area_pv(seg, 0, usp->devs[j].pv, 0)) {
|
||||||
|
stack;
|
||||||
seg->area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
|
return 0;
|
||||||
seg->len = seg->area_len;
|
}
|
||||||
*le_cur += seg->len;
|
|
||||||
seg->area[0].type = AREA_PV;
|
|
||||||
seg->area[0].u.pv.pv = usp->devs[j].pv;
|
|
||||||
seg->area[0].u.pv.pe = 0;
|
|
||||||
list_add(&lv->segments, &seg->list);
|
list_add(&lv->segments, &seg->list);
|
||||||
|
|
||||||
|
*le_cur += seg->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_pool_segments(struct list *lvs, struct pool *mem,
|
int import_pool_segments(struct list *lvs, struct dm_pool *mem,
|
||||||
struct user_subpool *usp, int subpools)
|
struct user_subpool *usp, int subpools)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct list *lvhs;
|
|
||||||
struct lv_list *lvl;
|
struct lv_list *lvl;
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
uint32_t le_cur = 0;
|
uint32_t le_cur = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
list_iterate(lvhs, lvs) {
|
list_iterate_items(lvl, lvs) {
|
||||||
lvl = list_item(lvhs, struct lv_list);
|
|
||||||
|
|
||||||
lv = lvl->lv;
|
lv = lvl->lv;
|
||||||
|
|
||||||
|
if (lv->status & SNAPSHOT)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < subpools; i++) {
|
for (i = 0; i < subpools; i++) {
|
||||||
if (usp[i].striping) {
|
if (usp[i].striping) {
|
||||||
if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur)) {
|
if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur)) {
|
||||||
@@ -305,5 +313,4 @@ int import_pool_segments(struct list *lvs, struct pool *mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "xlate.h"
|
#include "xlate.h"
|
||||||
@@ -79,7 +78,7 @@ static void _destroy_label(struct labeller *l, struct label *label)
|
|||||||
|
|
||||||
static void _destroy(struct labeller *l)
|
static void _destroy(struct labeller *l)
|
||||||
{
|
{
|
||||||
dbg_free(l);
|
dm_free(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct label_ops _pool_ops = {
|
struct label_ops _pool_ops = {
|
||||||
@@ -96,7 +95,7 @@ struct labeller *pool_labeller_create(struct format_type *fmt)
|
|||||||
{
|
{
|
||||||
struct labeller *l;
|
struct labeller *l;
|
||||||
|
|
||||||
if (!(l = dbg_malloc(sizeof(*l)))) {
|
if (!(l = dm_malloc(sizeof(*l)))) {
|
||||||
log_error("Couldn't allocate labeller object.");
|
log_error("Couldn't allocate labeller object.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
42
lib/format_pool/sptype_names.h
Normal file
42
lib/format_pool/sptype_names.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
|
||||||
|
* Copyright (C) 2004-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 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 SPTYPE_NAMES_H
|
||||||
|
#define SPTYPE_NAMES_H
|
||||||
|
|
||||||
|
/* This must be kept up to date with sistina/pool/module/pool_sptypes.h */
|
||||||
|
|
||||||
|
/* Generic Labels */
|
||||||
|
#define SPTYPE_DATA (0x00000000)
|
||||||
|
|
||||||
|
/* GFS specific labels */
|
||||||
|
#define SPTYPE_GFS_DATA (0x68011670)
|
||||||
|
#define SPTYPE_GFS_JOURNAL (0x69011670)
|
||||||
|
|
||||||
|
struct sptype_name {
|
||||||
|
const char *name;
|
||||||
|
uint32_t label;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sptype_name sptype_names[] = {
|
||||||
|
{"data", SPTYPE_DATA},
|
||||||
|
|
||||||
|
{"gfs_data", SPTYPE_GFS_DATA},
|
||||||
|
{"gfs_journal", SPTYPE_GFS_JOURNAL},
|
||||||
|
|
||||||
|
{"", 0x0} /* This must be the last flag. */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -16,9 +16,7 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "format-text.h"
|
#include "format-text.h"
|
||||||
|
|
||||||
#include "pool.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "import-export.h"
|
#include "import-export.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
#include "lvm-file.h"
|
#include "lvm-file.h"
|
||||||
@@ -53,7 +51,7 @@ struct archive_file {
|
|||||||
struct list list;
|
struct list list;
|
||||||
|
|
||||||
char *path;
|
char *path;
|
||||||
int index;
|
uint32_t index;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -91,7 +89,6 @@ static int _split_vg(const char *filename, char *vgname, size_t vg_size,
|
|||||||
|
|
||||||
static void _insert_file(struct list *head, struct archive_file *b)
|
static void _insert_file(struct list *head, struct archive_file *b)
|
||||||
{
|
{
|
||||||
struct list *bh;
|
|
||||||
struct archive_file *bf = NULL;
|
struct archive_file *bf = NULL;
|
||||||
|
|
||||||
if (list_empty(head)) {
|
if (list_empty(head)) {
|
||||||
@@ -99,11 +96,9 @@ static void _insert_file(struct list *head, struct archive_file *b)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* index increases through list */
|
/* index reduces through list */
|
||||||
list_iterate(bh, head) {
|
list_iterate_items(bf, head) {
|
||||||
bf = list_item(bh, struct archive_file);
|
if (b->index > bf->index) {
|
||||||
|
|
||||||
if (bf->index > b->index) {
|
|
||||||
list_add(&bf->list, &b->list);
|
list_add(&bf->list, &b->list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -112,33 +107,34 @@ static void _insert_file(struct list *head, struct archive_file *b)
|
|||||||
list_add_h(&bf->list, &b->list);
|
list_add_h(&bf->list, &b->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *_join(struct pool *mem, const char *dir, const char *name)
|
static char *_join(struct dm_pool *mem, const char *dir, const char *name)
|
||||||
{
|
{
|
||||||
if (!pool_begin_object(mem, 32) ||
|
if (!dm_pool_begin_object(mem, 32) ||
|
||||||
!pool_grow_object(mem, dir, strlen(dir)) ||
|
!dm_pool_grow_object(mem, dir, strlen(dir)) ||
|
||||||
!pool_grow_object(mem, "/", 1) ||
|
!dm_pool_grow_object(mem, "/", 1) ||
|
||||||
!pool_grow_object(mem, name, strlen(name)) ||
|
!dm_pool_grow_object(mem, name, strlen(name)) ||
|
||||||
!pool_grow_object(mem, "\0", 1)) {
|
!dm_pool_grow_object(mem, "\0", 1)) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pool_end_object(mem);
|
return dm_pool_end_object(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a list of archive_files.
|
* Returns a list of archive_files.
|
||||||
*/
|
*/
|
||||||
static struct list *_scan_archive(struct pool *mem,
|
static struct list *_scan_archive(struct dm_pool *mem,
|
||||||
const char *vgname, const char *dir)
|
const char *vgname, const char *dir)
|
||||||
{
|
{
|
||||||
int i, count, ix;
|
int i, count;
|
||||||
|
uint32_t ix;
|
||||||
char vgname_found[64], *path;
|
char vgname_found[64], *path;
|
||||||
struct dirent **dirent;
|
struct dirent **dirent;
|
||||||
struct archive_file *af;
|
struct archive_file *af;
|
||||||
struct list *results;
|
struct list *results;
|
||||||
|
|
||||||
if (!(results = pool_alloc(mem, sizeof(*results)))) {
|
if (!(results = dm_pool_alloc(mem, sizeof(*results)))) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -147,13 +143,13 @@ static struct list *_scan_archive(struct pool *mem,
|
|||||||
|
|
||||||
/* Sort fails beyond 5-digit indexes */
|
/* Sort fails beyond 5-digit indexes */
|
||||||
if ((count = scandir(dir, &dirent, NULL, alphasort)) < 0) {
|
if ((count = scandir(dir, &dirent, NULL, alphasort)) < 0) {
|
||||||
log_err("Couldn't scan archive directory.");
|
log_err("Couldn't scan the archive directory (%s).", dir);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
/* ignore dot files */
|
if (!strcmp(dirent[i]->d_name, ".") ||
|
||||||
if (dirent[i]->d_name[0] == '.')
|
!strcmp(dirent[i]->d_name, ".."))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* check the name is the correct format */
|
/* check the name is the correct format */
|
||||||
@@ -173,7 +169,7 @@ static struct list *_scan_archive(struct pool *mem,
|
|||||||
/*
|
/*
|
||||||
* Create a new archive_file.
|
* Create a new archive_file.
|
||||||
*/
|
*/
|
||||||
if (!(af = pool_alloc(mem, sizeof(*af)))) {
|
if (!(af = dm_pool_alloc(mem, sizeof(*af)))) {
|
||||||
log_err("Couldn't create new archive file.");
|
log_err("Couldn't create new archive file.");
|
||||||
results = NULL;
|
results = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -199,7 +195,6 @@ static struct list *_scan_archive(struct pool *mem,
|
|||||||
static void _remove_expired(struct list *archives, uint32_t archives_size,
|
static void _remove_expired(struct list *archives, uint32_t archives_size,
|
||||||
uint32_t retain_days, uint32_t min_archive)
|
uint32_t retain_days, uint32_t min_archive)
|
||||||
{
|
{
|
||||||
struct list *bh;
|
|
||||||
struct archive_file *bf;
|
struct archive_file *bf;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
time_t retain_time;
|
time_t retain_time;
|
||||||
@@ -213,9 +208,7 @@ static void _remove_expired(struct list *archives, uint32_t archives_size,
|
|||||||
retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
|
retain_time = time(NULL) - (time_t) retain_days *SECS_PER_DAY;
|
||||||
|
|
||||||
/* Assume list is ordered oldest first (by index) */
|
/* Assume list is ordered oldest first (by index) */
|
||||||
list_iterate(bh, archives) {
|
list_iterate_items(bf, archives) {
|
||||||
bf = list_item(bh, struct archive_file);
|
|
||||||
|
|
||||||
/* Get the mtime of the file and unlink if too old */
|
/* Get the mtime of the file and unlink if too old */
|
||||||
if (stat(bf->path, &sb)) {
|
if (stat(bf->path, &sb)) {
|
||||||
log_sys_error("stat", bf->path);
|
log_sys_error("stat", bf->path);
|
||||||
@@ -240,7 +233,7 @@ int archive_vg(struct volume_group *vg,
|
|||||||
uint32_t retain_days, uint32_t min_archive)
|
uint32_t retain_days, uint32_t min_archive)
|
||||||
{
|
{
|
||||||
int i, fd, renamed = 0;
|
int i, fd, renamed = 0;
|
||||||
unsigned int ix = 0;
|
uint32_t ix = 0;
|
||||||
struct archive_file *last;
|
struct archive_file *last;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
char temp_file[PATH_MAX], archive_name[PATH_MAX];
|
char temp_file[PATH_MAX], archive_name[PATH_MAX];
|
||||||
@@ -272,20 +265,20 @@ int archive_vg(struct volume_group *vg,
|
|||||||
* Now we want to rename this file to <vg>_index.vg.
|
* Now we want to rename this file to <vg>_index.vg.
|
||||||
*/
|
*/
|
||||||
if (!(archives = _scan_archive(vg->cmd->mem, vg->name, dir))) {
|
if (!(archives = _scan_archive(vg->cmd->mem, vg->name, dir))) {
|
||||||
log_err("Couldn't scan the archive directory (%s).", dir);
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list_empty(archives))
|
if (list_empty(archives))
|
||||||
ix = 0;
|
ix = 0;
|
||||||
else {
|
else {
|
||||||
last = list_item(archives->p, struct archive_file);
|
last = list_item(list_first(archives), struct archive_file);
|
||||||
ix = last->index + 1;
|
ix = last->index + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
if (lvm_snprintf(archive_name, sizeof(archive_name),
|
if (lvm_snprintf(archive_name, sizeof(archive_name),
|
||||||
"%s/%s_%05d.vg", dir, vg->name, ix) < 0) {
|
"%s/%s_%05u.vg", dir, vg->name, ix) < 0) {
|
||||||
log_error("Archive file name too long.");
|
log_error("Archive file name too long.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -338,30 +331,27 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
|
|||||||
log_print("Description:\t%s", desc ? desc : "<No description>");
|
log_print("Description:\t%s", desc ? desc : "<No description>");
|
||||||
log_print("Backup Time:\t%s", ctime(&when));
|
log_print("Backup Time:\t%s", ctime(&when));
|
||||||
|
|
||||||
pool_free(cmd->mem, vg);
|
dm_pool_free(cmd->mem, vg);
|
||||||
tf->fmt->ops->destroy_instance(tf);
|
tf->fmt->ops->destroy_instance(tf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
||||||
{
|
{
|
||||||
struct list *archives, *ah;
|
struct list *archives;
|
||||||
struct archive_file *af;
|
struct archive_file *af;
|
||||||
|
|
||||||
if (!(archives = _scan_archive(cmd->mem, vgname, dir))) {
|
if (!(archives = _scan_archive(cmd->mem, vgname, dir))) {
|
||||||
log_err("Couldn't scan the archive directory (%s).", dir);
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list_empty(archives))
|
if (list_empty(archives))
|
||||||
log_print("No archives found in %s.", dir);
|
log_print("No archives found in %s.", dir);
|
||||||
|
|
||||||
list_iterate(ah, archives) {
|
list_iterate_back_items(af, archives)
|
||||||
af = list_item(ah, struct archive_file);
|
|
||||||
|
|
||||||
_display_archive(cmd, af);
|
_display_archive(cmd, af);
|
||||||
}
|
|
||||||
|
|
||||||
pool_free(cmd->mem, archives);
|
dm_pool_free(cmd->mem, archives);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,61 +13,72 @@
|
|||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools.h"
|
#include "lib.h"
|
||||||
|
#include "archiver.h"
|
||||||
|
#include "format-text.h"
|
||||||
|
#include "lvm-file.h"
|
||||||
|
#include "lvm-string.h"
|
||||||
|
#include "lvmcache.h"
|
||||||
|
#include "toolcontext.h"
|
||||||
|
|
||||||
static struct {
|
#include <unistd.h>
|
||||||
|
|
||||||
|
struct archive_params {
|
||||||
int enabled;
|
int enabled;
|
||||||
char *dir;
|
char *dir;
|
||||||
unsigned int keep_days;
|
unsigned int keep_days;
|
||||||
unsigned int keep_number;
|
unsigned int keep_number;
|
||||||
|
};
|
||||||
|
|
||||||
} _archive_params;
|
struct backup_params {
|
||||||
|
|
||||||
static struct {
|
|
||||||
int enabled;
|
int enabled;
|
||||||
char *dir;
|
char *dir;
|
||||||
|
};
|
||||||
|
|
||||||
} _backup_params;
|
int archive_init(struct cmd_context *cmd, const char *dir,
|
||||||
|
unsigned int keep_days, unsigned int keep_min)
|
||||||
int archive_init(const char *dir, unsigned int keep_days, unsigned int keep_min)
|
|
||||||
{
|
{
|
||||||
_archive_params.dir = NULL;
|
if (!(cmd->archive_params = dm_pool_zalloc(cmd->libmem,
|
||||||
|
sizeof(*cmd->archive_params)))) {
|
||||||
|
log_error("archive_params alloc failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->archive_params->dir = NULL;
|
||||||
|
|
||||||
if (!*dir)
|
if (!*dir)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!create_dir(dir))
|
if (!(cmd->archive_params->dir = dm_strdup(dir))) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!(_archive_params.dir = dbg_strdup(dir))) {
|
|
||||||
log_error("Couldn't copy archive directory name.");
|
log_error("Couldn't copy archive directory name.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_archive_params.keep_days = keep_days;
|
cmd->archive_params->keep_days = keep_days;
|
||||||
_archive_params.keep_number = keep_min;
|
cmd->archive_params->keep_number = keep_min;
|
||||||
_archive_params.enabled = 1;
|
cmd->archive_params->enabled = 1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_exit(void)
|
void archive_exit(struct cmd_context *cmd)
|
||||||
{
|
{
|
||||||
if (_archive_params.dir)
|
if (cmd->archive_params->dir)
|
||||||
dbg_free(_archive_params.dir);
|
dm_free(cmd->archive_params->dir);
|
||||||
memset(&_archive_params, 0, sizeof(_archive_params));
|
memset(cmd->archive_params, 0, sizeof(*cmd->archive_params));
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_enable(int flag)
|
void archive_enable(struct cmd_context *cmd, int flag)
|
||||||
{
|
{
|
||||||
_archive_params.enabled = flag;
|
cmd->archive_params->enabled = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *_build_desc(struct pool *mem, const char *line, int before)
|
static char *_build_desc(struct dm_pool *mem, const char *line, int before)
|
||||||
{
|
{
|
||||||
size_t len = strlen(line) + 32;
|
size_t len = strlen(line) + 32;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
|
||||||
if (!(buffer = pool_zalloc(mem, strlen(line) + 32))) {
|
if (!(buffer = dm_pool_zalloc(mem, strlen(line) + 32))) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -91,14 +102,14 @@ static int __archive(struct volume_group *vg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return archive_vg(vg, _archive_params.dir, desc,
|
return archive_vg(vg, vg->cmd->archive_params->dir, desc,
|
||||||
_archive_params.keep_days,
|
vg->cmd->archive_params->keep_days,
|
||||||
_archive_params.keep_number);
|
vg->cmd->archive_params->keep_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
int archive(struct volume_group *vg)
|
int archive(struct volume_group *vg)
|
||||||
{
|
{
|
||||||
if (!_archive_params.enabled || !_archive_params.dir)
|
if (!vg->cmd->archive_params->enabled || !vg->cmd->archive_params->dir)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (test_mode()) {
|
if (test_mode()) {
|
||||||
@@ -106,7 +117,16 @@ int archive(struct volume_group *vg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_verbose("Archiving volume group \"%s\" metadata.", vg->name);
|
if (!create_dir(vg->cmd->archive_params->dir))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Trap a read-only file system */
|
||||||
|
if ((access(vg->cmd->archive_params->dir, R_OK | W_OK | X_OK) == -1) &&
|
||||||
|
(errno == EROFS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
log_verbose("Archiving volume group \"%s\" metadata (seqno %u).", vg->name,
|
||||||
|
vg->seqno);
|
||||||
if (!__archive(vg)) {
|
if (!__archive(vg)) {
|
||||||
log_error("Volume group \"%s\" metadata archive failed.",
|
log_error("Volume group \"%s\" metadata archive failed.",
|
||||||
vg->name);
|
vg->name);
|
||||||
@@ -121,23 +141,26 @@ int archive_display(struct cmd_context *cmd, const char *vg_name)
|
|||||||
int r1, r2;
|
int r1, r2;
|
||||||
|
|
||||||
init_partial(1);
|
init_partial(1);
|
||||||
r1 = archive_list(cmd, _archive_params.dir, vg_name);
|
r1 = archive_list(cmd, cmd->archive_params->dir, vg_name);
|
||||||
r2 = backup_list(cmd, _backup_params.dir, vg_name);
|
r2 = backup_list(cmd, cmd->backup_params->dir, vg_name);
|
||||||
init_partial(0);
|
init_partial(0);
|
||||||
|
|
||||||
return r1 && r2;
|
return r1 && r2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int backup_init(const char *dir)
|
int backup_init(struct cmd_context *cmd, const char *dir)
|
||||||
{
|
{
|
||||||
_backup_params.dir = NULL;
|
if (!(cmd->backup_params = dm_pool_zalloc(cmd->libmem,
|
||||||
|
sizeof(*cmd->archive_params)))) {
|
||||||
|
log_error("archive_params alloc failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->backup_params->dir = NULL;
|
||||||
if (!*dir)
|
if (!*dir)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!create_dir(dir))
|
if (!(cmd->backup_params->dir = dm_strdup(dir))) {
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!(_backup_params.dir = dbg_strdup(dir))) {
|
|
||||||
log_error("Couldn't copy backup directory name.");
|
log_error("Couldn't copy backup directory name.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -145,16 +168,16 @@ int backup_init(const char *dir)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void backup_exit(void)
|
void backup_exit(struct cmd_context *cmd)
|
||||||
{
|
{
|
||||||
if (_backup_params.dir)
|
if (cmd->backup_params->dir)
|
||||||
dbg_free(_backup_params.dir);
|
dm_free(cmd->backup_params->dir);
|
||||||
memset(&_backup_params, 0, sizeof(_backup_params));
|
memset(cmd->backup_params, 0, sizeof(*cmd->backup_params));
|
||||||
}
|
}
|
||||||
|
|
||||||
void backup_enable(int flag)
|
void backup_enable(struct cmd_context *cmd, int flag)
|
||||||
{
|
{
|
||||||
_backup_params.enabled = flag;
|
cmd->backup_params->enabled = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __backup(struct volume_group *vg)
|
static int __backup(struct volume_group *vg)
|
||||||
@@ -168,20 +191,18 @@ static int __backup(struct volume_group *vg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lvm_snprintf(name, sizeof(name), "%s/%s",
|
if (lvm_snprintf(name, sizeof(name), "%s/%s",
|
||||||
_backup_params.dir, vg->name) < 0) {
|
vg->cmd->backup_params->dir, vg->name) < 0) {
|
||||||
log_error("Failed to generate volume group metadata backup "
|
log_error("Failed to generate volume group metadata backup "
|
||||||
"filename.");
|
"filename.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_verbose("Creating volume group backup \"%s\"", name);
|
|
||||||
|
|
||||||
return backup_to_file(name, desc, vg);
|
return backup_to_file(name, desc, vg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int backup(struct volume_group *vg)
|
int backup(struct volume_group *vg)
|
||||||
{
|
{
|
||||||
if (!_backup_params.enabled || !_backup_params.dir) {
|
if (!vg->cmd->backup_params->enabled || !vg->cmd->backup_params->dir) {
|
||||||
log_print("WARNING: This metadata update is NOT backed up");
|
log_print("WARNING: This metadata update is NOT backed up");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -191,6 +212,14 @@ int backup(struct volume_group *vg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!create_dir(vg->cmd->backup_params->dir))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Trap a read-only file system */
|
||||||
|
if ((access(vg->cmd->backup_params->dir, R_OK | W_OK | X_OK) == -1) &&
|
||||||
|
(errno == EROFS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!__backup(vg)) {
|
if (!__backup(vg)) {
|
||||||
log_error("Backup of volume group %s metadata failed.",
|
log_error("Backup of volume group %s metadata failed.",
|
||||||
vg->name);
|
vg->name);
|
||||||
@@ -200,12 +229,12 @@ int backup(struct volume_group *vg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int backup_remove(const char *vg_name)
|
int backup_remove(struct cmd_context *cmd, const char *vg_name)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
||||||
if (lvm_snprintf(path, sizeof(path), "%s/%s",
|
if (lvm_snprintf(path, sizeof(path), "%s/%s",
|
||||||
_backup_params.dir, vg_name) < 0) {
|
cmd->backup_params->dir, vg_name) < 0) {
|
||||||
log_err("Failed to generate backup filename (for removal).");
|
log_err("Failed to generate backup filename (for removal).");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -271,7 +300,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (cmd->fmt != info->fmt) {
|
if (cmd->fmt != info->fmt) {
|
||||||
log_error("PV %s is a different format (%s)",
|
log_error("PV %s is a different format (seqno %s)",
|
||||||
dev_name(pv->dev), info->fmt->name);
|
dev_name(pv->dev), info->fmt->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -314,7 +343,7 @@ int backup_restore(struct cmd_context *cmd, const char *vg_name)
|
|||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
||||||
if (lvm_snprintf(path, sizeof(path), "%s/%s",
|
if (lvm_snprintf(path, sizeof(path), "%s/%s",
|
||||||
_backup_params.dir, vg_name) < 0) {
|
cmd->backup_params->dir, vg_name) < 0) {
|
||||||
log_err("Failed to generate backup filename (for restore).");
|
log_err("Failed to generate backup filename (for restore).");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -332,6 +361,8 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
|
|||||||
|
|
||||||
cmd = vg->cmd;
|
cmd = vg->cmd;
|
||||||
|
|
||||||
|
log_verbose("Creating volume group backup \"%s\" (seqno %u).", file, vg->seqno);
|
||||||
|
|
||||||
if (!(context = create_text_context(cmd, file, desc)) ||
|
if (!(context = create_text_context(cmd, file, desc)) ||
|
||||||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
||||||
context))) {
|
context))) {
|
||||||
@@ -354,3 +385,34 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg)
|
|||||||
tf->fmt->ops->destroy_instance(tf);
|
tf->fmt->ops->destroy_instance(tf);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update backup (and archive) if they're out-of-date or don't exist.
|
||||||
|
*/
|
||||||
|
void check_current_backup(struct volume_group *vg)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
struct volume_group *vg_backup;
|
||||||
|
|
||||||
|
if ((vg->status & PARTIAL_VG) || (vg->status & EXPORTED_VG))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (lvm_snprintf(path, sizeof(path), "%s/%s",
|
||||||
|
vg->cmd->backup_params->dir, vg->name) < 0) {
|
||||||
|
log_debug("Failed to generate backup filename.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_suppress(1);
|
||||||
|
/* Up-to-date backup exists? */
|
||||||
|
if ((vg_backup = backup_read_vg(vg->cmd, vg->name, path)) &&
|
||||||
|
(vg->seqno == vg_backup->seqno) &&
|
||||||
|
(id_equal(&vg->id, &vg_backup->id)))
|
||||||
|
return;
|
||||||
|
log_suppress(0);
|
||||||
|
|
||||||
|
if (vg_backup)
|
||||||
|
archive(vg_backup);
|
||||||
|
archive(vg);
|
||||||
|
backup(vg);
|
||||||
|
}
|
||||||
@@ -18,11 +18,6 @@
|
|||||||
|
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: This file is going to merge with the archiving code in
|
|
||||||
* lib/format_text at some point.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are two operations that come under the general area of
|
* There are two operations that come under the general area of
|
||||||
* backups. 'Archiving' occurs just before a volume group
|
* backups. 'Archiving' occurs just before a volume group
|
||||||
@@ -36,20 +31,20 @@
|
|||||||
* Typically backups will be stored in /etc/lvm/backups.
|
* Typically backups will be stored in /etc/lvm/backups.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int archive_init(const char *dir,
|
int archive_init(struct cmd_context *cmd, const char *dir,
|
||||||
unsigned int keep_days, unsigned int keep_min);
|
unsigned int keep_days, unsigned int keep_min);
|
||||||
void archive_exit(void);
|
void archive_exit(struct cmd_context *cmd);
|
||||||
|
|
||||||
void archive_enable(int flag);
|
void archive_enable(struct cmd_context *cmd, int flag);
|
||||||
int archive(struct volume_group *vg);
|
int archive(struct volume_group *vg);
|
||||||
int archive_display(struct cmd_context *cmd, const char *vg_name);
|
int archive_display(struct cmd_context *cmd, const char *vg_name);
|
||||||
|
|
||||||
int backup_init(const char *dir);
|
int backup_init(struct cmd_context *cmd, const char *dir);
|
||||||
void backup_exit(void);
|
void backup_exit(struct cmd_context *cmd);
|
||||||
|
|
||||||
void backup_enable(int flag);
|
void backup_enable(struct cmd_context *cmd, int flag);
|
||||||
int backup(struct volume_group *vg);
|
int backup(struct volume_group *vg);
|
||||||
int backup_remove(const char *vg_name);
|
int backup_remove(struct cmd_context *cmd, const char *vg_name);
|
||||||
|
|
||||||
struct volume_group *backup_read_vg(struct cmd_context *cmd,
|
struct volume_group *backup_read_vg(struct cmd_context *cmd,
|
||||||
const char *vg_name, const char *file);
|
const char *vg_name, const char *file);
|
||||||
@@ -60,4 +55,6 @@ int backup_restore(struct cmd_context *cmd, const char *vg_name);
|
|||||||
|
|
||||||
int backup_to_file(const char *file, const char *desc, struct volume_group *vg);
|
int backup_to_file(const char *file, const char *desc, struct volume_group *vg);
|
||||||
|
|
||||||
|
void check_current_backup(struct volume_group *vg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -16,11 +16,9 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "import-export.h"
|
#include "import-export.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "pool.h"
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
#include "segtypes.h"
|
#include "segtype.h"
|
||||||
#include "text_export.h"
|
#include "text_export.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -30,19 +28,32 @@
|
|||||||
struct formatter;
|
struct formatter;
|
||||||
typedef int (*out_with_comment_fn) (struct formatter * f, const char *comment,
|
typedef int (*out_with_comment_fn) (struct formatter * f, const char *comment,
|
||||||
const char *fmt, va_list ap);
|
const char *fmt, va_list ap);
|
||||||
typedef void (*nl_fn) (struct formatter * f);
|
typedef int (*nl_fn) (struct formatter * f);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro for formatted output.
|
||||||
|
* out_with_comment_fn returns -1 if data didn't fit and buffer was expanded.
|
||||||
|
* Then argument list is reset and out_with_comment_fn is called again.
|
||||||
|
*/
|
||||||
|
#define _out_with_comment(f, buffer, fmt, ap) \
|
||||||
|
do { \
|
||||||
|
va_start(ap, fmt); \
|
||||||
|
r = f->out_with_comment(f, buffer, fmt, ap); \
|
||||||
|
va_end(ap); \
|
||||||
|
} while (r == -1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The first half of this file deals with
|
* The first half of this file deals with
|
||||||
* exporting the vg, ie. writing it to a file.
|
* exporting the vg, ie. writing it to a file.
|
||||||
*/
|
*/
|
||||||
struct formatter {
|
struct formatter {
|
||||||
struct pool *mem; /* pv names allocated from here */
|
struct dm_pool *mem; /* pv names allocated from here */
|
||||||
struct hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
|
struct dm_hash_table *pv_names; /* dev_name -> pv_name (eg, pv1) */
|
||||||
|
|
||||||
union {
|
union {
|
||||||
FILE *fp; /* where we're writing to */
|
FILE *fp; /* where we're writing to */
|
||||||
struct {
|
struct {
|
||||||
char *buf;
|
char *start;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t used;
|
uint32_t used;
|
||||||
} buf;
|
} buf;
|
||||||
@@ -95,22 +106,45 @@ static void _dec_indent(struct formatter *f)
|
|||||||
/*
|
/*
|
||||||
* Newline function for prettier layout.
|
* Newline function for prettier layout.
|
||||||
*/
|
*/
|
||||||
static void _nl_file(struct formatter *f)
|
static int _nl_file(struct formatter *f)
|
||||||
{
|
{
|
||||||
fprintf(f->data.fp, "\n");
|
fprintf(f->data.fp, "\n");
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _nl_raw(struct formatter *f)
|
static int _extend_buffer(struct formatter *f)
|
||||||
{
|
{
|
||||||
if (f->data.buf.used >= f->data.buf.size - 1)
|
char *newbuf;
|
||||||
return;
|
|
||||||
|
|
||||||
*f->data.buf.buf = '\n';
|
log_debug("Doubling metadata output buffer to %" PRIu32,
|
||||||
f->data.buf.buf += 1;
|
f->data.buf.size * 2);
|
||||||
|
if (!(newbuf = dm_realloc(f->data.buf.start,
|
||||||
|
f->data.buf.size * 2))) {
|
||||||
|
log_error("Buffer reallocation failed.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
f->data.buf.start = newbuf;
|
||||||
|
f->data.buf.size *= 2;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _nl_raw(struct formatter *f)
|
||||||
|
{
|
||||||
|
/* If metadata doesn't fit, extend buffer */
|
||||||
|
if ((f->data.buf.used + 2 > f->data.buf.size) &&
|
||||||
|
(!_extend_buffer(f))) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(f->data.buf.start + f->data.buf.used) = '\n';
|
||||||
f->data.buf.used += 1;
|
f->data.buf.used += 1;
|
||||||
*f->data.buf.buf = '\0';
|
|
||||||
|
|
||||||
return;
|
*(f->data.buf.start + f->data.buf.used) = '\0';
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COMMENT_TAB 6
|
#define COMMENT_TAB 6
|
||||||
@@ -154,16 +188,21 @@ static int _out_with_comment_raw(struct formatter *f, const char *comment,
|
|||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = vsnprintf(f->data.buf.buf, f->data.buf.size - f->data.buf.used,
|
n = vsnprintf(f->data.buf.start + f->data.buf.used,
|
||||||
fmt, ap);
|
f->data.buf.size - f->data.buf.used, fmt, ap);
|
||||||
|
|
||||||
if (n < 0 || (n > f->data.buf.size - f->data.buf.used - 1))
|
/* If metadata doesn't fit, extend buffer */
|
||||||
return 0;
|
if (n < 0 || (n + f->data.buf.used + 2 > f->data.buf.size)) {
|
||||||
|
if (!_extend_buffer(f)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1; /* Retry */
|
||||||
|
}
|
||||||
|
|
||||||
f->data.buf.buf += n;
|
|
||||||
f->data.buf.used += n;
|
f->data.buf.used += n;
|
||||||
|
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -209,9 +248,7 @@ int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
|
|||||||
if (!_sectors_to_units(size, buffer, sizeof(buffer)))
|
if (!_sectors_to_units(size, buffer, sizeof(buffer)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
_out_with_comment(f, buffer, fmt, ap);
|
||||||
r = f->out_with_comment(f, buffer, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -225,9 +262,7 @@ int out_hint(struct formatter *f, const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
_out_with_comment(f, "# Hint only", fmt, ap);
|
||||||
r = f->out_with_comment(f, "# Hint only", fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -240,9 +275,7 @@ int out_text(struct formatter *f, const char *fmt, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
_out_with_comment(f, NULL, fmt, ap);
|
||||||
r = f->out_with_comment(f, NULL, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -257,10 +290,10 @@ static int _print_header(struct formatter *f,
|
|||||||
outf(f, "# Generated by LVM2: %s", ctime(&t));
|
outf(f, "# Generated by LVM2: %s", ctime(&t));
|
||||||
outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
|
outf(f, CONTENTS_FIELD " = \"" CONTENTS_VALUE "\"");
|
||||||
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
|
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
|
|
||||||
outf(f, "description = \"%s\"", desc);
|
outf(f, "description = \"%s\"", desc);
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
|
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
|
||||||
_utsname.sysname, _utsname.nodename, _utsname.release,
|
_utsname.sysname, _utsname.nodename, _utsname.release,
|
||||||
_utsname.version, _utsname.machine);
|
_utsname.version, _utsname.machine);
|
||||||
@@ -309,7 +342,7 @@ static int _print_vg(struct formatter *f, struct volume_group *vg)
|
|||||||
|
|
||||||
/* Default policy is NORMAL; INHERIT is meaningless */
|
/* Default policy is NORMAL; INHERIT is meaningless */
|
||||||
if (vg->alloc != ALLOC_NORMAL && vg->alloc != ALLOC_INHERIT) {
|
if (vg->alloc != ALLOC_NORMAL && vg->alloc != ALLOC_INHERIT) {
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
outf(f, "allocation_policy = \"%s\"",
|
outf(f, "allocation_policy = \"%s\"",
|
||||||
get_alloc_string(vg->alloc));
|
get_alloc_string(vg->alloc));
|
||||||
}
|
}
|
||||||
@@ -325,12 +358,12 @@ static inline const char *_get_pv_name(struct formatter *f,
|
|||||||
struct physical_volume *pv)
|
struct physical_volume *pv)
|
||||||
{
|
{
|
||||||
return (pv) ? (const char *)
|
return (pv) ? (const char *)
|
||||||
hash_lookup(f->pv_names, dev_name(pv->dev)) : "Missing";
|
dm_hash_lookup(f->pv_names, dev_name(pv->dev)) : "Missing";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||||
{
|
{
|
||||||
struct list *pvh;
|
struct pv_list *pvl;
|
||||||
struct physical_volume *pv;
|
struct physical_volume *pv;
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -338,15 +371,15 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
|||||||
outf(f, "physical_volumes {");
|
outf(f, "physical_volumes {");
|
||||||
_inc_indent(f);
|
_inc_indent(f);
|
||||||
|
|
||||||
list_iterate(pvh, &vg->pvs) {
|
list_iterate_items(pvl, &vg->pvs) {
|
||||||
pv = list_item(pvh, struct pv_list)->pv;
|
pv = pvl->pv;
|
||||||
|
|
||||||
if (!(name = _get_pv_name(f, pv))) {
|
if (!(name = _get_pv_name(f, pv))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
outf(f, "%s {", name);
|
outf(f, "%s {", name);
|
||||||
_inc_indent(f);
|
_inc_indent(f);
|
||||||
|
|
||||||
@@ -360,7 +393,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
|||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
|
|
||||||
if (!print_flags(pv->status, PV_FLAGS, buffer, sizeof(buffer))) {
|
if (!print_flags(pv->status, PV_FLAGS, buffer, sizeof(buffer))) {
|
||||||
stack;
|
stack;
|
||||||
@@ -407,7 +440,7 @@ static int _print_segment(struct formatter *f, struct volume_group *vg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
outf(f, "type = \"%s\"", seg->segtype->name);
|
outf(f, "type = \"%s\"", seg->segtype->name);
|
||||||
|
|
||||||
if (!list_empty(&seg->tags)) {
|
if (!list_empty(&seg->tags)) {
|
||||||
@@ -436,28 +469,31 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
|||||||
const char *name;
|
const char *name;
|
||||||
unsigned int s;
|
unsigned int s;
|
||||||
|
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
|
|
||||||
outf(f, "%ss = [", type);
|
outf(f, "%ss = [", type);
|
||||||
_inc_indent(f);
|
_inc_indent(f);
|
||||||
|
|
||||||
for (s = 0; s < seg->area_count; s++) {
|
for (s = 0; s < seg->area_count; s++) {
|
||||||
switch (seg->area[s].type) {
|
switch (seg_type(seg, s)) {
|
||||||
case AREA_PV:
|
case AREA_PV:
|
||||||
if (!(name = _get_pv_name(f, seg->area[s].u.pv.pv))) {
|
if (!(name = _get_pv_name(f, seg_pv(seg, s)))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
outf(f, "\"%s\", %u%s", name,
|
outf(f, "\"%s\", %u%s", name,
|
||||||
seg->area[s].u.pv.pe,
|
seg_pe(seg, s),
|
||||||
(s == seg->area_count - 1) ? "" : ",");
|
(s == seg->area_count - 1) ? "" : ",");
|
||||||
break;
|
break;
|
||||||
case AREA_LV:
|
case AREA_LV:
|
||||||
outf(f, "\"%s\", %u%s",
|
outf(f, "\"%s\", %u%s",
|
||||||
seg->area[s].u.lv.lv->name,
|
seg_lv(seg, s)->name,
|
||||||
seg->area[s].u.lv.le,
|
seg_le(seg, s),
|
||||||
(s == seg->area_count - 1) ? "" : ",");
|
(s == seg->area_count - 1) ? "" : ",");
|
||||||
|
break;
|
||||||
|
case AREA_UNASSIGNED:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,72 +502,57 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _count_segments(struct logical_volume *lv)
|
static int _print_lv(struct formatter *f, struct logical_volume *lv)
|
||||||
{
|
{
|
||||||
int r = 0;
|
struct lv_segment *seg;
|
||||||
struct list *segh;
|
char buffer[4096];
|
||||||
|
int seg_count;
|
||||||
|
|
||||||
list_iterate(segh, &lv->segments)
|
outnl(f);
|
||||||
r++;
|
outf(f, "%s {", lv->name);
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _print_snapshot(struct formatter *f, struct snapshot *snap,
|
|
||||||
unsigned int count)
|
|
||||||
{
|
|
||||||
char buffer[256];
|
|
||||||
struct lv_segment seg;
|
|
||||||
|
|
||||||
f->nl(f);
|
|
||||||
|
|
||||||
outf(f, "snapshot%u {", count);
|
|
||||||
_inc_indent(f);
|
_inc_indent(f);
|
||||||
|
|
||||||
if (!id_write_format(&snap->id, buffer, sizeof(buffer))) {
|
/* FIXME: Write full lvid */
|
||||||
|
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
outf(f, "id = \"%s\"", buffer);
|
outf(f, "id = \"%s\"", buffer);
|
||||||
|
|
||||||
seg.status = LVM_READ | LVM_WRITE | VISIBLE_LV;
|
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
|
||||||
if (!print_flags(seg.status, LV_FLAGS, buffer, sizeof(buffer))) {
|
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
outf(f, "status = %s", buffer);
|
outf(f, "status = %s", buffer);
|
||||||
outf(f, "segment_count = 1");
|
|
||||||
|
|
||||||
f->nl(f);
|
if (!list_empty(&lv->tags)) {
|
||||||
|
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
|
||||||
if (!(seg.segtype = get_segtype_from_string(snap->origin->vg->cmd,
|
stack;
|
||||||
"snapshot"))) {
|
return 0;
|
||||||
stack;
|
}
|
||||||
return 0;
|
outf(f, "tags = %s", buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
seg.le = 0;
|
if (lv->alloc != ALLOC_INHERIT)
|
||||||
seg.len = snap->origin->le_count;
|
outf(f, "allocation_policy = \"%s\"",
|
||||||
seg.origin = snap->origin;
|
get_alloc_string(lv->alloc));
|
||||||
seg.cow = snap->cow;
|
|
||||||
seg.chunk_size = snap->chunk_size;
|
|
||||||
|
|
||||||
/* FIXME Dummy values */
|
if (lv->read_ahead)
|
||||||
list_init(&seg.list);
|
outf(f, "read_ahead = %u", lv->read_ahead);
|
||||||
seg.lv = snap->cow;
|
if (lv->major >= 0)
|
||||||
seg.stripe_size = 0;
|
outf(f, "major = %d", lv->major);
|
||||||
seg.area_count = 0;
|
if (lv->minor >= 0)
|
||||||
seg.area_len = 0;
|
outf(f, "minor = %d", lv->minor);
|
||||||
seg.extents_copied = 0;
|
outf(f, "segment_count = %u", list_size(&lv->segments));
|
||||||
|
outnl(f);
|
||||||
|
|
||||||
/* Can't tag a snapshot independently of its origin */
|
seg_count = 1;
|
||||||
list_init(&seg.tags);
|
list_iterate_items(seg, &lv->segments) {
|
||||||
|
if (!_print_segment(f, lv->vg, seg_count++, seg)) {
|
||||||
if (!_print_segment(f, snap->origin->vg, 1, &seg)) {
|
stack;
|
||||||
stack;
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_dec_indent(f);
|
_dec_indent(f);
|
||||||
@@ -540,31 +561,9 @@ static int _print_snapshot(struct formatter *f, struct snapshot *snap,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _print_snapshots(struct formatter *f, struct volume_group *vg)
|
|
||||||
{
|
|
||||||
struct list *sh;
|
|
||||||
struct snapshot *s;
|
|
||||||
unsigned int count = 0;
|
|
||||||
|
|
||||||
list_iterate(sh, &vg->snapshots) {
|
|
||||||
s = list_item(sh, struct snapshot_list)->snapshot;
|
|
||||||
|
|
||||||
if (!_print_snapshot(f, s, count++)) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||||
{
|
{
|
||||||
struct list *lvh;
|
struct lv_list *lvl;
|
||||||
struct logical_volume *lv;
|
|
||||||
struct lv_segment *seg;
|
|
||||||
char buffer[4096];
|
|
||||||
int seg_count;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't bother with an lv section if there are no lvs.
|
* Don't bother with an lv section if there are no lvs.
|
||||||
@@ -575,63 +574,25 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
|||||||
outf(f, "logical_volumes {");
|
outf(f, "logical_volumes {");
|
||||||
_inc_indent(f);
|
_inc_indent(f);
|
||||||
|
|
||||||
list_iterate(lvh, &vg->lvs) {
|
/*
|
||||||
lv = list_item(lvh, struct lv_list)->lv;
|
* Write visible LVs first
|
||||||
|
*/
|
||||||
f->nl(f);
|
list_iterate_items(lvl, &vg->lvs) {
|
||||||
outf(f, "%s {", lv->name);
|
if (!(lvl->lv->status & VISIBLE_LV))
|
||||||
_inc_indent(f);
|
continue;
|
||||||
|
if (!_print_lv(f, lvl->lv)) {
|
||||||
/* FIXME: Write full lvid */
|
|
||||||
if (!id_write_format(&lv->lvid.id[1], buffer, sizeof(buffer))) {
|
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
outf(f, "id = \"%s\"", buffer);
|
|
||||||
|
|
||||||
if (!print_flags(lv->status, LV_FLAGS, buffer, sizeof(buffer))) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
outf(f, "status = %s", buffer);
|
|
||||||
|
|
||||||
if (!list_empty(&lv->tags)) {
|
|
||||||
if (!print_tags(&lv->tags, buffer, sizeof(buffer))) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
outf(f, "tags = %s", buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lv->alloc != ALLOC_INHERIT)
|
|
||||||
outf(f, "allocation_policy = \"%s\"",
|
|
||||||
get_alloc_string(lv->alloc));
|
|
||||||
|
|
||||||
if (lv->read_ahead)
|
|
||||||
outf(f, "read_ahead = %u", lv->read_ahead);
|
|
||||||
if (lv->major >= 0)
|
|
||||||
outf(f, "major = %d", lv->major);
|
|
||||||
if (lv->minor >= 0)
|
|
||||||
outf(f, "minor = %d", lv->minor);
|
|
||||||
outf(f, "segment_count = %u", _count_segments(lv));
|
|
||||||
f->nl(f);
|
|
||||||
|
|
||||||
seg_count = 1;
|
|
||||||
list_iterate_items(seg, &lv->segments) {
|
|
||||||
if (!_print_segment(f, vg, seg_count++, seg)) {
|
|
||||||
stack;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_dec_indent(f);
|
|
||||||
outf(f, "}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_print_snapshots(f, vg)) {
|
list_iterate_items(lvl, &vg->lvs) {
|
||||||
stack;
|
if ((lvl->lv->status & VISIBLE_LV))
|
||||||
return 0;
|
continue;
|
||||||
|
if (!_print_lv(f, lvl->lv)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_dec_indent(f);
|
_dec_indent(f);
|
||||||
@@ -648,22 +609,22 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
|||||||
static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
struct list *pvh;
|
struct pv_list *pvl;
|
||||||
struct physical_volume *pv;
|
struct physical_volume *pv;
|
||||||
char buffer[32], *name;
|
char buffer[32], *name;
|
||||||
|
|
||||||
if (!(f->mem = pool_create(512))) {
|
if (!(f->mem = dm_pool_create("text pv_names", 512))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(f->pv_names = hash_create(128))) {
|
if (!(f->pv_names = dm_hash_create(128))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_iterate(pvh, &vg->pvs) {
|
list_iterate_items(pvl, &vg->pvs) {
|
||||||
pv = list_item(pvh, struct pv_list)->pv;
|
pv = pvl->pv;
|
||||||
|
|
||||||
/* FIXME But skip if there's already an LV called pv%d ! */
|
/* FIXME But skip if there's already an LV called pv%d ! */
|
||||||
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
|
if (lvm_snprintf(buffer, sizeof(buffer), "pv%d", count++) < 0) {
|
||||||
@@ -671,12 +632,12 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(name = pool_strdup(f->mem, buffer))) {
|
if (!(name = dm_pool_strdup(f->mem, buffer))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hash_insert(f->pv_names, dev_name(pv->dev), name)) {
|
if (!dm_hash_insert(f->pv_names, dev_name(pv->dev), name)) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -686,10 +647,10 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
|||||||
|
|
||||||
bad:
|
bad:
|
||||||
if (f->mem)
|
if (f->mem)
|
||||||
pool_destroy(f->mem);
|
dm_pool_destroy(f->mem);
|
||||||
|
|
||||||
if (f->pv_names)
|
if (f->pv_names)
|
||||||
hash_destroy(f->pv_names);
|
dm_hash_destroy(f->pv_names);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -716,11 +677,11 @@ static int _text_vg_export(struct formatter *f,
|
|||||||
if (!_print_vg(f, vg))
|
if (!_print_vg(f, vg))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
if (!_print_pvs(f, vg))
|
if (!_print_pvs(f, vg))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
f->nl(f);
|
outnl(f);
|
||||||
if (!_print_lvs(f, vg))
|
if (!_print_lvs(f, vg))
|
||||||
fail;
|
fail;
|
||||||
|
|
||||||
@@ -736,10 +697,10 @@ static int _text_vg_export(struct formatter *f,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
if (f->mem)
|
if (f->mem)
|
||||||
pool_destroy(f->mem);
|
dm_pool_destroy(f->mem);
|
||||||
|
|
||||||
if (f->pv_names)
|
if (f->pv_names)
|
||||||
hash_destroy(f->pv_names);
|
dm_hash_destroy(f->pv_names);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -751,7 +712,7 @@ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
|
|||||||
|
|
||||||
_init();
|
_init();
|
||||||
|
|
||||||
if (!(f = dbg_malloc(sizeof(*f)))) {
|
if (!(f = dm_malloc(sizeof(*f)))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -766,27 +727,31 @@ int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
|
|||||||
r = _text_vg_export(f, vg, desc);
|
r = _text_vg_export(f, vg, desc);
|
||||||
if (r)
|
if (r)
|
||||||
r = !ferror(f->data.fp);
|
r = !ferror(f->data.fp);
|
||||||
dbg_free(f);
|
dm_free(f);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns amount of buffer used incl. terminating NUL */
|
/* Returns amount of buffer used incl. terminating NUL */
|
||||||
int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
|
int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf)
|
||||||
uint32_t size)
|
|
||||||
{
|
{
|
||||||
struct formatter *f;
|
struct formatter *f;
|
||||||
int r;
|
int r = 0;
|
||||||
|
|
||||||
_init();
|
_init();
|
||||||
|
|
||||||
if (!(f = dbg_malloc(sizeof(*f)))) {
|
if (!(f = dm_malloc(sizeof(*f)))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(f, 0, sizeof(*f));
|
memset(f, 0, sizeof(*f));
|
||||||
f->data.buf.buf = buf;
|
|
||||||
f->data.buf.size = size;
|
f->data.buf.size = 65536; /* Initial metadata limit */
|
||||||
|
if (!(f->data.buf.start = dm_malloc(f->data.buf.size))) {
|
||||||
|
log_error("text_export buffer allocation failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
f->indent = 0;
|
f->indent = 0;
|
||||||
f->header = 0;
|
f->header = 0;
|
||||||
f->out_with_comment = &_out_with_comment_raw;
|
f->out_with_comment = &_out_with_comment_raw;
|
||||||
@@ -794,15 +759,17 @@ int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
|
|||||||
|
|
||||||
if (!_text_vg_export(f, vg, desc)) {
|
if (!_text_vg_export(f, vg, desc)) {
|
||||||
stack;
|
stack;
|
||||||
r = 0;
|
dm_free(f->data.buf.start);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = f->data.buf.used + 1;
|
r = f->data.buf.used + 1;
|
||||||
|
*buf = f->data.buf.start;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dbg_free(f);
|
dm_free(f);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef outf
|
#undef outf
|
||||||
|
#undef outnl
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ static struct flag _vg_flags[] = {
|
|||||||
{LVM_WRITE, "WRITE"},
|
{LVM_WRITE, "WRITE"},
|
||||||
{CLUSTERED, "CLUSTERED"},
|
{CLUSTERED, "CLUSTERED"},
|
||||||
{SHARED, "SHARED"},
|
{SHARED, "SHARED"},
|
||||||
|
{PRECOMMITTED, NULL},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -52,8 +53,12 @@ static struct flag _lv_flags[] = {
|
|||||||
{VISIBLE_LV, "VISIBLE"},
|
{VISIBLE_LV, "VISIBLE"},
|
||||||
{PVMOVE, "PVMOVE"},
|
{PVMOVE, "PVMOVE"},
|
||||||
{LOCKED, "LOCKED"},
|
{LOCKED, "LOCKED"},
|
||||||
|
{MIRROR_IMAGE, NULL},
|
||||||
|
{MIRROR_LOG, NULL},
|
||||||
{MIRRORED, NULL},
|
{MIRRORED, NULL},
|
||||||
{VIRTUAL, NULL},
|
{VIRTUAL, NULL},
|
||||||
|
{SNAPSHOT, NULL},
|
||||||
|
{ACTIVATE_EXCL, NULL},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#include "lvm-types.h"
|
#include "lvm-types.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "pool.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Archives a vg config. 'retain_days' is the minimum number of
|
* Archives a vg config. 'retain_days' is the minimum number of
|
||||||
@@ -47,11 +46,11 @@ struct labeller *text_labeller_create(const struct format_type *fmt);
|
|||||||
|
|
||||||
int pvhdr_read(struct device *dev, char *buf);
|
int pvhdr_read(struct device *dev, char *buf);
|
||||||
|
|
||||||
int add_da(const struct format_type *fmt, struct pool *mem, struct list *das,
|
int add_da(const struct format_type *fmt, struct dm_pool *mem, struct list *das,
|
||||||
uint64_t start, uint64_t size);
|
uint64_t start, uint64_t size);
|
||||||
void del_das(struct list *das);
|
void del_das(struct list *das);
|
||||||
|
|
||||||
int add_mda(const struct format_type *fmt, struct pool *mem, struct list *mdas,
|
int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct list *mdas,
|
||||||
struct device *dev, uint64_t start, uint64_t size);
|
struct device *dev, uint64_t start, uint64_t size);
|
||||||
void del_mdas(struct list *mdas);
|
void del_mdas(struct list *mdas);
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "lvm-types.h"
|
#include "lvm-types.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "pool.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ struct text_vg_version_ops {
|
|||||||
int (*check_version) (struct config_tree * cf);
|
int (*check_version) (struct config_tree * cf);
|
||||||
struct volume_group *(*read_vg) (struct format_instance * fid,
|
struct volume_group *(*read_vg) (struct format_instance * fid,
|
||||||
struct config_tree * cf);
|
struct config_tree * cf);
|
||||||
void (*read_desc) (struct pool * mem, struct config_tree * cf,
|
void (*read_desc) (struct dm_pool * mem, struct config_tree * cf,
|
||||||
time_t *when, char **desc);
|
time_t *when, char **desc);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,11 +55,10 @@ int print_flags(uint32_t status, int type, char *buffer, size_t size);
|
|||||||
int read_flags(uint32_t *status, int type, struct config_value *cv);
|
int read_flags(uint32_t *status, int type, struct config_value *cv);
|
||||||
|
|
||||||
int print_tags(struct list *tags, char *buffer, size_t size);
|
int print_tags(struct list *tags, char *buffer, size_t size);
|
||||||
int read_tags(struct pool *mem, struct list *tags, struct config_value *cv);
|
int read_tags(struct dm_pool *mem, struct list *tags, struct config_value *cv);
|
||||||
|
|
||||||
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
|
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
|
||||||
int text_vg_export_raw(struct volume_group *vg, const char *desc, char *buf,
|
int text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf);
|
||||||
uint32_t size);
|
|
||||||
struct volume_group *text_vg_import_file(struct format_instance *fid,
|
struct volume_group *text_vg_import_file(struct format_instance *fid,
|
||||||
const char *file,
|
const char *file,
|
||||||
time_t *when, char **desc);
|
time_t *when, char **desc);
|
||||||
|
|||||||
@@ -16,9 +16,7 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "import-export.h"
|
#include "import-export.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
|
|
||||||
|
|||||||
@@ -16,22 +16,21 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "import-export.h"
|
#include "import-export.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "hash.h"
|
|
||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "lvmcache.h"
|
#include "lvmcache.h"
|
||||||
#include "lv_alloc.h"
|
#include "lv_alloc.h"
|
||||||
#include "segtypes.h"
|
#include "pv_alloc.h"
|
||||||
|
#include "segtype.h"
|
||||||
#include "text_import.h"
|
#include "text_import.h"
|
||||||
|
|
||||||
typedef int (*section_fn) (struct format_instance * fid, struct pool * mem,
|
typedef int (*section_fn) (struct format_instance * fid, struct dm_pool * mem,
|
||||||
struct volume_group * vg, struct config_node * pvn,
|
struct volume_group * vg, struct config_node * pvn,
|
||||||
struct config_node * vgn,
|
struct config_node * vgn,
|
||||||
struct hash_table * pv_hash);
|
struct dm_hash_table * pv_hash);
|
||||||
|
|
||||||
#define _read_int32(root, path, result) \
|
#define _read_int32(root, path, result) \
|
||||||
get_config_uint32(root, path, result)
|
get_config_uint32(root, path, (uint32_t *) result)
|
||||||
|
|
||||||
#define _read_uint32(root, path, result) \
|
#define _read_uint32(root, path, result) \
|
||||||
get_config_uint32(root, path, result)
|
get_config_uint32(root, path, result)
|
||||||
@@ -110,16 +109,16 @@ static int _read_id(struct id *id, struct config_node *cn, const char *path)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_pv(struct format_instance *fid, struct pool *mem,
|
static int _read_pv(struct format_instance *fid, struct dm_pool *mem,
|
||||||
struct volume_group *vg, struct config_node *pvn,
|
struct volume_group *vg, struct config_node *pvn,
|
||||||
struct config_node *vgn, struct hash_table *pv_hash)
|
struct config_node *vgn, struct dm_hash_table *pv_hash)
|
||||||
{
|
{
|
||||||
struct physical_volume *pv;
|
struct physical_volume *pv;
|
||||||
struct pv_list *pvl;
|
struct pv_list *pvl;
|
||||||
struct config_node *cn;
|
struct config_node *cn;
|
||||||
|
|
||||||
if (!(pvl = pool_zalloc(mem, sizeof(*pvl))) ||
|
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
|
||||||
!(pvl->pv = pool_zalloc(mem, sizeof(*pvl->pv)))) {
|
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -130,7 +129,7 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
|
|||||||
* Add the pv to the pv hash for quick lookup when we read
|
* Add the pv to the pv hash for quick lookup when we read
|
||||||
* the lv segments.
|
* the lv segments.
|
||||||
*/
|
*/
|
||||||
if (!hash_insert(pv_hash, pvn->key, pv)) {
|
if (!dm_hash_insert(pv_hash, pvn->key, pv)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -163,7 +162,7 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pv->vg_name = pool_strdup(mem, vg->name))) {
|
if (!(pv->vg_name = dm_pool_strdup(mem, vg->name))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -190,6 +189,7 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_init(&pv->tags);
|
list_init(&pv->tags);
|
||||||
|
list_init(&pv->segments);
|
||||||
|
|
||||||
/* Optional tags */
|
/* Optional tags */
|
||||||
if ((cn = find_config_node(pvn, "tags")) &&
|
if ((cn = find_config_node(pvn, "tags")) &&
|
||||||
@@ -208,6 +208,11 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
|
|||||||
pv->pe_alloc_count = 0;
|
pv->pe_alloc_count = 0;
|
||||||
pv->fmt = fid->fmt;
|
pv->fmt = fid->fmt;
|
||||||
|
|
||||||
|
if (!alloc_pv_segment_whole_pv(mem, pv)) {
|
||||||
|
stack;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
vg->pv_count++;
|
vg->pv_count++;
|
||||||
list_add(&vg->pvs, &pvl->list);
|
list_add(&vg->pvs, &pvl->list);
|
||||||
|
|
||||||
@@ -216,12 +221,9 @@ static int _read_pv(struct format_instance *fid, struct pool *mem,
|
|||||||
|
|
||||||
static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg)
|
static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg)
|
||||||
{
|
{
|
||||||
struct list *segh;
|
|
||||||
struct lv_segment *comp;
|
struct lv_segment *comp;
|
||||||
|
|
||||||
list_iterate(segh, &lv->segments) {
|
list_iterate_items(comp, &lv->segments) {
|
||||||
comp = list_item(segh, struct lv_segment);
|
|
||||||
|
|
||||||
if (comp->le > seg->le) {
|
if (comp->le > seg->le) {
|
||||||
list_add(&comp->list, &seg->list);
|
list_add(&comp->list, &seg->list);
|
||||||
return;
|
return;
|
||||||
@@ -232,9 +234,9 @@ static void _insert_segment(struct logical_volume *lv, struct lv_segment *seg)
|
|||||||
list_add(&lv->segments, &seg->list);
|
list_add(&lv->segments, &seg->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_segment(struct pool *mem, struct volume_group *vg,
|
static int _read_segment(struct dm_pool *mem, struct volume_group *vg,
|
||||||
struct logical_volume *lv, struct config_node *sn,
|
struct logical_volume *lv, struct config_node *sn,
|
||||||
struct hash_table *pv_hash)
|
struct dm_hash_table *pv_hash)
|
||||||
{
|
{
|
||||||
uint32_t area_count = 0u;
|
uint32_t area_count = 0u;
|
||||||
struct lv_segment *seg;
|
struct lv_segment *seg;
|
||||||
@@ -283,19 +285,13 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(seg = alloc_lv_segment(mem, area_count))) {
|
if (!(seg = alloc_lv_segment(mem, segtype, lv, start_extent,
|
||||||
|
extent_count, 0, 0, NULL, area_count,
|
||||||
|
extent_count, 0, 0, 0))) {
|
||||||
log_error("Segment allocation failed");
|
log_error("Segment allocation failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
seg->lv = lv;
|
|
||||||
seg->le = start_extent;
|
|
||||||
seg->len = extent_count;
|
|
||||||
seg->area_len = extent_count;
|
|
||||||
seg->status = 0u;
|
|
||||||
seg->segtype = segtype;
|
|
||||||
seg->extents_copied = 0u;
|
|
||||||
|
|
||||||
if (seg->segtype->ops->text_import &&
|
if (seg->segtype->ops->text_import &&
|
||||||
!seg->segtype->ops->text_import(seg, sn, pv_hash)) {
|
!seg->segtype->ops->text_import(seg, sn, pv_hash)) {
|
||||||
stack;
|
stack;
|
||||||
@@ -315,17 +311,18 @@ static int _read_segment(struct pool *mem, struct volume_group *vg,
|
|||||||
*/
|
*/
|
||||||
_insert_segment(lv, seg);
|
_insert_segment(lv, seg);
|
||||||
|
|
||||||
if (seg->segtype->flags & SEG_AREAS_MIRRORED)
|
if (seg_is_mirrored(seg))
|
||||||
lv->status |= MIRRORED;
|
lv->status |= MIRRORED;
|
||||||
|
|
||||||
if (seg->segtype->flags & SEG_VIRTUAL)
|
if (seg_is_virtual(seg))
|
||||||
lv->status |= VIRTUAL;
|
lv->status |= VIRTUAL;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
|
int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
|
||||||
const struct config_node *cn, struct hash_table *pv_hash)
|
const struct config_node *cn, struct dm_hash_table *pv_hash,
|
||||||
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
unsigned int s;
|
unsigned int s;
|
||||||
struct config_value *cv;
|
struct config_value *cv;
|
||||||
@@ -360,20 +357,14 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME Cope if LV not yet read in */
|
/* FIXME Cope if LV not yet read in */
|
||||||
if ((pv = hash_lookup(pv_hash, cv->v.str))) {
|
if ((pv = dm_hash_lookup(pv_hash, cv->v.str))) {
|
||||||
seg->area[s].type = AREA_PV;
|
if (!set_lv_segment_area_pv(seg, s, pv, cv->next->v.i)) {
|
||||||
seg->area[s].u.pv.pv = pv;
|
stack;
|
||||||
seg->area[s].u.pv.pe = cv->next->v.i;
|
return 0;
|
||||||
/*
|
}
|
||||||
* Adjust extent counts in the pv and vg.
|
|
||||||
*/
|
|
||||||
pv->pe_alloc_count += seg->area_len;
|
|
||||||
seg->lv->vg->free_count -= seg->area_len;
|
|
||||||
|
|
||||||
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
|
} else if ((lv1 = find_lv(seg->lv->vg, cv->v.str))) {
|
||||||
seg->area[s].type = AREA_LV;
|
set_lv_segment_area_lv(seg, s, lv1, cv->next->v.i,
|
||||||
seg->area[s].u.lv.lv = lv1;
|
flags);
|
||||||
seg->area[s].u.lv.le = cv->next->v.i;
|
|
||||||
} else {
|
} else {
|
||||||
log_error("Couldn't find volume '%s' "
|
log_error("Couldn't find volume '%s' "
|
||||||
"for segment '%s'.",
|
"for segment '%s'.",
|
||||||
@@ -396,9 +387,9 @@ int text_import_areas(struct lv_segment *seg, const struct config_node *sn,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_segments(struct pool *mem, struct volume_group *vg,
|
static int _read_segments(struct dm_pool *mem, struct volume_group *vg,
|
||||||
struct logical_volume *lv, struct config_node *lvn,
|
struct logical_volume *lv, struct config_node *lvn,
|
||||||
struct hash_table *pv_hash)
|
struct dm_hash_table *pv_hash)
|
||||||
{
|
{
|
||||||
struct config_node *sn;
|
struct config_node *sn;
|
||||||
int count = 0, seg_count;
|
int count = 0, seg_count;
|
||||||
@@ -437,7 +428,7 @@ static int _read_segments(struct pool *mem, struct volume_group *vg,
|
|||||||
/*
|
/*
|
||||||
* Check there are no gaps or overlaps in the lv.
|
* Check there are no gaps or overlaps in the lv.
|
||||||
*/
|
*/
|
||||||
if (!lv_check_segments(lv)) {
|
if (!check_lv_segments(lv, 0)) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -453,23 +444,23 @@ static int _read_segments(struct pool *mem, struct volume_group *vg,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_lvnames(struct format_instance *fid, struct pool *mem,
|
static int _read_lvnames(struct format_instance *fid, struct dm_pool *mem,
|
||||||
struct volume_group *vg, struct config_node *lvn,
|
struct volume_group *vg, struct config_node *lvn,
|
||||||
struct config_node *vgn, struct hash_table *pv_hash)
|
struct config_node *vgn, struct dm_hash_table *pv_hash)
|
||||||
{
|
{
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
struct lv_list *lvl;
|
struct lv_list *lvl;
|
||||||
struct config_node *cn;
|
struct config_node *cn;
|
||||||
|
|
||||||
if (!(lvl = pool_zalloc(mem, sizeof(*lvl))) ||
|
if (!(lvl = dm_pool_zalloc(mem, sizeof(*lvl))) ||
|
||||||
!(lvl->lv = pool_zalloc(mem, sizeof(*lvl->lv)))) {
|
!(lvl->lv = dm_pool_zalloc(mem, sizeof(*lvl->lv)))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv = lvl->lv;
|
lv = lvl->lv;
|
||||||
|
|
||||||
if (!(lv->name = pool_strdup(mem, lvn->key))) {
|
if (!(lv->name = dm_pool_strdup(mem, lvn->key))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -508,6 +499,8 @@ static int _read_lvnames(struct format_instance *fid, struct pool *mem,
|
|||||||
if (!_read_int32(lvn, "read_ahead", &lv->read_ahead))
|
if (!_read_int32(lvn, "read_ahead", &lv->read_ahead))
|
||||||
lv->read_ahead = 0;
|
lv->read_ahead = 0;
|
||||||
|
|
||||||
|
lv->snapshot = NULL;
|
||||||
|
list_init(&lv->snapshot_segs);
|
||||||
list_init(&lv->segments);
|
list_init(&lv->segments);
|
||||||
list_init(&lv->tags);
|
list_init(&lv->tags);
|
||||||
|
|
||||||
@@ -526,9 +519,9 @@ static int _read_lvnames(struct format_instance *fid, struct pool *mem,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_lvsegs(struct format_instance *fid, struct pool *mem,
|
static int _read_lvsegs(struct format_instance *fid, struct dm_pool *mem,
|
||||||
struct volume_group *vg, struct config_node *lvn,
|
struct volume_group *vg, struct config_node *lvn,
|
||||||
struct config_node *vgn, struct hash_table *pv_hash)
|
struct config_node *vgn, struct dm_hash_table *pv_hash)
|
||||||
{
|
{
|
||||||
struct logical_volume *lv;
|
struct logical_volume *lv;
|
||||||
struct lv_list *lvl;
|
struct lv_list *lvl;
|
||||||
@@ -561,24 +554,29 @@ static int _read_lvsegs(struct format_instance *fid, struct pool *mem,
|
|||||||
|
|
||||||
lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
|
lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size;
|
||||||
|
|
||||||
/* Skip this for now for snapshots */
|
/*
|
||||||
if (!(lv->status & SNAPSHOT)) {
|
* FIXME We now have 2 LVs for each snapshot. The real one was
|
||||||
lv->minor = -1;
|
* created by vg_add_snapshot from the segment text_import.
|
||||||
if ((lv->status & FIXED_MINOR) &&
|
*/
|
||||||
!_read_int32(lvn, "minor", &lv->minor)) {
|
if (lv->status & SNAPSHOT) {
|
||||||
log_error("Couldn't read minor number for logical "
|
|
||||||
"volume %s.", lv->name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
lv->major = -1;
|
|
||||||
if ((lv->status & FIXED_MINOR) &&
|
|
||||||
!_read_int32(lvn, "major", &lv->major)) {
|
|
||||||
log_error("Couldn't read major number for logical "
|
|
||||||
"volume %s.", lv->name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vg->lv_count--;
|
vg->lv_count--;
|
||||||
list_del(&lvl->list);
|
list_del(&lvl->list);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv->minor = -1;
|
||||||
|
if ((lv->status & FIXED_MINOR) &&
|
||||||
|
!_read_int32(lvn, "minor", &lv->minor)) {
|
||||||
|
log_error("Couldn't read minor number for logical "
|
||||||
|
"volume %s.", lv->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv->major = -1;
|
||||||
|
if ((lv->status & FIXED_MINOR) &&
|
||||||
|
!_read_int32(lvn, "major", &lv->major)) {
|
||||||
|
log_error("Couldn't read major number for logical "
|
||||||
|
"volume %s.", lv->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -586,9 +584,9 @@ static int _read_lvsegs(struct format_instance *fid, struct pool *mem,
|
|||||||
|
|
||||||
static int _read_sections(struct format_instance *fid,
|
static int _read_sections(struct format_instance *fid,
|
||||||
const char *section, section_fn fn,
|
const char *section, section_fn fn,
|
||||||
struct pool *mem,
|
struct dm_pool *mem,
|
||||||
struct volume_group *vg, struct config_node *vgn,
|
struct volume_group *vg, struct config_node *vgn,
|
||||||
struct hash_table *pv_hash, int optional)
|
struct dm_hash_table *pv_hash, int optional)
|
||||||
{
|
{
|
||||||
struct config_node *n;
|
struct config_node *n;
|
||||||
|
|
||||||
@@ -616,8 +614,8 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
|||||||
{
|
{
|
||||||
struct config_node *vgn, *cn;
|
struct config_node *vgn, *cn;
|
||||||
struct volume_group *vg;
|
struct volume_group *vg;
|
||||||
struct hash_table *pv_hash = NULL;
|
struct dm_hash_table *pv_hash = NULL;
|
||||||
struct pool *mem = fid->fmt->cmd->mem;
|
struct dm_pool *mem = fid->fmt->cmd->mem;
|
||||||
|
|
||||||
/* skip any top-level values */
|
/* skip any top-level values */
|
||||||
for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
|
for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ;
|
||||||
@@ -627,7 +625,7 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vg = pool_zalloc(mem, sizeof(*vg)))) {
|
if (!(vg = dm_pool_zalloc(mem, sizeof(*vg)))) {
|
||||||
stack;
|
stack;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -637,12 +635,12 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
|||||||
/* eg Set to instance of fmt1 here if reading a format1 backup? */
|
/* eg Set to instance of fmt1 here if reading a format1 backup? */
|
||||||
vg->fid = fid;
|
vg->fid = fid;
|
||||||
|
|
||||||
if (!(vg->name = pool_strdup(mem, vgn->key))) {
|
if (!(vg->name = dm_pool_strdup(mem, vgn->key))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vg->system_id = pool_zalloc(mem, NAME_LEN))) {
|
if (!(vg->system_id = dm_pool_zalloc(mem, NAME_LEN))) {
|
||||||
stack;
|
stack;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -722,7 +720,7 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
|||||||
* The pv hash memoises the pv section names -> pv
|
* The pv hash memoises the pv section names -> pv
|
||||||
* structures.
|
* structures.
|
||||||
*/
|
*/
|
||||||
if (!(pv_hash = hash_create(32))) {
|
if (!(pv_hash = dm_hash_create(32))) {
|
||||||
log_error("Couldn't create hash table.");
|
log_error("Couldn't create hash table.");
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
@@ -736,7 +734,6 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_init(&vg->lvs);
|
list_init(&vg->lvs);
|
||||||
list_init(&vg->snapshots);
|
|
||||||
list_init(&vg->tags);
|
list_init(&vg->tags);
|
||||||
|
|
||||||
/* Optional tags */
|
/* Optional tags */
|
||||||
@@ -760,7 +757,13 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
|||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_destroy(pv_hash);
|
if (!fixup_imported_mirrors(vg)) {
|
||||||
|
log_error("Failed to fixup mirror pointers after import for "
|
||||||
|
"volume group %s.", vg->name);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
dm_hash_destroy(pv_hash);
|
||||||
|
|
||||||
if (vg->status & PARTIAL_VG) {
|
if (vg->status & PARTIAL_VG) {
|
||||||
vg->status &= ~LVM_WRITE;
|
vg->status &= ~LVM_WRITE;
|
||||||
@@ -774,13 +777,13 @@ static struct volume_group *_read_vg(struct format_instance *fid,
|
|||||||
|
|
||||||
bad:
|
bad:
|
||||||
if (pv_hash)
|
if (pv_hash)
|
||||||
hash_destroy(pv_hash);
|
dm_hash_destroy(pv_hash);
|
||||||
|
|
||||||
pool_free(mem, vg);
|
dm_pool_free(mem, vg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _read_desc(struct pool *mem,
|
static void _read_desc(struct dm_pool *mem,
|
||||||
struct config_tree *cft, time_t *when, char **desc)
|
struct config_tree *cft, time_t *when, char **desc)
|
||||||
{
|
{
|
||||||
const char *d;
|
const char *d;
|
||||||
@@ -789,7 +792,7 @@ static void _read_desc(struct pool *mem,
|
|||||||
log_suppress(1);
|
log_suppress(1);
|
||||||
d = find_config_str(cft->root, "description", "");
|
d = find_config_str(cft->root, "description", "");
|
||||||
log_suppress(0);
|
log_suppress(0);
|
||||||
*desc = pool_strdup(mem, d);
|
*desc = dm_pool_strdup(mem, d);
|
||||||
|
|
||||||
get_config_uint32(cft->root, "creation_time", &u);
|
get_config_uint32(cft->root, "creation_time", &u);
|
||||||
*when = u;
|
*when = u;
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ struct data_area_list {
|
|||||||
/* On disk */
|
/* On disk */
|
||||||
struct pv_header {
|
struct pv_header {
|
||||||
uint8_t pv_uuid[ID_LEN];
|
uint8_t pv_uuid[ID_LEN];
|
||||||
|
|
||||||
|
/* This size can be overridden if PV belongs to a VG */
|
||||||
uint64_t device_size_xl; /* Bytes */
|
uint64_t device_size_xl; /* Bytes */
|
||||||
|
|
||||||
/* NULL-terminated list of data areas followed by */
|
/* NULL-terminated list of data areas followed by */
|
||||||
@@ -81,5 +83,6 @@ struct mda_context {
|
|||||||
#define FMTT_VERSION 1
|
#define FMTT_VERSION 1
|
||||||
#define MDA_HEADER_SIZE 512
|
#define MDA_HEADER_SIZE 512
|
||||||
#define LVM2_LABEL "LVM2 001"
|
#define LVM2_LABEL "LVM2 001"
|
||||||
|
#define MDA_SIZE_MIN (8 * getpagesize())
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
#include "import-export.h"
|
#include "import-export.h"
|
||||||
#include "pool.h"
|
|
||||||
#include "str_list.h"
|
#include "str_list.h"
|
||||||
#include "lvm-string.h"
|
#include "lvm-string.h"
|
||||||
|
|
||||||
@@ -53,7 +52,7 @@ int print_tags(struct list *tags, char *buffer, size_t size)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_tags(struct pool *mem, struct list *tags, struct config_value *cv)
|
int read_tags(struct dm_pool *mem, struct list *tags, struct config_value *cv)
|
||||||
{
|
{
|
||||||
if (cv->type == CFG_EMPTY_ARRAY)
|
if (cv->type == CFG_EMPTY_ARRAY)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -64,7 +63,7 @@ int read_tags(struct pool *mem, struct list *tags, struct config_value *cv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!str_list_add(mem, tags, pool_strdup(mem, cv->v.str))) {
|
if (!str_list_add(mem, tags, dm_pool_strdup(mem, cv->v.str))) {
|
||||||
stack;
|
stack;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user