mirror of
git://sourceware.org/git/lvm2.git
synced 2026-01-16 20:32:47 +03:00
Compare commits
540 Commits
dev-dct-wr
...
dev-dct-sc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31e2c4c1a6 | ||
|
|
09b0eea6a0 | ||
|
|
440d6ae79f | ||
|
|
8331321070 | ||
|
|
17b2746486 | ||
|
|
bb45e33518 | ||
|
|
ba3707d953 | ||
|
|
df27392c8c | ||
|
|
ca930bd936 | ||
|
|
5e17203ff5 | ||
|
|
9759f915e7 | ||
|
|
ff677aa69f | ||
|
|
a7f334a532 | ||
|
|
c43f2f8ae0 | ||
|
|
fe05828e7e | ||
|
|
0a4d6d9d1d | ||
|
|
e9950efff1 | ||
|
|
e75bd71aae | ||
|
|
92b47d8eb8 | ||
|
|
38abd6bb2c | ||
|
|
91d3b56875 | ||
|
|
fc0495ea04 | ||
|
|
874001ee6e | ||
|
|
8c7b2df41f | ||
|
|
f83e11ff43 | ||
|
|
692fe7bb31 | ||
|
|
fe660467fa | ||
|
|
5b361b197e | ||
|
|
2097c27c05 | ||
|
|
759b0392d5 | ||
|
|
c64dbc7ee8 | ||
|
|
2bce6faed0 | ||
|
|
e7f107c246 | ||
|
|
247f69f9aa | ||
|
|
b725b5ea6e | ||
|
|
4a746f7ffc | ||
|
|
a65f8e0a62 | ||
|
|
102294f978 | ||
|
|
8b904dc711 | ||
|
|
affe1af148 | ||
|
|
ef1c57e68f | ||
|
|
d02f5392a0 | ||
|
|
7a8b7b4add | ||
|
|
3e2f09d78b | ||
|
|
01b05cf51d | ||
|
|
64719861ec | ||
|
|
00f603de2c | ||
|
|
6b00c8c910 | ||
|
|
92fcfc59b2 | ||
|
|
318bb3a06b | ||
|
|
71933d3496 | ||
|
|
2419345b9d | ||
|
|
4dc5d4ac7e | ||
|
|
fcbed26393 | ||
|
|
9cdd4dcca7 | ||
|
|
64a8505b96 | ||
|
|
05eb90db68 | ||
|
|
fccd6e0346 | ||
|
|
348c46c8fc | ||
|
|
a21028dea7 | ||
|
|
579c941321 | ||
|
|
6f61de3009 | ||
|
|
f678052385 | ||
|
|
6a099707c4 | ||
|
|
49caa9f3b1 | ||
|
|
51fd232b8e | ||
|
|
21bdd0a359 | ||
|
|
8f85834a33 | ||
|
|
25b672417e | ||
|
|
395ce6c2bb | ||
|
|
2b3dcd754f | ||
|
|
86a3a0c765 | ||
|
|
e1287c3b71 | ||
|
|
04fd55a0c9 | ||
|
|
cdcd8011d0 | ||
|
|
d388b36da2 | ||
|
|
d95b26fae0 | ||
|
|
ece80cd0fb | ||
|
|
bf461b99c6 | ||
|
|
7e13586837 | ||
|
|
d7237ca63a | ||
|
|
3d96203e21 | ||
|
|
7e77e250a9 | ||
|
|
d1f9845c96 | ||
|
|
cfe26470e3 | ||
|
|
2b90466f78 | ||
|
|
80ef913872 | ||
|
|
65c4f81dc2 | ||
|
|
5e8307f4bf | ||
|
|
66dd481f46 | ||
|
|
d651b340e6 | ||
|
|
7b77226df2 | ||
|
|
a616abba03 | ||
|
|
5eac292925 | ||
|
|
d1f8978ac5 | ||
|
|
5f75f5e2bc | ||
|
|
9164a393de | ||
|
|
0f87b015b5 | ||
|
|
b1ad32acd6 | ||
|
|
82e3b2e0ad | ||
|
|
7bde16f5e1 | ||
|
|
d94e5ba5af | ||
|
|
efd0939583 | ||
|
|
679116a9b8 | ||
|
|
dc934b13b9 | ||
|
|
54f98c94b4 | ||
|
|
adfdfd9c58 | ||
|
|
b94f2a8b55 | ||
|
|
8daf5cd45f | ||
|
|
353718785f | ||
|
|
0004ffa73a | ||
|
|
b75e26874e | ||
|
|
87a3ea7f8f | ||
|
|
94c264b975 | ||
|
|
9a33388c1a | ||
|
|
9eca131256 | ||
|
|
396d93937d | ||
|
|
31410447fd | ||
|
|
a5f83cb612 | ||
|
|
151377dd50 | ||
|
|
19ff0d983e | ||
|
|
53fa1582d9 | ||
|
|
e01ce8e2ae | ||
|
|
441b702362 | ||
|
|
d86b583644 | ||
|
|
b76283c4b3 | ||
|
|
f5efe1beb5 | ||
|
|
2e84dd47d4 | ||
|
|
ebf33323b9 | ||
|
|
75424dd692 | ||
|
|
57b5bc9c87 | ||
|
|
744afec6c0 | ||
|
|
aee0cd6530 | ||
|
|
01f108c4d0 | ||
|
|
0a28e3c44b | ||
|
|
6f6583afed | ||
|
|
9980ed9527 | ||
|
|
79a168d119 | ||
|
|
b99f7d0df9 | ||
|
|
e86cd9c5ba | ||
|
|
9452e62efb | ||
|
|
f1bfc0621b | ||
|
|
d2522f4a05 | ||
|
|
ff8aaadec9 | ||
|
|
1f17b1c565 | ||
|
|
fe4f83171d | ||
|
|
287565fd5d | ||
|
|
f1d3648dc7 | ||
|
|
14ea63cfc7 | ||
|
|
60eb608d66 | ||
|
|
c23f4c8075 | ||
|
|
40b277ae17 | ||
|
|
1398e66a55 | ||
|
|
a8480f0f6e | ||
|
|
12949ea886 | ||
|
|
01d5e4d1ca | ||
|
|
d5b0c72f40 | ||
|
|
ff5776024f | ||
|
|
2aaea13aaa | ||
|
|
648188df2a | ||
|
|
f1e8437c59 | ||
|
|
1cedbaf137 | ||
|
|
1a17a5ab80 | ||
|
|
d9b9751032 | ||
|
|
0ddbc4c5cd | ||
|
|
8a550fa3e8 | ||
|
|
afbaab20c7 | ||
|
|
f584f0cd9e | ||
|
|
5ec7992e29 | ||
|
|
feb7fef6c8 | ||
|
|
1f7bd719d0 | ||
|
|
12222add1a | ||
|
|
37d603268f | ||
|
|
f07a793813 | ||
|
|
53338cf566 | ||
|
|
8e9bc52b15 | ||
|
|
a55f4a8fe2 | ||
|
|
93336685f6 | ||
|
|
1d6e1d08a8 | ||
|
|
51ac56a05e | ||
|
|
02e02a5ccc | ||
|
|
4c59b2aa21 | ||
|
|
5ef8d84569 | ||
|
|
49575a6ce1 | ||
|
|
7768650d87 | ||
|
|
25c665d555 | ||
|
|
6db533c439 | ||
|
|
3ed79d8dfe | ||
|
|
85fae836c0 | ||
|
|
9bcc76b63c | ||
|
|
5feb99dda6 | ||
|
|
0558b223b8 | ||
|
|
73710b87fb | ||
|
|
c1f5ca6751 | ||
|
|
0783c661b9 | ||
|
|
2151b71819 | ||
|
|
28865f971e | ||
|
|
63c58d2a5d | ||
|
|
9684e82cc4 | ||
|
|
afd43a75f2 | ||
|
|
a126dde069 | ||
|
|
18f2475fa1 | ||
|
|
8df0a32abb | ||
|
|
dd1f5f9a24 | ||
|
|
93f2d194ac | ||
|
|
14a3c34983 | ||
|
|
d0644fb2c3 | ||
|
|
712f7dfb4c | ||
|
|
26d76d31c5 | ||
|
|
a5fc6a0fe7 | ||
|
|
0b2a037c80 | ||
|
|
e8b4306eb0 | ||
|
|
acac3cb524 | ||
|
|
b19e036918 | ||
|
|
370749a4b8 | ||
|
|
7575c7ae5c | ||
|
|
f370cda716 | ||
|
|
0993355300 | ||
|
|
077040199d | ||
|
|
7166bbd9c2 | ||
|
|
a7d7471906 | ||
|
|
b1483dcbac | ||
|
|
76d203517b | ||
|
|
ada99f939f | ||
|
|
77432ee137 | ||
|
|
daca6e2c22 | ||
|
|
bee8027cfa | ||
|
|
8d2ad4419a | ||
|
|
f1858d209d | ||
|
|
09621725d0 | ||
|
|
b6cff47bde | ||
|
|
d6bc11bf72 | ||
|
|
2dd43a7314 | ||
|
|
94c4af232c | ||
|
|
179f59a0ca | ||
|
|
05920e3818 | ||
|
|
edcc410835 | ||
|
|
d5b37f24f4 | ||
|
|
e27baa791f | ||
|
|
ed90a3d9b4 | ||
|
|
fe3ef6867f | ||
|
|
3d26bde1c0 | ||
|
|
e86798203e | ||
|
|
48d04afaa2 | ||
|
|
c6a76c1ffe | ||
|
|
81d3639955 | ||
|
|
d3d28b1b64 | ||
|
|
d37b19aaaa | ||
|
|
79d8d06217 | ||
|
|
cc140f68a5 | ||
|
|
076e155697 | ||
|
|
b4ab2a1051 | ||
|
|
26fb6b5e8d | ||
|
|
accf324ccb | ||
|
|
c06325263f | ||
|
|
1880b573f3 | ||
|
|
8e7690b798 | ||
|
|
1c3774c7a8 | ||
|
|
7a9efc5fae | ||
|
|
b35ef9d67c | ||
|
|
22554c3ff0 | ||
|
|
5a73399b73 | ||
|
|
adc238062d | ||
|
|
a9b4acd511 | ||
|
|
e5a600860c | ||
|
|
a60c8748ea | ||
|
|
8cbe4a171e | ||
|
|
d682ad619a | ||
|
|
a481fdaa35 | ||
|
|
583cf413d5 | ||
|
|
fda7bc1297 | ||
|
|
80d0f200d0 | ||
|
|
e793ff1e18 | ||
|
|
db37905d7f | ||
|
|
87659256f0 | ||
|
|
92ee16f7c0 | ||
|
|
53bad89a7b | ||
|
|
8b2cdd8d3a | ||
|
|
94701b700b | ||
|
|
4d75c4f597 | ||
|
|
0363e4de70 | ||
|
|
e6912cc61c | ||
|
|
b4a74d1008 | ||
|
|
800a93d4ac | ||
|
|
78406ef617 | ||
|
|
e5e957e330 | ||
|
|
8a92f70709 | ||
|
|
f69ff4b84a | ||
|
|
6e9ccf7b6f | ||
|
|
bc1bc4cffc | ||
|
|
eadd58a97d | ||
|
|
1a451207b8 | ||
|
|
5edb353062 | ||
|
|
0a2d7c57a1 | ||
|
|
a18409b6d1 | ||
|
|
ff712987a5 | ||
|
|
b4dfe026dd | ||
|
|
fab9987ad7 | ||
|
|
b563c926ba | ||
|
|
664d3b0f22 | ||
|
|
5141a510bd | ||
|
|
3608e8aee7 | ||
|
|
a3bb8f2ec1 | ||
|
|
941f67ed09 | ||
|
|
bbac843268 | ||
|
|
262008f1ce | ||
|
|
236a45dfc5 | ||
|
|
4bbaff1fa6 | ||
|
|
2cbe88d6a1 | ||
|
|
a654148b76 | ||
|
|
d7bb23dd15 | ||
|
|
23afad8247 | ||
|
|
c4f5d93122 | ||
|
|
d86e943b80 | ||
|
|
f4543aca15 | ||
|
|
dac8274701 | ||
|
|
7a99dac9ad | ||
|
|
127c2fc6e2 | ||
|
|
d4293b579d | ||
|
|
6097dfb9ad | ||
|
|
94712e3233 | ||
|
|
a66380ea3e | ||
|
|
f7912635a0 | ||
|
|
8a03675241 | ||
|
|
bee9b5c1d8 | ||
|
|
74936f53f7 | ||
|
|
d95c0e977c | ||
|
|
a6075fe2f2 | ||
|
|
241c63f7a7 | ||
|
|
131ca0eb95 | ||
|
|
15c588f931 | ||
|
|
75037bee5d | ||
|
|
d01c17ff22 | ||
|
|
7342ab06fc | ||
|
|
5f7a7af7f2 | ||
|
|
c05077f4d4 | ||
|
|
177b63becc | ||
|
|
88d04e9173 | ||
|
|
413a114cdb | ||
|
|
b2616cd456 | ||
|
|
d2a3bfe6ca | ||
|
|
17802084c9 | ||
|
|
d5f3239de4 | ||
|
|
843ee943ab | ||
|
|
3cbb751815 | ||
|
|
6d6e1ae887 | ||
|
|
64447e9d9b | ||
|
|
e5456c259f | ||
|
|
f4200acac2 | ||
|
|
dac990ae03 | ||
|
|
d3cff64408 | ||
|
|
ca12dae32b | ||
|
|
ff21723512 | ||
|
|
d602837b91 | ||
|
|
84679d254f | ||
|
|
2d64ffaee5 | ||
|
|
78c7ae7cd2 | ||
|
|
dceef4709d | ||
|
|
936c7b5104 | ||
|
|
bc0cb66304 | ||
|
|
a125a3bb50 | ||
|
|
ee9488488f | ||
|
|
7df4a13282 | ||
|
|
e10633394d | ||
|
|
2244a56021 | ||
|
|
3bea893733 | ||
|
|
f5fbb1b76f | ||
|
|
89a3440fc0 | ||
|
|
e9d10f3711 | ||
|
|
d0b0c20077 | ||
|
|
9cb913ab4b | ||
|
|
8e1771f857 | ||
|
|
1042cd9a61 | ||
|
|
eb3dcc72eb | ||
|
|
0b7a4503e5 | ||
|
|
67790d7e3b | ||
|
|
73bea16c92 | ||
|
|
00531186fc | ||
|
|
56620b9039 | ||
|
|
2a9a3346e7 | ||
|
|
eb1160ee42 | ||
|
|
fa64c51428 | ||
|
|
9dd759c6b1 | ||
|
|
081e47912e | ||
|
|
589c654562 | ||
|
|
e946a5e690 | ||
|
|
f87d1a2abb | ||
|
|
6846af6612 | ||
|
|
39eee85fff | ||
|
|
456b659b4e | ||
|
|
8bfa4439e1 | ||
|
|
4e976d9960 | ||
|
|
e080e35c83 | ||
|
|
520bd9356e | ||
|
|
da29afe028 | ||
|
|
5509e764f1 | ||
|
|
8d93d8b7b7 | ||
|
|
824230e1e2 | ||
|
|
9d190d6b46 | ||
|
|
8d3ce32880 | ||
|
|
7528a33630 | ||
|
|
3bab1a1026 | ||
|
|
db4af67b37 | ||
|
|
aa34da6ecc | ||
|
|
6fad7f2eac | ||
|
|
91d6822534 | ||
|
|
b36b4b82d8 | ||
|
|
135c226e26 | ||
|
|
83fe6e720f | ||
|
|
f7d9542aed | ||
|
|
5d820b0201 | ||
|
|
0c842ee8ad | ||
|
|
5237175cb6 | ||
|
|
b5f906e984 | ||
|
|
5ecd65e6f2 | ||
|
|
b140bba9fe | ||
|
|
ac09fa08aa | ||
|
|
e43b5f1e3c | ||
|
|
646e3280dd | ||
|
|
9e836c77a0 | ||
|
|
12667e9897 | ||
|
|
3cba071254 | ||
|
|
26a09c84c9 | ||
|
|
2c5e034cd3 | ||
|
|
b9846bdc3e | ||
|
|
868b733588 | ||
|
|
fbaf5a32bb | ||
|
|
9c0ce4daa2 | ||
|
|
19e1373580 | ||
|
|
5bf1dba9eb | ||
|
|
a7cb25c877 | ||
|
|
a915cd5a46 | ||
|
|
f87ff95e32 | ||
|
|
096edeee71 | ||
|
|
3ef0861355 | ||
|
|
14008ead2a | ||
|
|
3af61d8646 | ||
|
|
53666d6ee3 | ||
|
|
4486f08d51 | ||
|
|
c94d78f068 | ||
|
|
f49bedc029 | ||
|
|
04cd4df847 | ||
|
|
a1e2541333 | ||
|
|
82bffa99ad | ||
|
|
4b371246f5 | ||
|
|
a383586177 | ||
|
|
f90082ce8f | ||
|
|
2895180058 | ||
|
|
3cc9efc0ed | ||
|
|
96910de4c7 | ||
|
|
f74f94c2dd | ||
|
|
427121efc7 | ||
|
|
ef2e0d3d68 | ||
|
|
d280999b62 | ||
|
|
d422aa7924 | ||
|
|
3bf2ca11d9 | ||
|
|
e429e69b65 | ||
|
|
2c597c73a8 | ||
|
|
be9b731f44 | ||
|
|
9b173bb931 | ||
|
|
6373f39092 | ||
|
|
b86eb913c1 | ||
|
|
5ec24dfb0b | ||
|
|
39dec26508 | ||
|
|
bdc2f4c704 | ||
|
|
eed060f040 | ||
|
|
99e168162a | ||
|
|
2be585b79c | ||
|
|
018bba897c | ||
|
|
df4c50396b | ||
|
|
87ee401eea | ||
|
|
67d8fb1e83 | ||
|
|
834cba000a | ||
|
|
cb54d0801d | ||
|
|
ae2af1d5ed | ||
|
|
51c83f1483 | ||
|
|
8454ce66c5 | ||
|
|
bee9f4efdd | ||
|
|
48dfc388f7 | ||
|
|
6e8a32e4fd | ||
|
|
bfafd2b4e9 | ||
|
|
026d94d882 | ||
|
|
48030389ce | ||
|
|
25b942a8ac | ||
|
|
b26e565ee5 | ||
|
|
19ddad12ca | ||
|
|
b17b556e26 | ||
|
|
9fa4c099fb | ||
|
|
a9fd207192 | ||
|
|
3acf6040b5 | ||
|
|
8f5695fa71 | ||
|
|
be0bf43d74 | ||
|
|
45f0c48365 | ||
|
|
abc9265a06 | ||
|
|
f96b455506 | ||
|
|
b4212be2e7 | ||
|
|
b218a7cfe7 | ||
|
|
a690d16d29 | ||
|
|
f08ef23856 | ||
|
|
665d265349 | ||
|
|
fa2fa9f36d | ||
|
|
ce6e74f485 | ||
|
|
5485ec10e2 | ||
|
|
cddeaed6e9 | ||
|
|
8532b1ca97 | ||
|
|
4b8e5ad595 | ||
|
|
9ae1935b74 | ||
|
|
74adbec77f | ||
|
|
2ec29d0677 | ||
|
|
9757b4726c | ||
|
|
37227b8ad6 | ||
|
|
0534723a2d | ||
|
|
ff1324d595 | ||
|
|
71162b2b4e | ||
|
|
0b6ee6a912 | ||
|
|
a4c56a3bc3 | ||
|
|
6308365d48 | ||
|
|
3e8bd8d1bd | ||
|
|
e9503f257a | ||
|
|
b84a9927b7 | ||
|
|
23ef677762 | ||
|
|
5dbe2fdd9d | ||
|
|
9fe7aba251 | ||
|
|
57594fe673 | ||
|
|
47608ff49b | ||
|
|
7691213a91 | ||
|
|
9b3458d5a9 | ||
|
|
a2affffed5 | ||
|
|
205fb35b50 | ||
|
|
10a095a58b | ||
|
|
b68141a49d | ||
|
|
9c0253d930 | ||
|
|
aba9652e58 | ||
|
|
1cc75317f9 | ||
|
|
5fef89361d | ||
|
|
2317ba3934 | ||
|
|
d7058cfa98 | ||
|
|
8801a86a3e | ||
|
|
6316959438 | ||
|
|
125da10d47 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -32,6 +32,7 @@ make.tmpl
|
||||
/configure.scan
|
||||
/cscope.*
|
||||
/html/
|
||||
/python/
|
||||
/reports/
|
||||
/tags
|
||||
/tmp/
|
||||
|
||||
45
Makefile.in
45
Makefile.in
@@ -18,7 +18,7 @@ top_builddir = @top_builddir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
|
||||
SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
|
||||
SUBDIRS = libdm conf daemons include lib libdaemon man scripts tools
|
||||
|
||||
ifeq ("@UDEV_RULES@", "yes")
|
||||
SUBDIRS += udev
|
||||
@@ -47,8 +47,6 @@ include $(top_srcdir)/base/Makefile
|
||||
include $(top_srcdir)/device_mapper/Makefile
|
||||
include $(top_srcdir)/test/unit/Makefile
|
||||
|
||||
libdm: include
|
||||
libdaemon: include
|
||||
lib: libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET)
|
||||
daemons: lib libdaemon tools
|
||||
scripts: lib
|
||||
@@ -56,16 +54,13 @@ tools: lib libdaemon
|
||||
po: tools daemons
|
||||
man: tools
|
||||
all_man: tools
|
||||
scripts: libdm
|
||||
test: tools daemons
|
||||
unit-test run-unit-test: test
|
||||
|
||||
lib.device-mapper: include.device-mapper
|
||||
libdm.device-mapper: include.device-mapper
|
||||
daemons.device-mapper: libdm.device-mapper
|
||||
tools.device-mapper: libdm.device-mapper
|
||||
scripts.device-mapper: include.device-mapper
|
||||
device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
|
||||
device_mapper: device-mapper
|
||||
|
||||
ifeq ("@INTL@", "yes")
|
||||
lib.pofile: include.pofile
|
||||
@@ -81,9 +76,10 @@ daemons.cflow: tools.cflow
|
||||
cflow: include.cflow
|
||||
endif
|
||||
|
||||
CSCOPE_DIRS = base daemons device_mapper include lib libdaemon scripts tools libdm test
|
||||
ifneq ("@CSCOPE_CMD@", "")
|
||||
cscope.out:
|
||||
@CSCOPE_CMD@ -b -R -s$(top_srcdir)
|
||||
@CSCOPE_CMD@ -b -R $(patsubst %,-s%,$(addprefix $(srcdir)/,$(CSCOPE_DIRS)))
|
||||
all: cscope.out
|
||||
endif
|
||||
DISTCLEAN_TARGETS += cscope.out
|
||||
@@ -116,11 +112,11 @@ rpm: dist
|
||||
$(LN_S) -f $(abs_top_srcdir)/spec/packages.inc $(rpmbuilddir)/SOURCES
|
||||
DM_VER=$$(cut -d- -f1 $(top_srcdir)/VERSION_DM);\
|
||||
GIT_VER=$$(cd $(top_srcdir); git describe | cut -d- --output-delimiter=. -f2,3 || echo 0);\
|
||||
sed -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \
|
||||
$(SED) -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \
|
||||
-e "s,^\(Version:[^0-9%]*\)[0-9.]*$$,\1 $(LVM_VER)," \
|
||||
-e "s,^\(Release:[^0-9%]*\)[0-9.]\+,\1 $$GIT_VER," \
|
||||
$(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc
|
||||
rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
|
||||
V=$(V) rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
|
||||
|
||||
generate: conf.generate man.generate
|
||||
$(MAKE) -C conf generate
|
||||
@@ -154,6 +150,31 @@ install_all_man:
|
||||
install_tmpfiles_configuration:
|
||||
$(MAKE) -C scripts install_tmpfiles_configuration
|
||||
|
||||
help:
|
||||
@echo -e "\nAvailable targets:"
|
||||
@echo " all Default target."
|
||||
@echo " all_man Build all man pages with generators."
|
||||
@echo " clean Remove all compile files."
|
||||
@echo " device-mapper Device mapper part of lvm2."
|
||||
@echo " dist Generate distributable file."
|
||||
@echo " distclean Remove all build files."
|
||||
@echo " generate Generate man pages for sources."
|
||||
@echo " help Display callable targets."
|
||||
@echo " install Install all files."
|
||||
@echo " install_all_man Install all man pages."
|
||||
@echo " install_cluster Install cmirrord."
|
||||
@echo " install_device-mapper Install device mapper files."
|
||||
@echo " install_initscripts Install initialization scripts."
|
||||
@echo " install_lvm2 Install lvm2 files."
|
||||
@echo " install_systemd_units Install systemd units."
|
||||
@echo " lcov Generate lcov output."
|
||||
@echo " lcov-dated Generate lcov with timedate suffix."
|
||||
@echo " lcov-reset Reset lcov counters"
|
||||
@echo " man Build man pages."
|
||||
@echo " rpm Build rpm."
|
||||
@echo " run-unit-test Run unit tests."
|
||||
@echo " tags Generate c/etags."
|
||||
|
||||
ifneq ("$(LCOV)", "")
|
||||
.PHONY: lcov-reset lcov lcov-dated
|
||||
|
||||
@@ -183,8 +204,8 @@ endif
|
||||
ifneq ($(shell which ctags 2>/dev/null),)
|
||||
.PHONY: tags
|
||||
tags:
|
||||
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
|
||||
test -f tags || find $(top_srcdir) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
|
||||
test -z "$(shell find $(addprefix $(top_srcdir)/,$(CSCOPE_DIRS)) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
|
||||
test -f tags || find $(addprefix $(top_srcdir)/,$(CSCOPE_DIRS)) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
|
||||
|
||||
CLEAN_TARGETS += tags
|
||||
endif
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.02.175-git (2020-08-09)
|
||||
1.02.179-git (2021-05-07)
|
||||
|
||||
84
WHATS_NEW
84
WHATS_NEW
@@ -1,6 +1,78 @@
|
||||
Version 2.03.11 -
|
||||
==================================
|
||||
Enhance error handling for fsadm and hanled correct fsck result.
|
||||
Version 2.03.13 -
|
||||
===============================
|
||||
Simplified handling of archive() and backup() internal calls.
|
||||
Fix load of kvdo target when it is not present in memory (2.03.12).
|
||||
|
||||
Version 2.03.12 - 07th May 2021
|
||||
===============================
|
||||
Allow attaching cache to thin data volume.
|
||||
Fix memleak when generating list of outdated pvs.
|
||||
Better hyphenation usage in man pages.
|
||||
Replace use of deprecated security_context_t with char*.
|
||||
Configure supports AIO_LIBS and AIO_CFLAGS.
|
||||
Improve build process for static builds.
|
||||
New --setautoactivation option to modify LV or VG auto activation.
|
||||
New metadata based autoactivation property for LVs and VGs.
|
||||
Improve signal handling with lvmpolld.
|
||||
Signal handler can interrupt command also for SIGTERM.
|
||||
Lvreduce --yes support.
|
||||
Add configure option --with/out-symvers for non-glibc builds.
|
||||
Report error when the filesystem is missing on fsadm resized volume.
|
||||
Handle better blockdev with --getsize64 support for fsadm.
|
||||
Do not include editline/history.h when using editline library.
|
||||
Support error and zero segtype for thin-pool data for testing.
|
||||
Support mixed extension for striped, error and zero segtypes.
|
||||
Support resize also for stacked virtual volumes.
|
||||
Skip dm-zero devices just like with dm-error target.
|
||||
Reduce ioctl() calls when checking target status.
|
||||
Merge polling does not fail, when LV is found to be already merged.
|
||||
Poll volumes with at least 100ms delays.
|
||||
Do not flush dm cache when cached LV is going to be removed.
|
||||
New lvmlockctl_kill_command configuration option.
|
||||
Support interruption while waiting on device close before deactivation.
|
||||
Flush thin-pool messages before removing more thin volumes.
|
||||
Improve hash function with less collisions and make it faster.
|
||||
Reduce ioctl count when deactivating volumes.
|
||||
Reduce number of metadata parsing.
|
||||
Enhance performance of lvremove and vgremove commands.
|
||||
Support interruption when taking archive and backup.
|
||||
Accelerate large lvremoves.
|
||||
Speedup search for cached device nodes.
|
||||
Speedup command initialization.
|
||||
Add devices file feature, off by default for now.
|
||||
Support extension of writecached volumes.
|
||||
Fix problem with unbound variable usage within fsadm.
|
||||
Fix IMSM MD RAID detection on 4k devices.
|
||||
Check for presence of VDO target before starting any conversion.
|
||||
Support metatadata profiles with volume VDO pool conversions.
|
||||
Support -Zn for conversion of already formated VDO pools.
|
||||
Avoid removing LVs on error path of lvconvert during creation volumes.
|
||||
Fix crashing lvdisplay when thin volume was waiting for merge.
|
||||
Support option --errorwhenfull when converting volume to thin-pool.
|
||||
Improve thin-performance profile support conversion to thin-pool.
|
||||
Add workaround to avoid read of internal 'converted' devices.
|
||||
Prohibit merging snapshot into the read-only thick snapshot origin.
|
||||
Restore support for flipping rw/r permissions for thin snapshot origin.
|
||||
Support resize of cached volumes.
|
||||
Disable autoactivation with global/event_activation=0.
|
||||
Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
|
||||
Allocation prints better error when metadata cannot fit on a single PV.
|
||||
Pvmove can better resolve full thin-pool tree move.
|
||||
Limit pool metadata spare to 16GiB.
|
||||
Improves conversion and allocation of pool metadata.
|
||||
Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0.
|
||||
Enhance lvdisplay to report raid available/partial.
|
||||
Support online rename of VDO pools.
|
||||
Improve removal of pmspare when last pool is removed.
|
||||
Fix problem with wiping of converted LVs.
|
||||
Fix memleak in scanning (2.03.11).
|
||||
Fix corner case allocation for thin-pools.
|
||||
|
||||
Version 2.03.11 - 08th January 2021
|
||||
===================================
|
||||
Fix pvck handling MDA at offset different from 4096.
|
||||
Partial or degraded activation of writecache is not allowed.
|
||||
Enhance error handling for fsadm and handle correct fsck result.
|
||||
Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values.
|
||||
Support using BLKZEROOUT for clearing devices.
|
||||
Support interruption when wipping LVs.
|
||||
@@ -20,6 +92,9 @@ Version 2.03.11 -
|
||||
Enhance --use-policy percentage rounding.
|
||||
Configure --with-vdo and --with-writecache as internal segments.
|
||||
Improving VDO man page examples.
|
||||
Allow pvmove of writecache origin.
|
||||
Report integrity fields.
|
||||
Integrity volumes defaults to journal mode.
|
||||
Switch code base to use flexible array syntax.
|
||||
Fix 64bit math when calculation cachevol size.
|
||||
Preserve uint32_t for seqno handling.
|
||||
@@ -191,7 +266,6 @@ Version 2.03.00 - 10th October 2018
|
||||
Remove clvmd
|
||||
Remove lvmlib (api)
|
||||
Remove lvmetad
|
||||
lvconvert: provide possible layouts between linear and striped/raid
|
||||
Use versionsort to fix archive file expiry beyond 100000 files.
|
||||
|
||||
Version 2.02.178-rc1 - 24th May 2018
|
||||
@@ -1711,7 +1785,7 @@ Version 2.02.105 - 20th January 2014
|
||||
Allow lvmetad to reuse stale socket.
|
||||
Only unlink lvmetad socket on error if created by the same process.
|
||||
Append missing newline to lvmetad missing socket path error message.
|
||||
Check for non-zero aligment in _text_pv_add_metadata_area() to not div by 0.
|
||||
Check for non-zero alignment in _text_pv_add_metadata_area() to not div by 0.
|
||||
Add allocation/use_blkid_wiping to lvm.conf to enable blkid wiping.
|
||||
Enable blkid_wiping by default if the blkid library is present.
|
||||
Add configure --disable-blkid_wiping to disable libblkid signature detection.
|
||||
|
||||
15
WHATS_NEW_DM
15
WHATS_NEW_DM
@@ -1,5 +1,14 @@
|
||||
Version 1.02.175 -
|
||||
===================================
|
||||
Version 1.02.179 -
|
||||
================================
|
||||
|
||||
Version 1.02.177 - 07th May 2021
|
||||
================================
|
||||
Configure proceeds without libaio to allow build of device-mapper only.
|
||||
Fix symbol versioning build with -O2 -flto.
|
||||
Add dm_tree_node_add_thin_pool_target_v1 with crop_metadata support.
|
||||
|
||||
Version 1.02.175 - 08th January 2021
|
||||
====================================
|
||||
|
||||
Version 1.02.173 - 09th August 2020
|
||||
===================================
|
||||
@@ -551,7 +560,7 @@ Version 1.02.86 - 23rd June 2014
|
||||
Add DM_REPORT_FIELD_TYPE_STRING_LIST: separate string and string list fields.
|
||||
Add dm_str_list to libdevmapper for string list type definition and its reuse.
|
||||
Add dmsetup -S/--select to define selection criteria for dmsetup reports.
|
||||
Add dm_report_init_with_selection to intialize report with selection criteria.
|
||||
Add dm_report_init_with_selection to initialize report with selection criteria.
|
||||
Add DM_REPORT_FIELD_TYPE_SIZE: separate number and size reporting fields.
|
||||
Use RemoveOnStop for dm-event.socket systemd unit.
|
||||
Document env var 'DM_DEFAULT_NAME_MANGLING_MODE' in dmsetup man page.
|
||||
|
||||
10
aclocal.m4
vendored
10
aclocal.m4
vendored
@@ -496,12 +496,14 @@ AC_DEFUN([AM_PATH_PYTHON],
|
||||
m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
|
||||
else
|
||||
|
||||
dnl Query Python for its version number. Getting [:3] seems to be
|
||||
dnl the best way to do this; it's what "site.py" does in the standard
|
||||
dnl library.
|
||||
dnl Query Python for its version number. Although site.py simply uses
|
||||
dnl sys.version[:3], printing that failed with Python 3.10, since the
|
||||
dnl trailing zero was eliminated. So now we output just the major
|
||||
dnl and minor version numbers, as numbers. Apparently the tertiary
|
||||
dnl version is not of interest.
|
||||
|
||||
AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
|
||||
[am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
|
||||
[am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[[:2]])"`])
|
||||
AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
|
||||
|
||||
dnl Use the values of $prefix and $exec_prefix for the corresponding
|
||||
|
||||
@@ -22,17 +22,26 @@ struct dm_hash_node {
|
||||
void *data;
|
||||
unsigned data_len;
|
||||
unsigned keylen;
|
||||
unsigned hash;
|
||||
char key[];
|
||||
};
|
||||
|
||||
struct dm_hash_table {
|
||||
unsigned num_nodes;
|
||||
unsigned num_slots;
|
||||
unsigned num_hint;
|
||||
unsigned mask_slots; /* (slots - 1) -> used as hash mask */
|
||||
unsigned collisions; /* Collissions of hash keys */
|
||||
unsigned search; /* How many keys were searched */
|
||||
unsigned found; /* How many nodes were found */
|
||||
unsigned same_hash; /* Was there a colision with same masked hash and len ? */
|
||||
struct dm_hash_node **slots;
|
||||
};
|
||||
|
||||
/* Permutation of the Integers 0 through 255 */
|
||||
static unsigned char _nums[] = {
|
||||
#if 0 /* TO BE REMOVED */
|
||||
static unsigned _hash(const void *key, unsigned len)
|
||||
{
|
||||
/* Permutation of the Integers 0 through 255 */
|
||||
static unsigned char _nums[] = {
|
||||
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
|
||||
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
|
||||
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,
|
||||
@@ -57,7 +66,79 @@ static unsigned char _nums[] = {
|
||||
44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
|
||||
163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
|
||||
209
|
||||
};
|
||||
};
|
||||
|
||||
const uint8_t *str = key;
|
||||
unsigned h = 0, g;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
h <<= 4;
|
||||
h += _nums[*str++];
|
||||
g = h & ((unsigned) 0xf << 16u);
|
||||
if (g) {
|
||||
h ^= g >> 16u;
|
||||
h ^= g >> 5u;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/* In-kernel DM hashing, still lots of collisions */
|
||||
static unsigned _hash_in_kernel(const char *key, unsigned len)
|
||||
{
|
||||
const unsigned char *str = (unsigned char *)key;
|
||||
const unsigned hash_mult = 2654435387U;
|
||||
unsigned hash = 0, i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
hash = (hash + str[i]) * hash_mult;
|
||||
|
||||
return hash;
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Adapted Bob Jenkins hash to read by 2 bytes if possible.
|
||||
* https://secure.wikimedia.org/wikipedia/en/wiki/Jenkins_hash_function
|
||||
*
|
||||
* Reduces amount of hash collisions
|
||||
*/
|
||||
static unsigned _hash(const void *key, unsigned len)
|
||||
{
|
||||
const uint8_t *str = (uint8_t*) key;
|
||||
unsigned hash = 0, i;
|
||||
unsigned sz = len / 2;
|
||||
|
||||
for(i = 0; i < sz; ++i) {
|
||||
hash += get16bits(str + 2 * i);
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
|
||||
if (len & 1) {
|
||||
hash += str[len - 1];
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 11);
|
||||
hash += (hash << 15);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static struct dm_hash_node *_create_node(const void *key, unsigned len)
|
||||
{
|
||||
@@ -71,49 +152,32 @@ static struct dm_hash_node *_create_node(const void *key, unsigned len)
|
||||
return n;
|
||||
}
|
||||
|
||||
static unsigned long _hash(const void *key, unsigned len)
|
||||
{
|
||||
const unsigned char *str = key;
|
||||
unsigned long h = 0, g;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
h <<= 4;
|
||||
h += _nums[*str++];
|
||||
g = h & ((unsigned long) 0xf << 16u);
|
||||
if (g) {
|
||||
h ^= g >> 16u;
|
||||
h ^= g >> 5u;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
struct dm_hash_table *dm_hash_create(unsigned size_hint)
|
||||
{
|
||||
size_t len;
|
||||
unsigned new_size = 16u;
|
||||
struct dm_hash_table *hc = zalloc(sizeof(*hc));
|
||||
|
||||
if (!hc)
|
||||
return_0;
|
||||
if (!hc) {
|
||||
log_error("Failed to allocate memory for hash.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hc->num_hint = size_hint;
|
||||
|
||||
/* round size hint up to a power of two */
|
||||
while (new_size < size_hint)
|
||||
new_size = new_size << 1;
|
||||
|
||||
hc->num_slots = new_size;
|
||||
hc->mask_slots = new_size - 1;
|
||||
len = sizeof(*(hc->slots)) * new_size;
|
||||
if (!(hc->slots = zalloc(len)))
|
||||
goto_bad;
|
||||
if (!(hc->slots = zalloc(len))) {
|
||||
free(hc);
|
||||
log_error("Failed to allocate slots for hash.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hc;
|
||||
|
||||
bad:
|
||||
free(hc->slots);
|
||||
free(hc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _free_nodes(struct dm_hash_table *t)
|
||||
@@ -121,7 +185,16 @@ static void _free_nodes(struct dm_hash_table *t)
|
||||
struct dm_hash_node *c, *n;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < t->num_slots; i++)
|
||||
#ifdef DEBUG
|
||||
log_debug("Free hash hint:%d slots:%d nodes:%d (s:%d f:%d c:%d h:%d)",
|
||||
t->num_hint, t->mask_slots + 1, t->num_nodes,
|
||||
t->search, t->found, t->collisions, t->same_hash);
|
||||
#endif
|
||||
|
||||
if (!t->num_nodes)
|
||||
return;
|
||||
|
||||
for (i = 0; i <= t->mask_slots; i++)
|
||||
for (c = t->slots[i]; c; c = n) {
|
||||
n = c->next;
|
||||
free(c);
|
||||
@@ -135,23 +208,32 @@ void dm_hash_destroy(struct dm_hash_table *t)
|
||||
free(t);
|
||||
}
|
||||
|
||||
static struct dm_hash_node **_find(struct dm_hash_table *t, const void *key,
|
||||
uint32_t len)
|
||||
static struct dm_hash_node **_findh(struct dm_hash_table *t, const void *key,
|
||||
uint32_t len, unsigned hash)
|
||||
{
|
||||
unsigned h = _hash(key, len) & (t->num_slots - 1);
|
||||
struct dm_hash_node **c;
|
||||
|
||||
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
|
||||
if ((*c)->keylen != len)
|
||||
continue;
|
||||
|
||||
if (!memcmp(key, (*c)->key, len))
|
||||
break;
|
||||
++t->search;
|
||||
for (c = &t->slots[hash & t->mask_slots]; *c; c = &((*c)->next)) {
|
||||
if ((*c)->keylen == len && (*c)->hash == hash) {
|
||||
if (!memcmp(key, (*c)->key, len)) {
|
||||
++t->found;
|
||||
break;
|
||||
}
|
||||
++t->same_hash;
|
||||
}
|
||||
++t->collisions;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static struct dm_hash_node **_find(struct dm_hash_table *t, const void *key,
|
||||
uint32_t len)
|
||||
{
|
||||
return _findh(t, key, len, _hash(key, len));
|
||||
}
|
||||
|
||||
void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key,
|
||||
uint32_t len)
|
||||
{
|
||||
@@ -163,7 +245,8 @@ void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key,
|
||||
int dm_hash_insert_binary(struct dm_hash_table *t, const void *key,
|
||||
uint32_t len, void *data)
|
||||
{
|
||||
struct dm_hash_node **c = _find(t, key, len);
|
||||
unsigned hash = _hash(key, len);
|
||||
struct dm_hash_node **c = _findh(t, key, len, hash);
|
||||
|
||||
if (*c)
|
||||
(*c)->data = data;
|
||||
@@ -174,6 +257,7 @@ int dm_hash_insert_binary(struct dm_hash_table *t, const void *key,
|
||||
return 0;
|
||||
|
||||
n->data = data;
|
||||
n->hash = hash;
|
||||
n->next = 0;
|
||||
*c = n;
|
||||
t->num_nodes++;
|
||||
@@ -217,7 +301,7 @@ static struct dm_hash_node **_find_str_with_val(struct dm_hash_table *t,
|
||||
struct dm_hash_node **c;
|
||||
unsigned h;
|
||||
|
||||
h = _hash(key, len) & (t->num_slots - 1);
|
||||
h = _hash(key, len) & t->mask_slots;
|
||||
|
||||
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
|
||||
if ((*c)->keylen != len)
|
||||
@@ -248,7 +332,7 @@ int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
|
||||
n->data = (void *)val;
|
||||
n->data_len = val_len;
|
||||
|
||||
h = _hash(key, len) & (t->num_slots - 1);
|
||||
h = _hash(key, len) & t->mask_slots;
|
||||
|
||||
first = t->slots[h];
|
||||
|
||||
@@ -316,7 +400,7 @@ void *dm_hash_lookup_with_count(struct dm_hash_table *t, const char *key, int *c
|
||||
|
||||
*count = 0;
|
||||
|
||||
h = _hash(key, len) & (t->num_slots - 1);
|
||||
h = _hash(key, len) & t->mask_slots;
|
||||
|
||||
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
|
||||
if ((*c)->keylen != len)
|
||||
@@ -345,7 +429,7 @@ void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
|
||||
struct dm_hash_node *c, *n;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < t->num_slots; i++)
|
||||
for (i = 0; i <= t->mask_slots; i++)
|
||||
for (c = t->slots[i]; c; c = n) {
|
||||
n = c->next;
|
||||
f(c->data);
|
||||
@@ -355,8 +439,8 @@ void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
|
||||
void dm_hash_wipe(struct dm_hash_table *t)
|
||||
{
|
||||
_free_nodes(t);
|
||||
memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots);
|
||||
t->num_nodes = 0u;
|
||||
memset(t->slots, 0, sizeof(struct dm_hash_node *) * (t->mask_slots + 1));
|
||||
t->num_nodes = t->collisions = t->search = t->same_hash = 0u;
|
||||
}
|
||||
|
||||
char *dm_hash_get_key(struct dm_hash_table *t __attribute__((unused)),
|
||||
@@ -376,7 +460,7 @@ static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s)
|
||||
struct dm_hash_node *c = NULL;
|
||||
unsigned i;
|
||||
|
||||
for (i = s; i < t->num_slots && !c; i++)
|
||||
for (i = s; i <= t->mask_slots && !c; i++)
|
||||
c = t->slots[i];
|
||||
|
||||
return c;
|
||||
@@ -389,7 +473,5 @@ struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)
|
||||
|
||||
struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n)
|
||||
{
|
||||
unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
|
||||
|
||||
return n->next ? n->next : _next_slot(t, h + 1);
|
||||
return n->next ? n->next : _next_slot(t, (n->hash & t->mask_slots) + 1);
|
||||
}
|
||||
|
||||
@@ -78,14 +78,14 @@ devices {
|
||||
# routines to acquire this information. For example, this information
|
||||
# is used to drive LVM filtering like MD component detection, multipath
|
||||
# component detection, partition detection and others.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# none
|
||||
# No external device information source is used.
|
||||
# udev
|
||||
# Reuse existing udev database records. Applicable only if LVM is
|
||||
# compiled with udev support.
|
||||
#
|
||||
#
|
||||
external_device_info_source = "none"
|
||||
|
||||
# Configuration option devices/hints.
|
||||
@@ -94,13 +94,13 @@ devices {
|
||||
# scanning, and will only scan the listed PVs. Removing the hint file
|
||||
# will cause lvm to generate a new one. Disable hints if PVs will
|
||||
# be copied onto devices using non-lvm commands, like dd.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# all
|
||||
# Use all hints.
|
||||
# none
|
||||
# Use no hints.
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# hints = "all"
|
||||
|
||||
@@ -118,12 +118,44 @@ devices {
|
||||
# Prefer the name with the least number of slashes.
|
||||
# Prefer a name that is a symlink.
|
||||
# Prefer the path with least value in lexicographical order.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ]
|
||||
#
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option devices/use_devicesfile.
|
||||
# Enable or disable the use of a devices file.
|
||||
# When enabled, lvm will only use devices that
|
||||
# are lised in the devices file. A devices file will
|
||||
# be used, regardless of this setting, when the --devicesfile
|
||||
# option is set to a specific file name.
|
||||
# This configuration option has an automatic default value.
|
||||
# use_devicesfile = 0
|
||||
|
||||
# Configuration option devices/devicesfile.
|
||||
# The name of the system devices file, listing devices that LVM should use.
|
||||
# This should not be used to select a non-system devices file.
|
||||
# The --devicesfile option is intended for alternative devices files.
|
||||
# This configuration option has an automatic default value.
|
||||
# devicesfile = "system.devices"
|
||||
|
||||
# Configuration option devices/search_for_devnames.
|
||||
# Look outside of the devices file for missing devname entries.
|
||||
# A devname entry is used for a device that does not have a stable
|
||||
# device id, e.g. wwid, so the unstable device name is used as
|
||||
# the device id. After reboot, or if the device is reattached,
|
||||
# the device name may change, in which case lvm will not find
|
||||
# the expected PV on the device listed in the devices file.
|
||||
# This setting controls whether lvm will search other devices,
|
||||
# outside the devices file, to look for the missing PV on a
|
||||
# renamed device. If "none", lvm will not look at other devices,
|
||||
# and the PV may appear to be missing. If "auto", lvm will look
|
||||
# at other devices, but only those that are likely to have the PV.
|
||||
# If "all", lvm will look at all devices on the system.
|
||||
# This configuration option has an automatic default value.
|
||||
# search_for_devnames = "auto"
|
||||
|
||||
# Configuration option devices/filter.
|
||||
# Limit the block devices that are used by LVM commands.
|
||||
# This is a list of regular expressions used to accept or reject block
|
||||
@@ -139,7 +171,7 @@ devices {
|
||||
# then the device is accepted. Be careful mixing 'a' and 'r' patterns,
|
||||
# as the combination might produce unexpected results (test changes.)
|
||||
# Run vgscan after changing the filter to regenerate the cache.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Accept every block device:
|
||||
# filter = [ "a|.*|" ]
|
||||
@@ -151,7 +183,7 @@ devices {
|
||||
# filter = [ "a|loop|", "r|/dev/hdc|", "a|/dev/ide|", "r|.*|" ]
|
||||
# Use anchors to be very specific:
|
||||
# filter = [ "a|^/dev/hda8$|", "r|.*|" ]
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# filter = [ "a|.*|" ]
|
||||
|
||||
@@ -169,10 +201,10 @@ devices {
|
||||
# List of additional acceptable block device types.
|
||||
# These are of device type names from /proc/devices, followed by the
|
||||
# maximum number of partitions.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# types = [ "fd", 16 ]
|
||||
#
|
||||
#
|
||||
# This configuration option is advanced.
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
@@ -214,7 +246,7 @@ devices {
|
||||
# Configuration option devices/md_component_checks.
|
||||
# The checks LVM should use to detect MD component devices.
|
||||
# MD component devices are block devices used by MD software RAID.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# auto
|
||||
# LVM will skip scanning the end of devices when it has other
|
||||
@@ -225,7 +257,7 @@ devices {
|
||||
# full
|
||||
# LVM will scan the start and end of devices for MD superblocks.
|
||||
# This requires an extra read at the end of devices.
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# md_component_checks = "auto"
|
||||
|
||||
@@ -238,16 +270,16 @@ devices {
|
||||
# Configuration option devices/md_chunk_alignment.
|
||||
# Align the start of a PV data area with md device's stripe-width.
|
||||
# This applies if a PV is placed directly on an md device.
|
||||
# default_data_alignment will be overriden if it is not aligned
|
||||
# default_data_alignment will be overridden if it is not aligned
|
||||
# with the value detected for this setting.
|
||||
# This setting is overriden by data_alignment_detection,
|
||||
# This setting is overridden by data_alignment_detection,
|
||||
# data_alignment, and the --dataalignment option.
|
||||
md_chunk_alignment = 1
|
||||
|
||||
# Configuration option devices/default_data_alignment.
|
||||
# Align the start of a PV data area with this number of MiB.
|
||||
# Set to 1 for 1MiB, 2 for 2MiB, etc. Set to 0 to disable.
|
||||
# This setting is overriden by data_alignment and the --dataalignment
|
||||
# This setting is overridden by data_alignment and the --dataalignment
|
||||
# option.
|
||||
# This configuration option has an automatic default value.
|
||||
# default_data_alignment = 1
|
||||
@@ -261,9 +293,9 @@ devices {
|
||||
# preferred unit of receiving I/O, e.g. MD stripe width.
|
||||
# minimum_io_size is used if optimal_io_size is undefined (0).
|
||||
# If md_chunk_alignment is enabled, that detects the optimal_io_size.
|
||||
# default_data_alignment and md_chunk_alignment will be overriden
|
||||
# default_data_alignment and md_chunk_alignment will be overridden
|
||||
# if they are not aligned with the value detected for this setting.
|
||||
# This setting is overriden by data_alignment and the --dataalignment
|
||||
# This setting is overridden by data_alignment and the --dataalignment
|
||||
# option.
|
||||
data_alignment_detection = 1
|
||||
|
||||
@@ -272,7 +304,7 @@ devices {
|
||||
# When non-zero, this setting overrides default_data_alignment.
|
||||
# Set to 0 to disable, in which case default_data_alignment
|
||||
# is used to align the first PE in units of MiB.
|
||||
# This setting is overriden by the --dataalignment option.
|
||||
# This setting is overridden by the --dataalignment option.
|
||||
data_alignment = 0
|
||||
|
||||
# Configuration option devices/data_alignment_offset_detection.
|
||||
@@ -283,7 +315,7 @@ devices {
|
||||
# partitioning will have an alignment_offset of 3584 bytes (sector 7
|
||||
# is the lowest aligned logical block, the 4KiB sectors start at
|
||||
# LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).
|
||||
# This setting is overriden by the --dataalignmentoffset option.
|
||||
# This setting is overridden by the --dataalignmentoffset option.
|
||||
data_alignment_offset_detection = 1
|
||||
|
||||
# Configuration option devices/ignore_suspended_devices.
|
||||
@@ -367,7 +399,7 @@ allocation {
|
||||
# defined here, it will check whether any of them are attached to the
|
||||
# PVs concerned and then seek to match those PV tags between existing
|
||||
# extents and new extents.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Use the special tag "@*" as a wildcard to match any PV tag:
|
||||
# cling_tag_list = [ "@*" ]
|
||||
@@ -375,7 +407,7 @@ allocation {
|
||||
# PVs are tagged with either @site1 or @site2 to indicate where
|
||||
# they are situated:
|
||||
# cling_tag_list = [ "@site1", "@site2" ]
|
||||
#
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option allocation/maximise_cling.
|
||||
@@ -434,25 +466,25 @@ allocation {
|
||||
|
||||
# Configuration option allocation/cache_metadata_format.
|
||||
# Sets default metadata format for new cache.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# 0 Automatically detected best available format
|
||||
# 1 Original format
|
||||
# 2 Improved 2nd. generation format
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_metadata_format = 0
|
||||
|
||||
# Configuration option allocation/cache_mode.
|
||||
# The default cache mode used for new cache.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# writethrough
|
||||
# Data blocks are immediately written from the cache to disk.
|
||||
# writeback
|
||||
# Data blocks are written from the cache back to disk after some
|
||||
# delay to improve performance.
|
||||
#
|
||||
#
|
||||
# This setting replaces allocation/cache_pool_cachemode.
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_mode = "writethrough"
|
||||
@@ -493,6 +525,13 @@ allocation {
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_pool_metadata_require_separate_pvs = 0
|
||||
|
||||
# Configuration option allocation/thin_pool_crop_metadata.
|
||||
# Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
|
||||
# This is slightly less then the actual maximum 15.88 GiB.
|
||||
# For compatibility with older version and use of cropped size set to 1.
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_pool_crop_metadata = 0
|
||||
|
||||
# Configuration option allocation/thin_pool_zero.
|
||||
# Thin pool data chunks are zeroed before they are first used.
|
||||
# Zeroing with a larger thin pool chunk size reduces performance.
|
||||
@@ -501,18 +540,18 @@ allocation {
|
||||
|
||||
# Configuration option allocation/thin_pool_discards.
|
||||
# The discards behaviour of thin pool volumes.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# ignore
|
||||
# nopassdown
|
||||
# passdown
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_pool_discards = "passdown"
|
||||
|
||||
# Configuration option allocation/thin_pool_chunk_size_policy.
|
||||
# The chunk size calculation policy for thin pool volumes.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# generic
|
||||
# If thin_pool_chunk_size is defined, use it. Otherwise, calculate
|
||||
@@ -524,7 +563,7 @@ allocation {
|
||||
# the chunk size for performance based on device hints exposed in
|
||||
# sysfs - the optimal_io_size. The chunk size is always at least
|
||||
# 512KiB.
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_pool_chunk_size_policy = "generic"
|
||||
|
||||
@@ -937,8 +976,7 @@ global {
|
||||
# a volume group's metadata, instead of always granting the read-only
|
||||
# requests immediately, delay them to allow the read-write requests to
|
||||
# be serviced. Without this setting, write access may be stalled by a
|
||||
# high volume of read-only requests. This option only affects
|
||||
# locking_type 1 viz. local file-based locking.
|
||||
# high volume of read-only requests. This option only affects file locks.
|
||||
prioritise_write_locks = 1
|
||||
|
||||
# Configuration option global/library_dir.
|
||||
@@ -962,7 +1000,7 @@ global {
|
||||
# Configuration option global/mirror_segtype_default.
|
||||
# The segment type used by the short mirroring option -m.
|
||||
# The --type mirror|raid1 option overrides this setting.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# mirror
|
||||
# The original RAID1 implementation from LVM/DM. It is
|
||||
@@ -982,16 +1020,16 @@ global {
|
||||
# handling a failure. This mirror implementation is not
|
||||
# cluster-aware and cannot be used in a shared (active/active)
|
||||
# fashion in a cluster.
|
||||
#
|
||||
#
|
||||
mirror_segtype_default = "@DEFAULT_MIRROR_SEGTYPE@"
|
||||
|
||||
# Configuration option global/support_mirrored_mirror_log.
|
||||
# Enable mirrored 'mirror' log type for testing.
|
||||
#
|
||||
#
|
||||
# This type is deprecated to create or convert to but can
|
||||
# be enabled to test that activation of existing mirrored
|
||||
# logs and conversion to disk/core works.
|
||||
#
|
||||
#
|
||||
# Not supported for regular operation!
|
||||
# This configuration option has an automatic default value.
|
||||
# support_mirrored_mirror_log = 0
|
||||
@@ -1002,7 +1040,7 @@ global {
|
||||
# The --stripes/-i and --mirrors/-m options can both be specified
|
||||
# during the creation of a logical volume to use both striping and
|
||||
# mirroring for the LV. There are two different implementations.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# raid10
|
||||
# LVM uses MD's RAID10 personality through DM. This is the
|
||||
@@ -1012,7 +1050,7 @@ global {
|
||||
# is done by creating a mirror LV on top of striped sub-LVs,
|
||||
# effectively creating a RAID 0+1 array. The layering is suboptimal
|
||||
# in terms of providing redundancy and performance.
|
||||
#
|
||||
#
|
||||
raid10_segtype_default = "@DEFAULT_RAID10_SEGTYPE@"
|
||||
|
||||
# Configuration option global/sparse_segtype_default.
|
||||
@@ -1020,7 +1058,7 @@ global {
|
||||
# The --type snapshot|thin option overrides this setting.
|
||||
# The combination of -V and -L options creates a sparse LV. There are
|
||||
# two different implementations.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# snapshot
|
||||
# The original snapshot implementation from LVM/DM. It uses an old
|
||||
@@ -1032,7 +1070,7 @@ global {
|
||||
# bigger minimal chunk size (64KiB) and uses a separate volume for
|
||||
# metadata. It has better performance, especially when more data
|
||||
# is used. It also supports full snapshots.
|
||||
#
|
||||
#
|
||||
sparse_segtype_default = "@DEFAULT_SPARSE_SEGTYPE@"
|
||||
|
||||
# Configuration option global/lvdisplay_shows_full_device_path.
|
||||
@@ -1046,12 +1084,15 @@ global {
|
||||
|
||||
# Configuration option global/event_activation.
|
||||
# Activate LVs based on system-generated device events.
|
||||
# When a device appears on the system, a system-generated event runs
|
||||
# the pvscan command to activate LVs if the new PV completes the VG.
|
||||
# Use auto_activation_volume_list to select which LVs should be
|
||||
# activated from these events (the default is all.)
|
||||
# When event_activation is disabled, the system will generally run
|
||||
# a direct activation command to activate LVs in complete VGs.
|
||||
# When a PV appears on the system, a system-generated uevent triggers
|
||||
# the lvm2-pvscan service which runs the pvscan --cache -aay command.
|
||||
# If the new PV completes a VG, pvscan autoactivates LVs in the VG.
|
||||
# When event_activation is disabled, the lvm2-activation services are
|
||||
# generated and run at fixed points during system startup. These
|
||||
# services run vgchange -aay to autoactivate LVs in VGs that happen
|
||||
# to be present at that point in time.
|
||||
# See the --setautoactivation option or the auto_activation_volume_list
|
||||
# setting to configure autoactivation for specific VGs or LVs.
|
||||
# This configuration option has an automatic default value.
|
||||
# event_activation = 1
|
||||
|
||||
@@ -1084,6 +1125,17 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# sanlock_lv_extend = 256
|
||||
|
||||
# Configuration option global/lvmlockctl_kill_command.
|
||||
# The command that lvmlockctl --kill should use to force LVs offline.
|
||||
# The lvmlockctl --kill command is run when a shared VG has lost
|
||||
# access to locks (e.g. when sanlock has lost access to storage.)
|
||||
# An empty string means that there will be no automatic attempt by
|
||||
# lvmlockctl --kill to forcibly shut down LVs in the VG, and the user
|
||||
# can manually intervene as described in lvmlockd(8).
|
||||
# The VG name will be appended to the command specified here.
|
||||
# This configuration option has an automatic default value.
|
||||
# lvmlockctl_kill_command = ""
|
||||
|
||||
# Configuration option global/thin_check_executable.
|
||||
# The full path to the thin_check command.
|
||||
# LVM uses this command to check that a thin metadata device is in a
|
||||
@@ -1130,20 +1182,20 @@ global {
|
||||
# causing problems. Features include: block_size, discards,
|
||||
# discards_non_power_2, external_origin, metadata_resize,
|
||||
# external_origin_extend, error_if_no_space.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# thin_disabled_features = [ "discards", "block_size" ]
|
||||
#
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option global/cache_disabled_features.
|
||||
# Features to not use in the cache driver.
|
||||
# This can be helpful for testing, or to avoid using a feature that is
|
||||
# causing problems. Features include: policy_mq, policy_smq, metadata2.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# cache_disabled_features = [ "policy_smq" ]
|
||||
#
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option global/cache_check_executable.
|
||||
@@ -1195,6 +1247,16 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# vdo_format_options = [ "" ]
|
||||
|
||||
# Configuration option global/vdo_disabled_features.
|
||||
# Features to not use in the vdo driver.
|
||||
# This can be helpful for testing, or to avoid using a feature that is
|
||||
# causing problems. Features include: online_rename
|
||||
#
|
||||
# Example
|
||||
# vdo_disabled_features = [ "online_rename" ]
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option global/fsadm_executable.
|
||||
# The full path to the fsadm command.
|
||||
# LVM uses this command to help with lvresize -r operations.
|
||||
@@ -1207,7 +1269,7 @@ global {
|
||||
# or vgimport.) A VG on shared storage devices is accessible only to
|
||||
# the host with a matching system ID. See 'man lvmsystemid' for
|
||||
# information on limitations and correct usage.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# none
|
||||
# The host has no system ID.
|
||||
@@ -1224,7 +1286,7 @@ global {
|
||||
# file
|
||||
# Use the contents of another file (system_id_file) to set the
|
||||
# system ID.
|
||||
#
|
||||
#
|
||||
system_id_source = "none"
|
||||
|
||||
# Configuration option global/system_id_file.
|
||||
@@ -1276,7 +1338,7 @@ activation {
|
||||
|
||||
# Configuration option activation/udev_sync.
|
||||
# Use udev notifications to synchronize udev and LVM.
|
||||
# The --nodevsync option overrides this setting.
|
||||
# The --noudevsync option overrides this setting.
|
||||
# When disabled, LVM commands will not wait for notifications from
|
||||
# udev, but continue irrespective of any possible udev processing in
|
||||
# the background. Only use this if udev is not running or has rules
|
||||
@@ -1350,7 +1412,7 @@ activation {
|
||||
# If this list is defined, an LV is only activated if it matches an
|
||||
# entry in this list. If this list is undefined, it imposes no limits
|
||||
# on LV activation (all are allowed).
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# vgname
|
||||
# The VG name is matched exactly and selects all LVs in the VG.
|
||||
@@ -1364,30 +1426,30 @@ activation {
|
||||
# or VG. See tags/hosttags. If any host tags exist but volume_list
|
||||
# is not defined, a default single-entry list containing '@*'
|
||||
# is assumed.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
#
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option activation/auto_activation_volume_list.
|
||||
# Only LVs selected by this list are auto-activated.
|
||||
# This list works like volume_list, but it is used only by
|
||||
# auto-activation commands. It does not apply to direct activation
|
||||
# commands. If this list is defined, an LV is only auto-activated
|
||||
# if it matches an entry in this list. If this list is undefined, it
|
||||
# imposes no limits on LV auto-activation (all are allowed.) If this
|
||||
# list is defined and empty, i.e. "[]", then no LVs are selected for
|
||||
# auto-activation. An LV that is selected by this list for
|
||||
# auto-activation, must also be selected by volume_list (if defined)
|
||||
# before it is activated. Auto-activation is an activation command that
|
||||
# includes the 'a' argument: --activate ay or -a ay. The 'a' (auto)
|
||||
# argument for auto-activation is meant to be used by activation
|
||||
# commands that are run automatically by the system, as opposed to LVM
|
||||
# commands run directly by a user. A user may also use the 'a' flag
|
||||
# directly to perform auto-activation. Also see pvscan(8) for more
|
||||
# information about auto-activation.
|
||||
#
|
||||
# A list of VGs or LVs that should be autoactivated.
|
||||
# Autoactivation is an activation command run with -aay,
|
||||
# i.e. vgchange -aay, lvchange -aay, or pvscan --cache -aay.
|
||||
# When this list is defined, an autoactivation command will only
|
||||
# activate LVs included in the list. If this list is undefined,
|
||||
# it has no effect. If this list is defined but empty, then no
|
||||
# LVs will be autoactivated. LVs can be included in the list by
|
||||
# LV name, VG name (applies to all LVs in the VG), or tag name.
|
||||
# VGs and LVs can also have an autoactivation property set in
|
||||
# metadata, see --setautoactivation. LVs included in this list
|
||||
# will not be autoactivated if the VG or LV autoactivation
|
||||
# property is disabled (see vgs or lvs "-o autoactivation").
|
||||
# The volume_list setting and the "activation skip" property
|
||||
# also apply to autoactivation.
|
||||
# The -aay option is meant to be used by activation commands that
|
||||
# are run automatically by the system, e.g. from systemd services.
|
||||
#
|
||||
# Accepted values:
|
||||
# vgname
|
||||
# The VG name is matched exactly and selects all LVs in the VG.
|
||||
@@ -1401,10 +1463,10 @@ activation {
|
||||
# or VG. See tags/hosttags. If any host tags exist but volume_list
|
||||
# is not defined, a default single-entry list containing '@*'
|
||||
# is assumed.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# auto_activation_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
#
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option activation/read_only_volume_list.
|
||||
@@ -1413,7 +1475,7 @@ activation {
|
||||
# against this list, and if it matches, it is activated in read-only
|
||||
# mode. This overrides the permission setting stored in the metadata,
|
||||
# e.g. from --permission rw.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# vgname
|
||||
# The VG name is matched exactly and selects all LVs in the VG.
|
||||
@@ -1427,10 +1489,10 @@ activation {
|
||||
# or VG. See tags/hosttags. If any host tags exist but volume_list
|
||||
# is not defined, a default single-entry list containing '@*'
|
||||
# is assumed.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# read_only_volume_list = [ "vg1", "vg2/lvol1", "@tag1", "@*" ]
|
||||
#
|
||||
#
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option activation/raid_region_size.
|
||||
@@ -1453,13 +1515,13 @@ activation {
|
||||
|
||||
# Configuration option activation/readahead.
|
||||
# Setting to use when there is no readahead setting in metadata.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# none
|
||||
# Disable readahead.
|
||||
# auto
|
||||
# Use default value chosen by kernel.
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# readahead = "auto"
|
||||
|
||||
@@ -1471,7 +1533,7 @@ activation {
|
||||
# performed by dmeventd automatically, and the steps perfomed by the
|
||||
# manual command lvconvert --repair --use-policies.
|
||||
# Automatic handling requires dmeventd to be monitoring the LV.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# warn
|
||||
# Use the system log to warn the user that a device in the RAID LV
|
||||
@@ -1482,7 +1544,7 @@ activation {
|
||||
# allocate
|
||||
# Attempt to use any extra physical volumes in the VG as spares and
|
||||
# replace faulty devices.
|
||||
#
|
||||
#
|
||||
raid_fault_policy = "warn"
|
||||
|
||||
# Configuration option activation/mirror_image_fault_policy.
|
||||
@@ -1494,7 +1556,7 @@ activation {
|
||||
# determines the steps perfomed by dmeventd automatically, and the steps
|
||||
# performed by the manual command lvconvert --repair --use-policies.
|
||||
# Automatic handling requires dmeventd to be monitoring the LV.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# remove
|
||||
# Simply remove the faulty device and run without it. If the log
|
||||
@@ -1519,7 +1581,7 @@ activation {
|
||||
# the redundant nature of the mirror. This policy acts like
|
||||
# 'remove' if no suitable device and space can be allocated for the
|
||||
# replacement.
|
||||
#
|
||||
#
|
||||
mirror_image_fault_policy = "remove"
|
||||
|
||||
# Configuration option activation/mirror_log_fault_policy.
|
||||
@@ -1534,26 +1596,26 @@ activation {
|
||||
# The minimum value is 50 (a smaller value is treated as 50.)
|
||||
# Also see snapshot_autoextend_percent.
|
||||
# Automatic extension requires dmeventd to be monitoring the LV.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
|
||||
# snapshot exceeds 700M, it is extended to 1.2G, and when it exceeds
|
||||
# 840M, it is extended to 1.44G:
|
||||
# snapshot_autoextend_threshold = 70
|
||||
#
|
||||
#
|
||||
snapshot_autoextend_threshold = 100
|
||||
|
||||
# Configuration option activation/snapshot_autoextend_percent.
|
||||
# Auto-extending a snapshot adds this percent extra space.
|
||||
# The amount of additional space added to a snapshot is this
|
||||
# percent of its current size.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
|
||||
# snapshot exceeds 700M, it is extended to 1.2G, and when it exceeds
|
||||
# 840M, it is extended to 1.44G:
|
||||
# snapshot_autoextend_percent = 20
|
||||
#
|
||||
#
|
||||
snapshot_autoextend_percent = 20
|
||||
|
||||
# Configuration option activation/thin_pool_autoextend_threshold.
|
||||
@@ -1562,26 +1624,26 @@ activation {
|
||||
# The minimum value is 50 (a smaller value is treated as 50.)
|
||||
# Also see thin_pool_autoextend_percent.
|
||||
# Automatic extension requires dmeventd to be monitoring the LV.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
|
||||
# thin pool exceeds 700M, it is extended to 1.2G, and when it exceeds
|
||||
# 840M, it is extended to 1.44G:
|
||||
# thin_pool_autoextend_threshold = 70
|
||||
#
|
||||
#
|
||||
thin_pool_autoextend_threshold = 100
|
||||
|
||||
# Configuration option activation/thin_pool_autoextend_percent.
|
||||
# Auto-extending a thin pool adds this percent extra space.
|
||||
# The amount of additional space added to a thin pool is this
|
||||
# percent of its current size.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Using 70% autoextend threshold and 20% autoextend size, when a 1G
|
||||
# thin pool exceeds 700M, it is extended to 1.2G, and when it exceeds
|
||||
# 840M, it is extended to 1.44G:
|
||||
# thin_pool_autoextend_percent = 20
|
||||
#
|
||||
#
|
||||
thin_pool_autoextend_percent = 20
|
||||
|
||||
# Configuration option activation/vdo_pool_autoextend_threshold.
|
||||
@@ -1590,13 +1652,13 @@ activation {
|
||||
# The minimum value is 50 (a smaller value is treated as 50.)
|
||||
# Also see vdo_pool_autoextend_percent.
|
||||
# Automatic extension requires dmeventd to be monitoring the LV.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Using 70% autoextend threshold and 20% autoextend size, when a 10G
|
||||
# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds
|
||||
# 8.4G, it is extended to 14.4G:
|
||||
# vdo_pool_autoextend_threshold = 70
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# vdo_pool_autoextend_threshold = 100
|
||||
|
||||
@@ -1604,7 +1666,7 @@ activation {
|
||||
# Auto-extending a VDO pool adds this percent extra space.
|
||||
# The amount of additional space added to a VDO pool is this
|
||||
# percent of its current size.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Using 70% autoextend threshold and 20% autoextend size, when a 10G
|
||||
# VDO pool exceeds 7G, it is extended to 12G, and when it exceeds
|
||||
@@ -1623,10 +1685,10 @@ activation {
|
||||
# pages corresponding to lines that match are not pinned. On some
|
||||
# systems, locale-archive was found to make up over 80% of the memory
|
||||
# used by the process.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# mlock_filter = [ "locale/locale-archive", "gconv/gconv-modules.cache" ]
|
||||
#
|
||||
#
|
||||
# This configuration option is advanced.
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
@@ -1667,7 +1729,7 @@ activation {
|
||||
# Configuration option activation/activation_mode.
|
||||
# How LVs with missing devices are activated.
|
||||
# The --activationmode option overrides this setting.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# complete
|
||||
# Only allow activation of an LV if all of the Physical Volumes it
|
||||
@@ -1682,7 +1744,7 @@ activation {
|
||||
# could cause data loss with a portion of the LV inaccessible.
|
||||
# This setting should not normally be used, but may sometimes
|
||||
# assist with data recovery.
|
||||
#
|
||||
#
|
||||
activation_mode = "degraded"
|
||||
|
||||
# Configuration option activation/lock_start_list.
|
||||
@@ -1730,7 +1792,7 @@ activation {
|
||||
# Configuration option metadata/pvmetadatacopies.
|
||||
# Number of copies of metadata to store on each PV.
|
||||
# The --pvmetadatacopies option overrides this setting.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# 2
|
||||
# Two copies of the VG metadata are stored on the PV, one at the
|
||||
@@ -1740,7 +1802,7 @@ activation {
|
||||
# 0
|
||||
# No copies of VG metadata are stored on the PV. This may be
|
||||
# useful for VGs containing large numbers of PVs.
|
||||
#
|
||||
#
|
||||
# This configuration option is advanced.
|
||||
# This configuration option has an automatic default value.
|
||||
# pvmetadatacopies = 1
|
||||
@@ -1890,7 +1952,7 @@ activation {
|
||||
# sequences are copied verbatim. Each special character sequence is
|
||||
# introduced by the '%' character and such sequence is then
|
||||
# substituted with a value as described below.
|
||||
#
|
||||
#
|
||||
# Accepted values:
|
||||
# %a
|
||||
# The abbreviated name of the day of the week according to the
|
||||
@@ -2013,7 +2075,7 @@ activation {
|
||||
# The timezone name or abbreviation.
|
||||
# %%
|
||||
# A literal '%' character.
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# time_format = "%Y-%m-%d %T %z"
|
||||
|
||||
@@ -2282,12 +2344,12 @@ dmeventd {
|
||||
# applied to the local machine as a 'host tag'. If this subsection is
|
||||
# empty (has no host_list), then the subsection name is always applied
|
||||
# as a 'host tag'.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# The host tag foo is given to all hosts, and the host tag
|
||||
# bar is given to the hosts named machine1 and machine2.
|
||||
# tags { foo { } bar { host_list = [ "machine1", "machine2" ] } }
|
||||
#
|
||||
#
|
||||
# This configuration section has variable name.
|
||||
# This configuration section has an automatic default value.
|
||||
# tag {
|
||||
|
||||
@@ -28,13 +28,13 @@ local {
|
||||
# main configuration file, e.g. lvm.conf. When used, it must be set to
|
||||
# a unique value among all hosts sharing access to the storage,
|
||||
# e.g. a host name.
|
||||
#
|
||||
#
|
||||
# Example
|
||||
# Set no system ID:
|
||||
# system_id = ""
|
||||
# Set the system_id to a specific name:
|
||||
# system_id = "host1"
|
||||
#
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# system_id = ""
|
||||
|
||||
|
||||
306
configure
vendored
306
configure
vendored
@@ -640,6 +640,7 @@ LVMLOCKD_PIDFILE
|
||||
LVMPOLLD_PIDFILE
|
||||
DMEVENTD_PIDFILE
|
||||
WRITE_INSTALL
|
||||
WRITECACHE
|
||||
VDO_LIB
|
||||
VDO_INCLUDE
|
||||
VDO
|
||||
@@ -702,6 +703,7 @@ LIB_SUFFIX
|
||||
LDDEPS
|
||||
JOBS
|
||||
INTL
|
||||
INTEGRITY
|
||||
HAVE_VALGRIND
|
||||
HAVE_REALTIME
|
||||
HAVE_LIBDL
|
||||
@@ -745,6 +747,7 @@ BUILD_DMFILEMAPD
|
||||
BUILD_LOCKDDLM_CONTROL
|
||||
BUILD_LOCKDDLM
|
||||
BUILD_LOCKDSANLOCK
|
||||
BUILD_LOCKDIDM
|
||||
BUILD_LVMLOCKD
|
||||
BUILD_LVMPOLLD
|
||||
BUILD_LVMDBUSD
|
||||
@@ -780,6 +783,8 @@ LOCKD_DLM_LIBS
|
||||
LOCKD_DLM_CFLAGS
|
||||
LOCKD_SANLOCK_LIBS
|
||||
LOCKD_SANLOCK_CFLAGS
|
||||
LOCKD_IDM_LIBS
|
||||
LOCKD_IDM_CFLAGS
|
||||
VALGRIND_LIBS
|
||||
VALGRIND_CFLAGS
|
||||
GENPNG
|
||||
@@ -795,6 +800,8 @@ PKGCONFIGINIT_CFLAGS
|
||||
PKG_CONFIG_LIBDIR
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG
|
||||
AIO_LIBS
|
||||
AIO_CFLAGS
|
||||
VDO_FORMAT_CMD
|
||||
CACHE_RESTORE_CMD
|
||||
CACHE_REPAIR_CMD
|
||||
@@ -868,6 +875,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -933,6 +941,7 @@ enable_cmirrord
|
||||
with_cmirrord_pidfile
|
||||
enable_debug
|
||||
with_optimisation
|
||||
with_symvers
|
||||
enable_profiling
|
||||
enable_valgrind_pool
|
||||
enable_devmapper
|
||||
@@ -940,6 +949,7 @@ enable_lvmpolld
|
||||
enable_lvmlockd_sanlock
|
||||
enable_lvmlockd_dlm
|
||||
enable_lvmlockd_dlmcontrol
|
||||
enable_lvmlockd_idm
|
||||
enable_use_lvmlockd
|
||||
with_lvmlockd_pidfile
|
||||
enable_use_lvmpolld
|
||||
@@ -996,6 +1006,8 @@ CXX
|
||||
CXXFLAGS
|
||||
CCC
|
||||
CPP
|
||||
AIO_CFLAGS
|
||||
AIO_LIBS
|
||||
PKG_CONFIG
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG_LIBDIR
|
||||
@@ -1011,6 +1023,8 @@ LOCKD_DLM_CFLAGS
|
||||
LOCKD_DLM_LIBS
|
||||
LOCKD_DLM_CONTROL_CFLAGS
|
||||
LOCKD_DLM_CONTROL_LIBS
|
||||
LOCKD_IDM_CFLAGS
|
||||
LOCKD_IDM_LIBS
|
||||
NOTIFY_DBUS_CFLAGS
|
||||
NOTIFY_DBUS_LIBS
|
||||
BLKID_CFLAGS
|
||||
@@ -1060,6 +1074,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE}'
|
||||
@@ -1312,6 +1327,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1449,7 +1473,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1602,6 +1626,7 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -1659,6 +1684,7 @@ Optional Features:
|
||||
--enable-lvmlockd-dlm enable the LVM lock daemon using dlm
|
||||
--enable-lvmlockd-dlmcontrol
|
||||
enable lvmlockd remote refresh using libdlmcontrol
|
||||
--enable-lvmlockd-idm enable the LVM lock daemon using idm
|
||||
--disable-use-lvmlockd disable usage of LVM lock daemon
|
||||
--disable-use-lvmpolld disable usage of LVM Poll Daemon
|
||||
--enable-dmfilemapd enable the dmstats filemap daemon
|
||||
@@ -1700,22 +1726,21 @@ Optional Packages:
|
||||
create nodes on resume or create [ON=resume]
|
||||
--with-default-name-mangling=MANGLING
|
||||
default name mangling: auto/none/hex [auto]
|
||||
--with-snapshots=TYPE snapshot support: internal/shared/none [internal]
|
||||
--with-mirrors=TYPE mirror support: internal/shared/none [internal]
|
||||
--with-snapshots=TYPE snapshot support: internal/none [internal]
|
||||
--with-mirrors=TYPE mirror support: internal/none [internal]
|
||||
--with-default-mirror-segtype=TYPE
|
||||
default mirror segtype: raid1/mirror [raid1]
|
||||
--with-default-raid10-segtype=TYPE
|
||||
default mirror segtype: raid10/mirror [raid10]
|
||||
--with-default-sparse-segtype=TYPE
|
||||
default sparse segtype: thin/snapshot [thin]
|
||||
--with-thin=TYPE thin provisioning support: internal/shared/none
|
||||
[internal]
|
||||
--with-thin=TYPE thin provisioning support: internal/none [internal]
|
||||
--with-thin-check=PATH thin_check tool: [autodetect]
|
||||
--with-thin-dump=PATH thin_dump tool: [autodetect]
|
||||
--with-thin-repair=PATH thin_repair tool: [autodetect]
|
||||
--with-thin-restore=PATH
|
||||
thin_restore tool: [autodetect]
|
||||
--with-cache=TYPE cache support: internal/shared/none [internal]
|
||||
--with-cache=TYPE cache support: internal/none [internal]
|
||||
--with-cache-check=PATH cache_check tool: [autodetect]
|
||||
--with-cache-dump=PATH cache_dump tool: [autodetect]
|
||||
--with-cache-repair=PATH
|
||||
@@ -1737,6 +1762,8 @@ Optional Packages:
|
||||
--with-cmirrord-pidfile=PATH
|
||||
cmirrord pidfile [PID_DIR/cmirrord.pid]
|
||||
--with-optimisation=OPT C optimisation flag [OPT=-O2]
|
||||
--with-symvers=STYLE use symbol versioning of the shared library
|
||||
[default=gnu]
|
||||
--with-lvmlockd-pidfile=PATH
|
||||
lvmlockd pidfile [PID_DIR/lvmlockd.pid]
|
||||
--with-lvmpolld-pidfile=PATH
|
||||
@@ -1783,6 +1810,8 @@ Some influential environment variables:
|
||||
CXX C++ compiler command
|
||||
CXXFLAGS C++ compiler flags
|
||||
CPP C preprocessor
|
||||
AIO_CFLAGS C compiler flags for AIO
|
||||
AIO_LIBS linker flags for AIO
|
||||
PKG_CONFIG path to pkg-config utility
|
||||
PKG_CONFIG_PATH
|
||||
directories to add to pkg-config's search path
|
||||
@@ -1810,6 +1839,10 @@ Some influential environment variables:
|
||||
C compiler flags for LOCKD_DLM_CONTROL, overriding pkg-config
|
||||
LOCKD_DLM_CONTROL_LIBS
|
||||
linker flags for LOCKD_DLM_CONTROL, overriding pkg-config
|
||||
LOCKD_IDM_CFLAGS
|
||||
C compiler flags for LOCKD_IDM, overriding pkg-config
|
||||
LOCKD_IDM_LIBS
|
||||
linker flags for LOCKD_IDM, overriding pkg-config
|
||||
NOTIFY_DBUS_CFLAGS
|
||||
C compiler flags for NOTIFY_DBUS, overriding pkg-config
|
||||
NOTIFY_DBUS_LIBS
|
||||
@@ -3091,19 +3124,18 @@ if test -z "$CFLAGS"; then :
|
||||
fi
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
|
||||
# equivalent to -rdynamic
|
||||
ELDFLAGS="-Wl,--export-dynamic"
|
||||
# FIXME Generate list and use --dynamic-list=.dlopen.sym
|
||||
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
||||
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
BUILD_LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
LOCKDDLM=no
|
||||
LOCKDDLM_CONTROL=no
|
||||
LOCKDIDM=no
|
||||
ODIRECT=yes
|
||||
DM_IOCTLS=yes
|
||||
SELINUX=yes
|
||||
@@ -3112,7 +3144,6 @@ case "$host_os" in
|
||||
;;
|
||||
darwin*)
|
||||
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
||||
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"
|
||||
ELDFLAGS=
|
||||
CLDWHOLEARCHIVE="-all_load"
|
||||
CLDNOWHOLEARCHIVE=
|
||||
@@ -6077,7 +6108,7 @@ fi
|
||||
|
||||
|
||||
for ac_header in assert.h ctype.h dirent.h errno.h fcntl.h float.h \
|
||||
getopt.h inttypes.h langinfo.h libaio.h libgen.h limits.h locale.h paths.h \
|
||||
getopt.h inttypes.h langinfo.h libgen.h limits.h locale.h paths.h \
|
||||
signal.h stdarg.h stddef.h stdio.h stdlib.h string.h sys/file.h \
|
||||
sys/ioctl.h syslog.h sys/mman.h sys/param.h sys/resource.h sys/stat.h \
|
||||
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
|
||||
@@ -6110,6 +6141,19 @@ fi
|
||||
|
||||
done
|
||||
|
||||
for ac_header in libaio.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "libaio.h" "ac_cv_header_libaio_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_libaio_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBAIO_H 1
|
||||
_ACEOF
|
||||
LVM_NEEDS_LIBAIO_WARN=
|
||||
else
|
||||
LVM_NEEDS_LIBAIO_WARN=y
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
@@ -8373,7 +8417,7 @@ fi
|
||||
|
||||
case "$MANGLING" in
|
||||
auto) mangling=DM_STRING_MANGLING_AUTO;;
|
||||
none|disabled) mangling=DM_STRING_MANGLING_NONE;;
|
||||
no|none|disabled) mangling=DM_STRING_MANGLING_NONE;;
|
||||
hex) mangling=DM_STRING_MANGLING_HEX;;
|
||||
*) as_fn_error $? "--with-default-name-mangling parameter invalid" "$LINENO" 5;;
|
||||
esac
|
||||
@@ -8400,7 +8444,7 @@ fi
|
||||
$as_echo "$SNAPSHOTS" >&6; }
|
||||
|
||||
case "$SNAPSHOTS" in
|
||||
none|shared) ;;
|
||||
no|none|shared) ;;
|
||||
internal)
|
||||
$as_echo "#define SNAPSHOT_INTERNAL 1" >>confdefs.h
|
||||
;;
|
||||
@@ -8422,7 +8466,7 @@ fi
|
||||
$as_echo "$MIRRORS" >&6; }
|
||||
|
||||
case "$MIRRORS" in
|
||||
none|shared) ;;
|
||||
no|none|shared) ;;
|
||||
internal)
|
||||
$as_echo "#define MIRRORED_INTERNAL 1" >>confdefs.h
|
||||
;;
|
||||
@@ -8467,7 +8511,10 @@ _ACEOF
|
||||
|
||||
# Check whether --with-default-sparse-segtype was given.
|
||||
if test "${with_default_sparse_segtype+set}" = set; then :
|
||||
withval=$with_default_sparse_segtype; DEFAULT_SPARSE_SEGTYPE=$withval
|
||||
withval=$with_default_sparse_segtype; case "$withval" in
|
||||
thin|snapshot) DEFAULT_SPARSE_SEGTYPE=$withval ;;
|
||||
*) as_fn_error $? "--with-default-sparse-segtype parameter invalid" "$LINENO" 5 ;;
|
||||
esac
|
||||
else
|
||||
DEFAULT_SPARSE_SEGTYPE="thin"
|
||||
fi
|
||||
@@ -8521,7 +8568,7 @@ fi
|
||||
$as_echo "$THIN" >&6; }
|
||||
|
||||
case "$THIN" in
|
||||
none) test "$DEFAULT_SPARSE_SEGTYPE" = "thin" && DEFAULT_SPARSE_SEGTYPE="snapshot" ;;
|
||||
no|none) test "$DEFAULT_SPARSE_SEGTYPE" = "thin" && DEFAULT_SPARSE_SEGTYPE="snapshot" ;;
|
||||
shared) ;;
|
||||
internal)
|
||||
$as_echo "#define THIN_INTERNAL 1" >>confdefs.h
|
||||
@@ -9002,7 +9049,6 @@ $as_echo "$THIN_CHECK_NEEDS_CHECK" >&6; }
|
||||
$as_echo "#define THIN_CHECK_NEEDS_CHECK 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -9077,7 +9123,7 @@ fi
|
||||
$as_echo "$CACHE" >&6; }
|
||||
|
||||
case "$CACHE" in
|
||||
none|shared) ;;
|
||||
no|none|shared) ;;
|
||||
internal)
|
||||
$as_echo "#define CACHE_INTERNAL 1" >>confdefs.h
|
||||
;;
|
||||
@@ -9614,7 +9660,7 @@ else
|
||||
fi
|
||||
|
||||
case "$VDO" in
|
||||
none) ;;
|
||||
no|none) ;;
|
||||
internal)
|
||||
|
||||
$as_echo "#define VDO_INTERNAL 1" >>confdefs.h
|
||||
@@ -9766,7 +9812,7 @@ fi
|
||||
$as_echo "$WRITECACHE" >&6; }
|
||||
|
||||
case "$WRITECACHE" in
|
||||
none) ;;
|
||||
no|none) ;;
|
||||
internal)
|
||||
|
||||
$as_echo "#define WRITECACHE_INTERNAL 1" >>confdefs.h
|
||||
@@ -9791,7 +9837,7 @@ fi
|
||||
$as_echo "$INTEGRITY" >&6; }
|
||||
|
||||
case "$INTEGRITY" in
|
||||
none) ;;
|
||||
no|none) ;;
|
||||
internal)
|
||||
|
||||
$as_echo "#define INTEGRITY_INTERNAL 1" >>confdefs.h
|
||||
@@ -9800,6 +9846,14 @@ $as_echo "#define INTEGRITY_INTERNAL 1" >>confdefs.h
|
||||
*) as_fn_error $? "--with-integrity parameter invalid" "$LINENO" 5 ;;
|
||||
esac
|
||||
|
||||
################################################################################
|
||||
# Allow users to override default location for libaio
|
||||
# there seems to be no pkg-config support available
|
||||
AIO_CFLAGS=
|
||||
AIO_LIBS=${AIO_LIBS:--laio}
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
# Check whether --enable-readline was given.
|
||||
if test "${enable_readline+set}" = set; then :
|
||||
@@ -10381,6 +10435,35 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $COPTIMISE_FLAG" >&5
|
||||
$as_echo "$COPTIMISE_FLAG" >&6; }
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use symbol versioning" >&5
|
||||
$as_echo_n "checking whether to use symbol versioning... " >&6; }
|
||||
|
||||
# Check whether --with-symvers was given.
|
||||
if test "${with_symvers+set}" = set; then :
|
||||
withval=$with_symvers; case "$withval" in
|
||||
gnu|no) symvers=$withval ;;
|
||||
*) as_fn_error $? "--with-symvers parameter invalid" "$LINENO" 5 ;;
|
||||
esac
|
||||
else
|
||||
symvers=gnu
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $symvers" >&5
|
||||
$as_echo "$symvers" >&6; }
|
||||
|
||||
if test "$GCC" = "yes" && test "$symvers" = "gnu" ; then
|
||||
|
||||
$as_echo "#define GNU_SYMVER 1" >>confdefs.h
|
||||
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to gather gcov profiling data" >&5
|
||||
$as_echo_n "checking whether to gather gcov profiling data... " >&6; }
|
||||
@@ -10717,7 +10800,6 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable valgrind awareness of pools" >&5
|
||||
$as_echo_n "checking whether to enable valgrind awareness of pools... " >&6; }
|
||||
@@ -11121,6 +11203,167 @@ $as_echo "#define LOCKDDLM_CONTROL_SUPPORT 1" >>confdefs.h
|
||||
BUILD_LVMLOCKD=yes
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockdidm" >&5
|
||||
$as_echo_n "checking whether to build lvmlockdidm... " >&6; }
|
||||
# Check whether --enable-lvmlockd-idm was given.
|
||||
if test "${enable_lvmlockd_idm+set}" = set; then :
|
||||
enableval=$enable_lvmlockd_idm; LOCKDIDM=$enableval
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LOCKDIDM" >&5
|
||||
$as_echo "$LOCKDIDM" >&6; }
|
||||
|
||||
BUILD_LOCKDIDM=$LOCKDIDM
|
||||
|
||||
if test "$BUILD_LOCKDIDM" = yes; then
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LOCKD_IDM" >&5
|
||||
$as_echo_n "checking for LOCKD_IDM... " >&6; }
|
||||
|
||||
if test -n "$LOCKD_IDM_CFLAGS"; then
|
||||
pkg_cv_LOCKD_IDM_CFLAGS="$LOCKD_IDM_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libseagate_ilm >= 0.1.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libseagate_ilm >= 0.1.0") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LOCKD_IDM_CFLAGS=`$PKG_CONFIG --cflags "libseagate_ilm >= 0.1.0" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$LOCKD_IDM_LIBS"; then
|
||||
pkg_cv_LOCKD_IDM_LIBS="$LOCKD_IDM_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libseagate_ilm >= 0.1.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libseagate_ilm >= 0.1.0") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LOCKD_IDM_LIBS=`$PKG_CONFIG --libs "libseagate_ilm >= 0.1.0" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
LOCKD_IDM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libseagate_ilm >= 0.1.0" 2>&1`
|
||||
else
|
||||
LOCKD_IDM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libseagate_ilm >= 0.1.0" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$LOCKD_IDM_PKG_ERRORS" >&5
|
||||
|
||||
$bailout
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
$bailout
|
||||
else
|
||||
LOCKD_IDM_CFLAGS=$pkg_cv_LOCKD_IDM_CFLAGS
|
||||
LOCKD_IDM_LIBS=$pkg_cv_LOCKD_IDM_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BLKID" >&5
|
||||
$as_echo_n "checking for BLKID... " >&6; }
|
||||
|
||||
if test -n "$BLKID_CFLAGS"; then
|
||||
pkg_cv_BLKID_CFLAGS="$BLKID_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.24\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "blkid >= 2.24") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_BLKID_CFLAGS=`$PKG_CONFIG --cflags "blkid >= 2.24" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$BLKID_LIBS"; then
|
||||
pkg_cv_BLKID_LIBS="$BLKID_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.24\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "blkid >= 2.24") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_BLKID_LIBS=`$PKG_CONFIG --libs "blkid >= 2.24" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "blkid >= 2.24" 2>&1`
|
||||
else
|
||||
BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "blkid >= 2.24" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$BLKID_PKG_ERRORS" >&5
|
||||
|
||||
$bailout
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
$bailout
|
||||
else
|
||||
BLKID_CFLAGS=$pkg_cv_BLKID_CFLAGS
|
||||
BLKID_LIBS=$pkg_cv_BLKID_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
HAVE_LOCKD_IDM=yes
|
||||
fi
|
||||
|
||||
$as_echo "#define LOCKDIDM_SUPPORT 1" >>confdefs.h
|
||||
|
||||
BUILD_LVMLOCKD=yes
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockd" >&5
|
||||
$as_echo_n "checking whether to build lvmlockd... " >&6; }
|
||||
@@ -11962,7 +12205,7 @@ $as_echo_n "checking for $am_display_PYTHON version... " >&6; }
|
||||
if ${am_cv_python_version+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"`
|
||||
am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[:2])"`
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5
|
||||
$as_echo "$am_cv_python_version" >&6; }
|
||||
@@ -12946,12 +13189,12 @@ fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$EDITLINE_PKG_ERRORS" >&5
|
||||
|
||||
as_fn_error $? "libedit could not be found which is required for the --enable-readline option." "$LINENO" 5
|
||||
as_fn_error $? "libedit could not be found which is required for the --enable-editline option." "$LINENO" 5
|
||||
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
as_fn_error $? "libedit could not be found which is required for the --enable-readline option." "$LINENO" 5
|
||||
as_fn_error $? "libedit could not be found which is required for the --enable-editline option." "$LINENO" 5
|
||||
|
||||
else
|
||||
EDITLINE_CFLAGS=$pkg_cv_EDITLINE_CFLAGS
|
||||
@@ -13404,13 +13647,12 @@ $as_echo_n "checking whether to enable readline... " >&6; }
|
||||
$as_echo "$READLINE" >&6; }
|
||||
|
||||
if test "$EDITLINE" = yes; then
|
||||
for ac_header in editline/readline.h editline/history.h
|
||||
for ac_header in editline/readline.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "editline/readline.h" "ac_cv_header_editline_readline_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_editline_readline_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||
#define HAVE_EDITLINE_READLINE_H 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
@@ -14106,6 +14348,8 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15483,6 +15727,10 @@ if test -n "$VDO_CONFIGURE_WARN"; then :
|
||||
$as_echo "$as_me: WARNING: Unrecognized 'vdoformat' tool is REQUIRED for VDO logical volume creation!" >&2;}
|
||||
fi
|
||||
|
||||
if test -n "$LVM_NEEDS_LIBAIO_WARN"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Only libdm part can be build without libaio: make [install_]device-mapper" >&5
|
||||
$as_echo "$as_me: WARNING: Only libdm part can be build without libaio: make [install_]device-mapper" >&2;}
|
||||
fi
|
||||
|
||||
if test "$ODIRECT" != yes; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: O_DIRECT disabled: low-memory pvmove may lock up" >&5
|
||||
|
||||
103
configure.ac
103
configure.ac
@@ -30,19 +30,18 @@ AC_CANONICAL_TARGET([])
|
||||
AS_IF([test -z "$CFLAGS"], [COPTIMISE_FLAG="-O2"])
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
|
||||
# equivalent to -rdynamic
|
||||
ELDFLAGS="-Wl,--export-dynamic"
|
||||
# FIXME Generate list and use --dynamic-list=.dlopen.sym
|
||||
CLDWHOLEARCHIVE="-Wl,-whole-archive"
|
||||
CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
LIB_SUFFIX=so
|
||||
DEVMAPPER=yes
|
||||
BUILD_LVMPOLLD=no
|
||||
LOCKDSANLOCK=no
|
||||
LOCKDDLM=no
|
||||
LOCKDDLM_CONTROL=no
|
||||
LOCKDIDM=no
|
||||
ODIRECT=yes
|
||||
DM_IOCTLS=yes
|
||||
SELINUX=yes
|
||||
@@ -51,7 +50,6 @@ case "$host_os" in
|
||||
;;
|
||||
darwin*)
|
||||
CFLAGS="$CFLAGS -no-cpp-precomp -fno-common"
|
||||
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"}"
|
||||
ELDFLAGS=
|
||||
CLDWHOLEARCHIVE="-all_load"
|
||||
CLDNOWHOLEARCHIVE=
|
||||
@@ -104,14 +102,14 @@ AC_HEADER_SYS_WAIT
|
||||
AC_HEADER_TIME
|
||||
|
||||
AC_CHECK_HEADERS([assert.h ctype.h dirent.h errno.h fcntl.h float.h \
|
||||
getopt.h inttypes.h langinfo.h libaio.h libgen.h limits.h locale.h paths.h \
|
||||
getopt.h inttypes.h langinfo.h libgen.h limits.h locale.h paths.h \
|
||||
signal.h stdarg.h stddef.h stdio.h stdlib.h string.h sys/file.h \
|
||||
sys/ioctl.h syslog.h sys/mman.h sys/param.h sys/resource.h sys/stat.h \
|
||||
sys/time.h sys/types.h sys/utsname.h sys/wait.h time.h \
|
||||
unistd.h], , [AC_MSG_ERROR(bailing out)])
|
||||
|
||||
AC_CHECK_HEADERS(termios.h sys/statvfs.h sys/timerfd.h sys/vfs.h linux/magic.h linux/fiemap.h)
|
||||
|
||||
AC_CHECK_HEADERS(libaio.h,LVM_NEEDS_LIBAIO_WARN=,LVM_NEEDS_LIBAIO_WARN=y)
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
AC_CHECK_HEADERS(asm/byteorder.h linux/fs.h malloc.h,,AC_MSG_ERROR(bailing out)) ;;
|
||||
@@ -292,7 +290,7 @@ AC_ARG_WITH(default-name-mangling,
|
||||
MANGLING=$withval, MANGLING=auto)
|
||||
case "$MANGLING" in
|
||||
auto) mangling=DM_STRING_MANGLING_AUTO;;
|
||||
none|disabled) mangling=DM_STRING_MANGLING_NONE;;
|
||||
no|none|disabled) mangling=DM_STRING_MANGLING_NONE;;
|
||||
hex) mangling=DM_STRING_MANGLING_HEX;;
|
||||
*) AC_MSG_ERROR([--with-default-name-mangling parameter invalid]);;
|
||||
esac
|
||||
@@ -304,12 +302,12 @@ dnl -- snapshots inclusion type
|
||||
AC_MSG_CHECKING(whether to include snapshots)
|
||||
AC_ARG_WITH(snapshots,
|
||||
AC_HELP_STRING([--with-snapshots=TYPE],
|
||||
[snapshot support: internal/shared/none [internal]]),
|
||||
[snapshot support: internal/none [internal]]),
|
||||
SNAPSHOTS=$withval, SNAPSHOTS=internal)
|
||||
AC_MSG_RESULT($SNAPSHOTS)
|
||||
|
||||
case "$SNAPSHOTS" in
|
||||
none|shared) ;;
|
||||
no|none|shared) ;;
|
||||
internal) AC_DEFINE([SNAPSHOT_INTERNAL], 1,
|
||||
[Define to 1 to include built-in support for snapshots.]) ;;
|
||||
*) AC_MSG_ERROR([--with-snapshots parameter invalid]) ;;
|
||||
@@ -320,12 +318,12 @@ dnl -- mirrors inclusion type
|
||||
AC_MSG_CHECKING(whether to include mirrors)
|
||||
AC_ARG_WITH(mirrors,
|
||||
AC_HELP_STRING([--with-mirrors=TYPE],
|
||||
[mirror support: internal/shared/none [internal]]),
|
||||
[mirror support: internal/none [internal]]),
|
||||
MIRRORS=$withval, MIRRORS=internal)
|
||||
AC_MSG_RESULT($MIRRORS)
|
||||
|
||||
case "$MIRRORS" in
|
||||
none|shared) ;;
|
||||
no|none|shared) ;;
|
||||
internal) AC_DEFINE([MIRRORED_INTERNAL], 1,
|
||||
[Define to 1 to include built-in support for mirrors.]) ;;
|
||||
*) AC_MSG_ERROR([--with-mirrors parameter invalid]) ;;
|
||||
@@ -355,14 +353,17 @@ AC_DEFINE_UNQUOTED([DEFAULT_RAID10_SEGTYPE], ["$DEFAULT_RAID10_SEGTYPE"],
|
||||
AC_ARG_WITH(default-sparse-segtype,
|
||||
AC_HELP_STRING([--with-default-sparse-segtype=TYPE],
|
||||
[default sparse segtype: thin/snapshot [thin]]),
|
||||
DEFAULT_SPARSE_SEGTYPE=$withval, DEFAULT_SPARSE_SEGTYPE="thin")
|
||||
[ case "$withval" in
|
||||
thin|snapshot) DEFAULT_SPARSE_SEGTYPE=$withval ;;
|
||||
*) AC_MSG_ERROR(--with-default-sparse-segtype parameter invalid) ;;
|
||||
esac], DEFAULT_SPARSE_SEGTYPE="thin")
|
||||
|
||||
################################################################################
|
||||
dnl -- thin provisioning
|
||||
AC_MSG_CHECKING(whether to include thin provisioning)
|
||||
AC_ARG_WITH(thin,
|
||||
AC_HELP_STRING([--with-thin=TYPE],
|
||||
[thin provisioning support: internal/shared/none [internal]]),
|
||||
[thin provisioning support: internal/none [internal]]),
|
||||
THIN=$withval, THIN=internal)
|
||||
AC_ARG_WITH(thin-check,
|
||||
AC_HELP_STRING([--with-thin-check=PATH],
|
||||
@@ -384,7 +385,7 @@ AC_ARG_WITH(thin-restore,
|
||||
AC_MSG_RESULT($THIN)
|
||||
|
||||
case "$THIN" in
|
||||
none) test "$DEFAULT_SPARSE_SEGTYPE" = "thin" && DEFAULT_SPARSE_SEGTYPE="snapshot" ;;
|
||||
no|none) test "$DEFAULT_SPARSE_SEGTYPE" = "thin" && DEFAULT_SPARSE_SEGTYPE="snapshot" ;;
|
||||
shared) ;;
|
||||
internal) AC_DEFINE([THIN_INTERNAL], 1,
|
||||
[Define to 1 to include built-in support for thin provisioning.]) ;;
|
||||
@@ -461,7 +462,6 @@ case "$THIN" in
|
||||
if test "$THIN_CHECK_NEEDS_CHECK" = yes; then
|
||||
AC_DEFINE([THIN_CHECK_NEEDS_CHECK], 1, [Define to 1 if the external 'thin_check' tool requires the --clear-needs-check-flag option])
|
||||
fi
|
||||
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -482,7 +482,7 @@ dnl -- cache inclusion type
|
||||
AC_MSG_CHECKING(whether to include cache)
|
||||
AC_ARG_WITH(cache,
|
||||
AC_HELP_STRING([--with-cache=TYPE],
|
||||
[cache support: internal/shared/none [internal]]),
|
||||
[cache support: internal/none [internal]]),
|
||||
CACHE=$withval, CACHE="internal")
|
||||
AC_ARG_WITH(cache-check,
|
||||
AC_HELP_STRING([--with-cache-check=PATH],
|
||||
@@ -503,7 +503,7 @@ AC_ARG_WITH(cache-restore,
|
||||
AC_MSG_RESULT($CACHE)
|
||||
|
||||
case "$CACHE" in
|
||||
none|shared) ;;
|
||||
no|none|shared) ;;
|
||||
internal) AC_DEFINE([CACHE_INTERNAL], 1, [Define to 1 to include built-in support for cache.]) ;;
|
||||
*) AC_MSG_ERROR([--with-cache parameter invalid]) ;;
|
||||
esac
|
||||
@@ -616,8 +616,8 @@ AC_ARG_WITH(vdo-format,
|
||||
[vdoformat tool: [autodetect]]),
|
||||
VDO_FORMAT_CMD=$withval, VDO_FORMAT_CMD="autodetect")
|
||||
case "$VDO" in
|
||||
none) ;;
|
||||
internal)
|
||||
no|none) ;;
|
||||
internal)
|
||||
AC_DEFINE([VDO_INTERNAL], 1, [Define to 1 to include built-in support for vdo.])
|
||||
if test "$VDO_FORMAT_CMD" = "autodetect"; then
|
||||
AC_PATH_TOOL(VDO_FORMAT_CMD, vdoformat, [], [$PATH])
|
||||
@@ -646,7 +646,7 @@ AC_DEFINE_UNQUOTED([VDO_FORMAT_CMD], ["$VDO_FORMAT_CMD"],
|
||||
#AC_ARG_WITH(vdo-lib,
|
||||
# AC_HELP_STRING([--with-vdo-lib=PATH],
|
||||
# [vdo support: Path to utils lib: [/usr/lib]]),
|
||||
# VDO_LIB=$withval, VDO_LIB="/usr/lib")
|
||||
# VDO_LIB=$withval, VDO_LIB="/usr/lib")
|
||||
#AC_MSG_RESULT($VDO_LIB)
|
||||
|
||||
################################################################################
|
||||
@@ -660,8 +660,8 @@ AC_ARG_WITH(writecache,
|
||||
AC_MSG_RESULT($WRITECACHE)
|
||||
|
||||
case "$WRITECACHE" in
|
||||
none) ;;
|
||||
internal)
|
||||
no|none) ;;
|
||||
internal)
|
||||
AC_DEFINE([WRITECACHE_INTERNAL], 1, [Define to 1 to include built-in support for writecache.])
|
||||
;;
|
||||
*) AC_MSG_ERROR([--with-writecache parameter invalid]) ;;
|
||||
@@ -678,13 +678,21 @@ AC_ARG_WITH(integrity,
|
||||
AC_MSG_RESULT($INTEGRITY)
|
||||
|
||||
case "$INTEGRITY" in
|
||||
none) ;;
|
||||
no|none) ;;
|
||||
internal)
|
||||
AC_DEFINE([INTEGRITY_INTERNAL], 1, [Define to 1 to include built-in support for integrity.])
|
||||
;;
|
||||
*) AC_MSG_ERROR([--with-integrity parameter invalid]) ;;
|
||||
esac
|
||||
|
||||
################################################################################
|
||||
# Allow users to override default location for libaio
|
||||
# there seems to be no pkg-config support available
|
||||
AIO_CFLAGS=
|
||||
AIO_LIBS=${AIO_LIBS:--laio}
|
||||
AC_ARG_VAR([AIO_CFLAGS], [C compiler flags for AIO])
|
||||
AC_ARG_VAR([AIO_LIBS], [linker flags for AIO])
|
||||
|
||||
################################################################################
|
||||
dnl -- Disable readline
|
||||
AC_ARG_ENABLE([readline],
|
||||
@@ -825,6 +833,29 @@ AC_ARG_WITH(optimisation,
|
||||
COPTIMISE_FLAG=$withval)
|
||||
AC_MSG_RESULT($COPTIMISE_FLAG)
|
||||
|
||||
################################################################################
|
||||
dnl -- Symbol versioning
|
||||
AC_MSG_CHECKING(whether to use symbol versioning)
|
||||
AC_ARG_WITH(symvers,
|
||||
AC_HELP_STRING([--with-symvers=STYLE],
|
||||
[use symbol versioning of the shared library [default=gnu]]),
|
||||
[ case "$withval" in
|
||||
gnu|no) symvers=$withval ;;
|
||||
*) AC_MSG_ERROR(--with-symvers parameter invalid) ;;
|
||||
esac], symvers=gnu)
|
||||
AC_MSG_RESULT($symvers)
|
||||
|
||||
if test "$GCC" = "yes" && test "$symvers" = "gnu" ; then
|
||||
AC_DEFINE(GNU_SYMVER, 1,
|
||||
[Define to use GNU versioning in the shared library.])
|
||||
case "$host_os" in
|
||||
linux*)
|
||||
CLDFLAGS="${CLDFLAGS-"$LDFLAGS"} -Wl,--version-script,.export.sym"
|
||||
LDDEPS="$LDDEPS .export.sym"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable profiling
|
||||
AC_MSG_CHECKING(whether to gather gcov profiling data)
|
||||
@@ -859,7 +890,6 @@ TESTSUITE_DATA='${datarootdir}/lvm2-testsuite'
|
||||
# double eval needed ${datarootdir} -> ${prefix}/share -> real path
|
||||
AC_DEFINE_UNQUOTED(TESTSUITE_DATA, ["$(eval echo $(eval echo $TESTSUITE_DATA))"], [Path to testsuite data])
|
||||
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable valgrind awareness of memory pools
|
||||
AC_MSG_CHECKING(whether to enable valgrind awareness of pools)
|
||||
@@ -960,6 +990,25 @@ if test "$BUILD_LOCKDDLM_CONTROL" = yes; then
|
||||
BUILD_LVMLOCKD=yes
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Build lvmlockdidm
|
||||
AC_MSG_CHECKING(whether to build lvmlockdidm)
|
||||
AC_ARG_ENABLE(lvmlockd-idm,
|
||||
AC_HELP_STRING([--enable-lvmlockd-idm],
|
||||
[enable the LVM lock daemon using idm]),
|
||||
LOCKDIDM=$enableval)
|
||||
AC_MSG_RESULT($LOCKDIDM)
|
||||
|
||||
BUILD_LOCKDIDM=$LOCKDIDM
|
||||
|
||||
dnl -- Look for Seagate IDM libraries
|
||||
if test "$BUILD_LOCKDIDM" = yes; then
|
||||
PKG_CHECK_MODULES(LOCKD_IDM, libseagate_ilm >= 0.1.0, [HAVE_LOCKD_IDM=yes], $bailout)
|
||||
PKG_CHECK_MODULES(BLKID, blkid >= 2.24, [HAVE_LOCKD_IDM=yes], $bailout)
|
||||
AC_DEFINE([LOCKDIDM_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd IDM option.])
|
||||
BUILD_LVMLOCKD=yes
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Build lvmlockd
|
||||
AC_MSG_CHECKING(whether to build lvmlockd)
|
||||
@@ -1420,7 +1469,7 @@ if test "$EDITLINE" == yes; then
|
||||
PKG_CHECK_MODULES([EDITLINE], [libedit], [
|
||||
AC_DEFINE([EDITLINE_SUPPORT], 1,
|
||||
[Define to 1 to include the LVM editline shell.])], AC_MSG_ERROR(
|
||||
[libedit could not be found which is required for the --enable-readline option.])
|
||||
[libedit could not be found which is required for the --enable-editline option.])
|
||||
)
|
||||
fi
|
||||
|
||||
@@ -1557,7 +1606,7 @@ AC_MSG_CHECKING(whether to enable readline)
|
||||
AC_MSG_RESULT($READLINE)
|
||||
|
||||
if test "$EDITLINE" = yes; then
|
||||
AC_CHECK_HEADERS(editline/readline.h editline/history.h,,hard_bailout)
|
||||
AC_CHECK_HEADERS(editline/readline.h,,hard_bailout)
|
||||
fi
|
||||
AC_MSG_CHECKING(whether to enable editline)
|
||||
AC_MSG_RESULT($EDITLINE)
|
||||
@@ -1779,6 +1828,7 @@ AC_SUBST(BLKDEACTIVATE)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
AC_SUBST(HAVE_VALGRIND)
|
||||
AC_SUBST(INTEGRITY)
|
||||
AC_SUBST(INTL)
|
||||
AC_SUBST(JOBS)
|
||||
AC_SUBST(LDDEPS)
|
||||
@@ -1855,6 +1905,7 @@ AC_SUBST(VDO)
|
||||
AC_SUBST(VDO_FORMAT_CMD)
|
||||
AC_SUBST(VDO_INCLUDE)
|
||||
AC_SUBST(VDO_LIB)
|
||||
AC_SUBST(WRITECACHE)
|
||||
AC_SUBST(WRITE_INSTALL)
|
||||
AC_SUBST(DMEVENTD_PIDFILE)
|
||||
AC_SUBST(LVMPOLLD_PIDFILE)
|
||||
@@ -1955,6 +2006,8 @@ AS_IF([test -n "$CACHE_CHECK_VERSION_WARN"],
|
||||
AS_IF([test -n "$VDO_CONFIGURE_WARN"],
|
||||
[AC_MSG_WARN([Unrecognized 'vdoformat' tool is REQUIRED for VDO logical volume creation!])])
|
||||
|
||||
AS_IF([test -n "$LVM_NEEDS_LIBAIO_WARN"],
|
||||
[AC_MSG_WARN([Only libdm part can be build without libaio: make [[install_]]device-mapper])])
|
||||
|
||||
AS_IF([test "$ODIRECT" != yes],
|
||||
[AC_MSG_WARN([O_DIRECT disabled: low-memory pvmove may lock up])])
|
||||
|
||||
@@ -22,6 +22,9 @@ SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
|
||||
|
||||
TARGETS = cmirrord
|
||||
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
CFLOW_TARGET := $(TARGETS)
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
LMLIBS += $(CPG_LIBS)
|
||||
@@ -33,6 +36,8 @@ cmirrord: $(OBJECTS)
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
|
||||
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
|
||||
|
||||
install: $(TARGETS)
|
||||
install_cluster: $(TARGETS)
|
||||
@echo " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord
|
||||
$(Q) $(INSTALL_PROGRAM) -D $< $(usrsbindir)/$(<F)
|
||||
|
||||
install: install_cluster
|
||||
|
||||
@@ -1548,7 +1548,7 @@ static void cpg_config_callback(cpg_handle_t handle, const struct cpg_name *gnam
|
||||
member_list, member_list_entries);
|
||||
}
|
||||
|
||||
cpg_callbacks_t cpg_callbacks = {
|
||||
static cpg_callbacks_t cpg_callbacks = {
|
||||
.cpg_deliver_fn = cpg_message_callback,
|
||||
.cpg_confchg_fn = cpg_config_callback,
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ struct clog_request {
|
||||
* machine. If the two are equal, there is no need
|
||||
* to do endian conversions.
|
||||
*/
|
||||
union {
|
||||
union version_u {
|
||||
uint64_t version[2]; /* LE version and native version */
|
||||
struct dm_list list;
|
||||
} u;
|
||||
|
||||
@@ -658,8 +658,7 @@ static int clog_dtr(struct dm_ulog_request *rq)
|
||||
if (lc->disk_fd != -1 && close(lc->disk_fd))
|
||||
LOG_ERROR("Failed to close disk log: %s",
|
||||
strerror(errno));
|
||||
if (lc->disk_buffer)
|
||||
free(lc->disk_buffer);
|
||||
free(lc->disk_buffer);
|
||||
free(lc->clean_bits);
|
||||
free(lc->sync_bits);
|
||||
free(lc);
|
||||
|
||||
@@ -14,11 +14,21 @@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
|
||||
SOURCES = libdevmapper-event.c
|
||||
SOURCES2 = dmeventd.c
|
||||
|
||||
TARGETS = dmeventd
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES) $(SOURCES2) \
|
||||
plugins/lvm2/dmeventd_lvm.c \
|
||||
plugins/mirror/dmeventd_mirror.c \
|
||||
plugins/raid/dmeventd_raid.c \
|
||||
plugins/snapshot/dmeventd_snapshot.c \
|
||||
plugins/thin/dmeventd_thin.c \
|
||||
plugins/vdo/dmeventd_vdo.c \
|
||||
)
|
||||
CFLOW_TARGET := $(TARGETS)
|
||||
|
||||
.PHONY: install_lib_dynamic install_lib_static install_include \
|
||||
install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
|
||||
@@ -37,6 +47,7 @@ endif
|
||||
|
||||
LIB_VERSION = $(LIB_VERSION_DM)
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIBS = $(PTHREAD_LIBS) -L$(interfacebuilddir) -ldevmapper
|
||||
|
||||
CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a
|
||||
|
||||
@@ -46,7 +57,6 @@ endif
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
CFLOW_TARGET = dmeventd
|
||||
|
||||
EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
|
||||
EXPORTED_FN_PREFIX = dm_event
|
||||
@@ -55,34 +65,26 @@ include $(top_builddir)/make.tmpl
|
||||
|
||||
all: device-mapper
|
||||
device-mapper: $(TARGETS)
|
||||
plugins.device-mapper: $(LIB_SHARED)
|
||||
|
||||
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
|
||||
LIBS += $(PTHREAD_LIBS) -L$(top_builddir)/libdm -ldevmapper
|
||||
|
||||
dmeventd: $(LIB_SHARED) dmeventd.o
|
||||
@echo " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
|
||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) -lm
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
|
||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS)
|
||||
|
||||
dmeventd.static: $(LIB_STATIC) dmeventd.o
|
||||
@echo " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static dmeventd.o \
|
||||
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
|
||||
|
||||
ifeq ("@PKGCONFIG@", "yes")
|
||||
INSTALL_LIB_TARGETS += install_pkgconfig
|
||||
endif
|
||||
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
-include $(top_builddir)/lib/liblvm-internal.cflow
|
||||
-include $(top_builddir)/lib/liblvm2cmd.cflow
|
||||
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
|
||||
-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
|
||||
endif
|
||||
|
||||
install_include: $(srcdir)/libdevmapper-event.h
|
||||
@echo " [INSTALL] $<"
|
||||
@echo " [INSTALL] $(<F)"
|
||||
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
|
||||
|
||||
install_pkgconfig: libdevmapper-event.pc
|
||||
|
||||
@@ -1742,7 +1742,8 @@ static void _init_thread_signals(void)
|
||||
sigset_t my_sigset;
|
||||
struct sigaction act = { .sa_handler = _sig_alarm };
|
||||
|
||||
sigaction(SIGALRM, &act, NULL);
|
||||
if (sigaction(SIGALRM, &act, NULL))
|
||||
log_sys_debug("sigaction", "SIGLARM");
|
||||
sigfillset(&my_sigset);
|
||||
|
||||
/* These are used for exiting */
|
||||
|
||||
@@ -25,9 +25,6 @@ LIB_NAME = libdevmapper-event-lvm2mirror
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
@@ -24,9 +24,6 @@ LIB_NAME = libdevmapper-event-lvm2raid
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
@@ -77,7 +77,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
|
||||
if (dead) {
|
||||
/*
|
||||
* Use the first event to run a repair ignoring any additonal ones.
|
||||
* Use the first event to run a repair ignoring any additional ones.
|
||||
*
|
||||
* We presume lvconvert to do pre-repair
|
||||
* checks to avoid bloat in this plugin.
|
||||
|
||||
@@ -24,9 +24,6 @@ LIB_NAME = libdevmapper-event-lvm2thin
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
@@ -24,9 +24,6 @@ LIB_NAME = libdevmapper-event-lvm2vdo
|
||||
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
|
||||
LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
install_lvm2: install_dm_plugin
|
||||
|
||||
@@ -15,7 +15,8 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
lvmdbusdir = $(python3dir)/lvmdbusd
|
||||
lvmdbuspydir = $(python3dir)/lvmdbusd
|
||||
lvmdbusdir = $(DESTDIR)$(lvmdbuspydir)
|
||||
|
||||
LVMDBUS_SRCDIR_FILES = \
|
||||
automatedproperties.py \
|
||||
@@ -53,16 +54,16 @@ include $(top_builddir)/make.tmpl
|
||||
all:
|
||||
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
|
||||
|
||||
install_lvmdbusd:
|
||||
install_lvmdbusd: $(LVMDBUSD)
|
||||
@echo " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_DIR) $(sbindir)
|
||||
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
|
||||
$(Q) $(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
|
||||
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
|
||||
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
|
||||
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
|
||||
$(Q) $(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
|
||||
$(Q) $(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
|
||||
$(Q) $(INSTALL_DIR) $(lvmdbusdir)
|
||||
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(lvmdbusdir))
|
||||
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(lvmdbusdir)
|
||||
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbuspydir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
|
||||
$(Q) $(CHMOD) 755 $(lvmdbusdir)/__pycache__
|
||||
$(Q) $(CHMOD) 444 $(lvmdbusdir)/__pycache__/*.py[co]
|
||||
|
||||
install_lvm2: install_lvmdbusd
|
||||
|
||||
|
||||
@@ -30,33 +30,39 @@ ifeq ("@BUILD_LOCKDDLM@", "yes")
|
||||
LOCK_LIBS += -ldlmcontrol
|
||||
endif
|
||||
|
||||
ifeq ("@BUILD_LOCKDIDM@", "yes")
|
||||
SOURCES += lvmlockd-idm.c
|
||||
LOCK_LIBS += -lseagate_ilm -lblkid
|
||||
endif
|
||||
|
||||
SOURCES2 = lvmlockctl.c
|
||||
|
||||
TARGETS = lvmlockd lvmlockctl
|
||||
|
||||
.PHONY: install_lvmlockd
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
CFLOW_TARGET = lvmlockd
|
||||
|
||||
.PHONY: install_lvmlockd install_lvmlockctl
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
CFLAGS += $(EXTRA_EXEC_CFLAGS)
|
||||
INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(RT_LIBS) $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||
|
||||
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||
|
||||
ifeq ($(USE_SD_NOTIFY),yes)
|
||||
CFLAGS += $(shell pkg-config --cflags libsystemd) -DUSE_SD_NOTIFY
|
||||
LIBS += $(shell pkg-config --libs libsystemd)
|
||||
endif
|
||||
|
||||
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
|
||||
$(top_builddir)/libdaemon/server/libdaemonserver.a
|
||||
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
|
||||
@echo " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LOCK_LIBS) -ldaemonserver $(INTERNAL_LIBS) $(LIBS)
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LOCK_LIBS) $(LIBS)
|
||||
|
||||
lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a
|
||||
lvmlockctl: lvmlockctl.o $(INTERNAL_LIBS)
|
||||
@echo " [CC] $@"
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(INTERNAL_LIBS) $(LIBS)
|
||||
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
|
||||
|
||||
install_lvmlockd: lvmlockd
|
||||
@echo " [INSTALL] $<"
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <syslog.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int quit = 0;
|
||||
static int info = 0;
|
||||
@@ -30,6 +33,7 @@ static int kill_vg = 0;
|
||||
static int drop_vg = 0;
|
||||
static int gl_enable = 0;
|
||||
static int gl_disable = 0;
|
||||
static int use_stderr = 0;
|
||||
static int stop_lockspaces = 0;
|
||||
static char *arg_vg_name = NULL;
|
||||
|
||||
@@ -47,6 +51,22 @@ do { \
|
||||
printf(fmt "\n", ##args); \
|
||||
} while (0)
|
||||
|
||||
#define log_sys_emerg(fmt, args...) \
|
||||
do { \
|
||||
if (use_stderr) \
|
||||
fprintf(stderr, fmt "\n", ##args); \
|
||||
else \
|
||||
syslog(LOG_EMERG, fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define log_sys_warn(fmt, args...) \
|
||||
do { \
|
||||
if (use_stderr) \
|
||||
fprintf(stderr, fmt "\n", ##args); \
|
||||
else \
|
||||
syslog(LOG_WARNING, fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define MAX_LINE 512
|
||||
|
||||
/* copied from lvmlockd-internal.h */
|
||||
@@ -502,51 +522,274 @@ static int do_stop_lockspaces(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int do_kill(void)
|
||||
static int _reopen_fd_to_null(int fd)
|
||||
{
|
||||
daemon_reply reply;
|
||||
int result;
|
||||
int rv;
|
||||
int null_fd;
|
||||
int r = 0;
|
||||
|
||||
syslog(LOG_EMERG, "Lost access to sanlock lease storage in VG %s.", arg_vg_name);
|
||||
/* These two lines explain the manual alternative to the FIXME below. */
|
||||
syslog(LOG_EMERG, "Immediately deactivate LVs in VG %s.", arg_vg_name);
|
||||
syslog(LOG_EMERG, "Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
|
||||
|
||||
/*
|
||||
* It may not be strictly necessary to notify lvmlockd of the kill, but
|
||||
* lvmlockd can use this information to avoid attempting any new lock
|
||||
* requests in the VG (which would fail anyway), and can return an
|
||||
* error indicating that the VG has been killed.
|
||||
*/
|
||||
|
||||
reply = _lvmlockd_send("kill_vg",
|
||||
"cmd = %s", "lvmlockctl",
|
||||
"pid = " FMTd64, (int64_t) getpid(),
|
||||
"vg_name = %s", arg_vg_name,
|
||||
NULL);
|
||||
|
||||
if (!_lvmlockd_result(reply, &result)) {
|
||||
log_error("lvmlockd result %d", result);
|
||||
rv = result;
|
||||
} else {
|
||||
rv = 0;
|
||||
if ((null_fd = open("/dev/null", O_RDWR)) == -1) {
|
||||
log_error("open error /dev/null %d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
daemon_reply_destroy(reply);
|
||||
if (close(fd)) {
|
||||
log_error("close error fd %d %d", fd, errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: here is where we should implement a strong form of
|
||||
* blkdeactivate, and if it completes successfully, automatically call
|
||||
* do_drop() afterward. (The drop step may not always be necessary
|
||||
* if the lvm commands run while shutting things down release all the
|
||||
* leases.)
|
||||
*
|
||||
* run_strong_blkdeactivate();
|
||||
* do_drop();
|
||||
*/
|
||||
if (dup2(null_fd, fd) == -1) {
|
||||
log_error("dup2 error %d", errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return rv;
|
||||
r = 1;
|
||||
out:
|
||||
if (close(null_fd)) {
|
||||
log_error("close error fd %d %d", null_fd, errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#define MAX_AV_COUNT 32
|
||||
#define ONE_ARG_LEN 1024
|
||||
|
||||
static void _run_command_pipe(const char *cmd_str, pid_t *pid_out, FILE **fp_out)
|
||||
{
|
||||
char arg[ONE_ARG_LEN];
|
||||
char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
|
||||
char *arg_dup;
|
||||
int av_count = 0;
|
||||
int cmd_len;
|
||||
int arg_len;
|
||||
pid_t pid = 0;
|
||||
FILE *fp = NULL;
|
||||
int pipefd[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_AV_COUNT + 1; i++)
|
||||
av[i] = NULL;
|
||||
|
||||
cmd_len = strlen(cmd_str);
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg_len = 0;
|
||||
|
||||
for (i = 0; i < cmd_len; i++) {
|
||||
if (!cmd_str[i])
|
||||
break;
|
||||
|
||||
if (av_count == MAX_AV_COUNT)
|
||||
goto out;
|
||||
|
||||
if (cmd_str[i] == '\\') {
|
||||
if (i == (cmd_len - 1))
|
||||
break;
|
||||
i++;
|
||||
|
||||
if (cmd_str[i] == '\\') {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
continue;
|
||||
}
|
||||
if (isspace(cmd_str[i])) {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
} else if (isspace(cmd_str[i])) {
|
||||
if (arg_len) {
|
||||
if (!(arg_dup = strdup(arg)))
|
||||
goto out;
|
||||
av[av_count++] = arg_dup;
|
||||
}
|
||||
|
||||
memset(arg, 0, sizeof(arg));
|
||||
arg_len = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_len) {
|
||||
if (av_count >= MAX_AV_COUNT)
|
||||
goto out;
|
||||
if (!(arg_dup = strdup(arg)))
|
||||
goto out;
|
||||
av[av_count++] = arg_dup;
|
||||
}
|
||||
|
||||
if (pipe(pipefd)) {
|
||||
log_error("pipe error %d", errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
log_error("fork error %d", errno);
|
||||
pid = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
/* Child -> writer, convert pipe[0] to STDOUT */
|
||||
if (!_reopen_fd_to_null(STDIN_FILENO))
|
||||
log_error("reopen STDIN error");
|
||||
else if (close(pipefd[0 /*read*/]))
|
||||
log_error("close error pipe[0] %d", errno);
|
||||
else if (close(STDOUT_FILENO))
|
||||
log_error("close error STDOUT %d", errno);
|
||||
else if (dup2(pipefd[1 /*write*/], STDOUT_FILENO) == -1)
|
||||
log_error("dup2 error STDOUT %d", errno);
|
||||
else if (close(pipefd[1]))
|
||||
log_error("close error pipe[1] %d", errno);
|
||||
else {
|
||||
execvp(av[0], av);
|
||||
log_error("execvp error %d", errno);
|
||||
}
|
||||
_exit(errno);
|
||||
}
|
||||
|
||||
/* Parent -> reader */
|
||||
if (close(pipefd[1 /*write*/]))
|
||||
log_error("close error STDOUT %d", errno);
|
||||
|
||||
if (!(fp = fdopen(pipefd[0 /*read*/], "r"))) {
|
||||
log_error("fdopen STDIN error %d", errno);
|
||||
if (close(pipefd[0]))
|
||||
log_error("close error STDIN %d", errno);
|
||||
}
|
||||
|
||||
out:
|
||||
for (i = 0; i < MAX_AV_COUNT + 1; i++)
|
||||
free(av[i]);
|
||||
|
||||
*pid_out = pid;
|
||||
*fp_out = fp;
|
||||
}
|
||||
|
||||
/* Returns -1 on error, 0 on success. */
|
||||
|
||||
static int _close_command_pipe(pid_t pid, FILE *fp)
|
||||
{
|
||||
int status, estatus;
|
||||
int ret = -1;
|
||||
|
||||
if (waitpid(pid, &status, 0) != pid) {
|
||||
log_error("waitpid error pid %d %d", pid, errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
/* pid exited with an exit code */
|
||||
estatus = WEXITSTATUS(status);
|
||||
|
||||
/* exit status 0: child success */
|
||||
if (!estatus) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* exit status not zero: child error */
|
||||
log_error("child exit error %d", estatus);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
/* pid terminated due to a signal */
|
||||
log_error("child exit from signal");
|
||||
goto out;
|
||||
}
|
||||
|
||||
log_error("child exit problem");
|
||||
|
||||
out:
|
||||
if (fp && fclose(fp))
|
||||
log_error("fclose error STDIN %d", errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns -1 on error, 0 on success. */
|
||||
|
||||
static int _get_kill_command(char *kill_cmd)
|
||||
{
|
||||
char config_cmd[PATH_MAX + 128] = { 0 };
|
||||
char config_val[1024] = { 0 };
|
||||
char line[PATH_MAX] = { 0 };
|
||||
pid_t pid = 0;
|
||||
FILE *fp = NULL;
|
||||
|
||||
snprintf(config_cmd, PATH_MAX, "%s config --typeconfig full global/lvmlockctl_kill_command", LVM_PATH);
|
||||
|
||||
_run_command_pipe(config_cmd, &pid, &fp);
|
||||
|
||||
if (!pid) {
|
||||
log_error("failed to run %s", config_cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!fp) {
|
||||
log_error("failed to get output %s", config_cmd);
|
||||
_close_command_pipe(pid, fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!fgets(line, sizeof(line), fp)) {
|
||||
log_error("no output from %s", config_cmd);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (sscanf(line, "lvmlockctl_kill_command=\"%256[^\n\"]\"", config_val) != 1) {
|
||||
log_error("unrecognized config value from %s", config_cmd);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!config_val[0] || (config_val[0] == ' ')) {
|
||||
log_error("invalid config value from %s", config_cmd);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (config_val[0] != '/') {
|
||||
log_error("lvmlockctl_kill_command must be full path");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
printf("Found lvmlockctl_kill_command: %s\n", config_val);
|
||||
|
||||
snprintf(kill_cmd, PATH_MAX, "%s %s", config_val, arg_vg_name);
|
||||
kill_cmd[PATH_MAX-1] = '\0';
|
||||
|
||||
_close_command_pipe(pid, fp);
|
||||
return 0;
|
||||
bad:
|
||||
_close_command_pipe(pid, fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns -1 on error, 0 on success. */
|
||||
|
||||
static int _run_kill_command(char *kill_cmd)
|
||||
{
|
||||
pid_t pid = 0;
|
||||
FILE *fp = NULL;
|
||||
int rv;
|
||||
|
||||
_run_command_pipe(kill_cmd, &pid, &fp);
|
||||
rv = _close_command_pipe(pid, fp);
|
||||
|
||||
if (!pid)
|
||||
return -1;
|
||||
|
||||
if (rv < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_drop(void)
|
||||
@@ -555,7 +798,7 @@ static int do_drop(void)
|
||||
int result;
|
||||
int rv;
|
||||
|
||||
syslog(LOG_WARNING, "Dropping locks for VG %s.", arg_vg_name);
|
||||
log_sys_warn("Dropping locks for VG %s.", arg_vg_name);
|
||||
|
||||
/*
|
||||
* Check for misuse by looking for any active LVs in the VG
|
||||
@@ -583,6 +826,84 @@ static int do_drop(void)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int do_kill(void)
|
||||
{
|
||||
char kill_cmd[PATH_MAX] = { 0 };
|
||||
daemon_reply reply;
|
||||
int no_kill_command = 0;
|
||||
int result;
|
||||
int rv;
|
||||
|
||||
log_sys_emerg("lvmlockd lost access to locks in VG %s.", arg_vg_name);
|
||||
|
||||
rv = _get_kill_command(kill_cmd);
|
||||
if (rv < 0) {
|
||||
log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name);
|
||||
log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
|
||||
no_kill_command = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* It may not be strictly necessary to notify lvmlockd of the kill, but
|
||||
* lvmlockd can use this information to avoid attempting any new lock
|
||||
* requests in the VG (which would fail anyway), and can return an
|
||||
* error indicating that the VG has been killed.
|
||||
*/
|
||||
_lvmlockd = lvmlockd_open(NULL);
|
||||
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
|
||||
log_error("Cannot connect to lvmlockd for kill_vg.");
|
||||
goto run;
|
||||
}
|
||||
reply = _lvmlockd_send("kill_vg",
|
||||
"cmd = %s", "lvmlockctl",
|
||||
"pid = " FMTd64, (int64_t) getpid(),
|
||||
"vg_name = %s", arg_vg_name,
|
||||
NULL);
|
||||
if (!_lvmlockd_result(reply, &result))
|
||||
log_error("lvmlockd result %d kill_vg", result);
|
||||
daemon_reply_destroy(reply);
|
||||
lvmlockd_close(_lvmlockd);
|
||||
|
||||
run:
|
||||
if (no_kill_command)
|
||||
return 0;
|
||||
|
||||
rv = _run_kill_command(kill_cmd);
|
||||
if (rv < 0) {
|
||||
log_sys_emerg("Failed to run VG %s kill command %s", arg_vg_name, kill_cmd);
|
||||
log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name);
|
||||
log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_sys_warn("Successful VG %s kill command %s", arg_vg_name, kill_cmd);
|
||||
|
||||
/*
|
||||
* If kill command was successfully, call do_drop(). (The drop step
|
||||
* may not always be necessary if the lvm commands run while shutting
|
||||
* things down release all the leases.)
|
||||
*/
|
||||
rv = 0;
|
||||
_lvmlockd = lvmlockd_open(NULL);
|
||||
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
|
||||
log_sys_emerg("Failed to connect to lvmlockd to drop locks in VG %s.", arg_vg_name);
|
||||
return -1;
|
||||
}
|
||||
reply = _lvmlockd_send("drop_vg",
|
||||
"cmd = %s", "lvmlockctl",
|
||||
"pid = " FMTd64, (int64_t) getpid(),
|
||||
"vg_name = %s", arg_vg_name,
|
||||
NULL);
|
||||
if (!_lvmlockd_result(reply, &result)) {
|
||||
log_sys_emerg("Failed to drop locks in VG %s", arg_vg_name);
|
||||
rv = result;
|
||||
}
|
||||
daemon_reply_destroy(reply);
|
||||
lvmlockd_close(_lvmlockd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf("lvmlockctl options\n");
|
||||
@@ -600,7 +921,7 @@ static void print_usage(void)
|
||||
printf("--force | -f 0|1>\n");
|
||||
printf(" Force option for other commands.\n");
|
||||
printf("--kill | -k <vgname>\n");
|
||||
printf(" Kill access to the VG when sanlock cannot renew lease.\n");
|
||||
printf(" Kill access to the VG locks are lost (see lvmlockctl_kill_command).\n");
|
||||
printf("--drop | -r <vgname>\n");
|
||||
printf(" Clear locks for the VG when it is unused after kill (-k).\n");
|
||||
printf("--gl-enable | -E <vgname>\n");
|
||||
@@ -609,6 +930,8 @@ static void print_usage(void)
|
||||
printf(" Tell lvmlockd to disable the global lock in a sanlock VG.\n");
|
||||
printf("--stop-lockspaces | -S\n");
|
||||
printf(" Stop all lockspaces.\n");
|
||||
printf("--stderr | -e\n");
|
||||
printf(" Send kill and drop messages to stderr instead of syslog\n");
|
||||
}
|
||||
|
||||
static int read_options(int argc, char *argv[])
|
||||
@@ -628,6 +951,7 @@ static int read_options(int argc, char *argv[])
|
||||
{"gl-enable", required_argument, 0, 'E' },
|
||||
{"gl-disable", required_argument, 0, 'D' },
|
||||
{"stop-lockspaces", no_argument, 0, 'S' },
|
||||
{"stderr", no_argument, 0, 'e' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -637,7 +961,7 @@ static int read_options(int argc, char *argv[])
|
||||
}
|
||||
|
||||
while (1) {
|
||||
c = getopt_long(argc, argv, "hqidE:D:w:k:r:S", long_options, &option_index);
|
||||
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
@@ -663,23 +987,30 @@ static int read_options(int argc, char *argv[])
|
||||
break;
|
||||
case 'k':
|
||||
kill_vg = 1;
|
||||
free(arg_vg_name);
|
||||
arg_vg_name = strdup(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
drop_vg = 1;
|
||||
free(arg_vg_name);
|
||||
arg_vg_name = strdup(optarg);
|
||||
break;
|
||||
case 'E':
|
||||
gl_enable = 1;
|
||||
free(arg_vg_name);
|
||||
arg_vg_name = strdup(optarg);
|
||||
break;
|
||||
case 'D':
|
||||
gl_disable = 1;
|
||||
free(arg_vg_name);
|
||||
arg_vg_name = strdup(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
stop_lockspaces = 1;
|
||||
break;
|
||||
case 'e':
|
||||
use_stderr = 1;
|
||||
break;
|
||||
default:
|
||||
print_usage();
|
||||
exit(1);
|
||||
@@ -698,8 +1029,12 @@ int main(int argc, char **argv)
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
_lvmlockd = lvmlockd_open(NULL);
|
||||
/* do_kill handles lvmlockd connections itself */
|
||||
if (kill_vg)
|
||||
return do_kill();
|
||||
|
||||
|
||||
_lvmlockd = lvmlockd_open(NULL);
|
||||
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
|
||||
log_error("Cannot connect to lvmlockd.");
|
||||
return -1;
|
||||
@@ -720,11 +1055,6 @@ int main(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (kill_vg) {
|
||||
rv = do_kill();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (drop_vg) {
|
||||
rv = do_drop();
|
||||
goto out;
|
||||
|
||||
@@ -421,6 +421,63 @@ struct lockspace *alloc_lockspace(void)
|
||||
return ls;
|
||||
}
|
||||
|
||||
static char **alloc_pvs_path(struct pvs *pvs, int num)
|
||||
{
|
||||
if (!num)
|
||||
return NULL;
|
||||
|
||||
pvs->path = malloc(sizeof(char *) * num);
|
||||
if (!pvs->path)
|
||||
return NULL;
|
||||
|
||||
memset(pvs->path, 0x0, sizeof(char *) * num);
|
||||
return pvs->path;
|
||||
}
|
||||
|
||||
static void free_pvs_path(struct pvs *pvs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pvs->num; i++) {
|
||||
if (!pvs->path[i])
|
||||
continue;
|
||||
|
||||
free((char *)pvs->path[i]);
|
||||
pvs->path[i] = NULL;
|
||||
}
|
||||
|
||||
if (!pvs->path) {
|
||||
free(pvs->path);
|
||||
pvs->path = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static char **alloc_and_copy_pvs_path(struct pvs *dst, struct pvs *src)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!alloc_pvs_path(dst, src->num))
|
||||
return NULL;
|
||||
|
||||
dst->num = 0;
|
||||
for (i = 0; i < src->num; i++) {
|
||||
if (!src->path[i] || !strcmp(src->path[i], "none"))
|
||||
continue;
|
||||
|
||||
dst->path[dst->num] = strdup(src->path[i]);
|
||||
if (!dst->path[dst->num]) {
|
||||
log_error("out of memory for copying pvs path");
|
||||
goto failed;
|
||||
}
|
||||
dst->num++;
|
||||
}
|
||||
return dst->path;
|
||||
|
||||
failed:
|
||||
free_pvs_path(dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct action *alloc_action(void)
|
||||
{
|
||||
struct action *act;
|
||||
@@ -510,6 +567,9 @@ static void free_action(struct action *act)
|
||||
free(act->path);
|
||||
act->path = NULL;
|
||||
}
|
||||
|
||||
free_pvs_path(&act->pvs);
|
||||
|
||||
pthread_mutex_lock(&unused_struct_mutex);
|
||||
if (unused_action_count >= MAX_UNUSED_ACTION) {
|
||||
free(act);
|
||||
@@ -564,9 +624,12 @@ static int setup_structs(void)
|
||||
struct lock *lk;
|
||||
int data_san = lm_data_size_sanlock();
|
||||
int data_dlm = lm_data_size_dlm();
|
||||
int data_idm = lm_data_size_idm();
|
||||
int i;
|
||||
|
||||
resource_lm_data_size = data_san > data_dlm ? data_san : data_dlm;
|
||||
resource_lm_data_size = resource_lm_data_size > data_idm ?
|
||||
resource_lm_data_size : data_idm;
|
||||
|
||||
pthread_mutex_init(&unused_struct_mutex, NULL);
|
||||
INIT_LIST_HEAD(&unused_action);
|
||||
@@ -683,6 +746,8 @@ static const char *lm_str(int x)
|
||||
return "dlm";
|
||||
case LD_LM_SANLOCK:
|
||||
return "sanlock";
|
||||
case LD_LM_IDM:
|
||||
return "idm";
|
||||
default:
|
||||
return "lm_unknown";
|
||||
}
|
||||
@@ -872,7 +937,7 @@ static int read_adopt_file(struct list_head *vg_lockd)
|
||||
char vg_uuid[72];
|
||||
char lm_type_str[16];
|
||||
char mode[8];
|
||||
struct lockspace *ls, *ls2;
|
||||
struct lockspace *ls = NULL, *ls2;
|
||||
struct resource *r;
|
||||
FILE *fp;
|
||||
|
||||
@@ -896,8 +961,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
|
||||
goto fail;
|
||||
|
||||
memset(vg_uuid, 0, sizeof(vg_uuid));
|
||||
memset(lm_type_str, 0, sizeof(lm_type_str));
|
||||
|
||||
if (sscanf(adopt_line, "VG: %63s %64s %16s %64s",
|
||||
if (sscanf(adopt_line, "VG: %63s %64s %15s %64s",
|
||||
vg_uuid, ls->vg_name, lm_type_str, ls->vg_args) != 4) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -916,8 +982,9 @@ static int read_adopt_file(struct list_head *vg_lockd)
|
||||
r->type = LD_RT_LV;
|
||||
|
||||
memset(vg_uuid, 0, sizeof(vg_uuid));
|
||||
memset(mode, 0, sizeof(mode));
|
||||
|
||||
if (sscanf(adopt_line, "LV: %64s %64s %s %8s %u",
|
||||
if (sscanf(adopt_line, "LV: %64s %64s %s %7s %u",
|
||||
vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -966,6 +1033,8 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
|
||||
rv = lm_prepare_lockspace_dlm(ls);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
rv = lm_prepare_lockspace_sanlock(ls);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_prepare_lockspace_idm(ls);
|
||||
else
|
||||
return -1;
|
||||
|
||||
@@ -982,6 +1051,8 @@ static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt)
|
||||
rv = lm_add_lockspace_dlm(ls, adopt);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
rv = lm_add_lockspace_sanlock(ls, adopt);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_add_lockspace_idm(ls, adopt);
|
||||
else
|
||||
return -1;
|
||||
|
||||
@@ -998,6 +1069,8 @@ static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_v
|
||||
rv = lm_rem_lockspace_dlm(ls, free_vg);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
rv = lm_rem_lockspace_sanlock(ls, free_vg);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_rem_lockspace_idm(ls, free_vg);
|
||||
else
|
||||
return -1;
|
||||
|
||||
@@ -1015,6 +1088,9 @@ static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct ac
|
||||
rv = lm_lock_dlm(ls, r, mode, vb_out, adopt);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
rv = lm_lock_sanlock(ls, r, mode, vb_out, retry, adopt);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid,
|
||||
&act->pvs, adopt);
|
||||
else
|
||||
return -1;
|
||||
|
||||
@@ -1032,6 +1108,8 @@ static int lm_convert(struct lockspace *ls, struct resource *r,
|
||||
rv = lm_convert_dlm(ls, r, mode, r_version);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
rv = lm_convert_sanlock(ls, r, mode, r_version);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_convert_idm(ls, r, mode, r_version);
|
||||
else
|
||||
return -1;
|
||||
|
||||
@@ -1049,6 +1127,8 @@ static int lm_unlock(struct lockspace *ls, struct resource *r, struct action *ac
|
||||
rv = lm_unlock_dlm(ls, r, r_version, lmu_flags);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
rv = lm_unlock_sanlock(ls, r, r_version, lmu_flags);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_unlock_idm(ls, r, r_version, lmu_flags);
|
||||
else
|
||||
return -1;
|
||||
|
||||
@@ -1063,6 +1143,8 @@ static int lm_hosts(struct lockspace *ls, int notify)
|
||||
return lm_hosts_dlm(ls, notify);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
return lm_hosts_sanlock(ls, notify);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
return lm_hosts_idm(ls, notify);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1072,6 +1154,8 @@ static void lm_rem_resource(struct lockspace *ls, struct resource *r)
|
||||
lm_rem_resource_dlm(ls, r);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
lm_rem_resource_sanlock(ls, r);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
lm_rem_resource_idm(ls, r);
|
||||
}
|
||||
|
||||
static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
|
||||
@@ -1080,6 +1164,8 @@ static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *s
|
||||
return 0;
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
return lm_find_free_lock_sanlock(ls, free_offset, sector_size, align_size);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1688,8 +1774,8 @@ static int res_update(struct lockspace *ls, struct resource *r,
|
||||
}
|
||||
|
||||
/*
|
||||
* There is nothing to deallocate when freeing a dlm LV, the LV
|
||||
* will simply be unlocked by rem_resource.
|
||||
* For DLM and IDM locking scheme, there is nothing to deallocate when freeing a
|
||||
* LV, the LV will simply be unlocked by rem_resource.
|
||||
*/
|
||||
|
||||
static int free_lv(struct lockspace *ls, struct resource *r)
|
||||
@@ -1698,6 +1784,8 @@ static int free_lv(struct lockspace *ls, struct resource *r)
|
||||
return lm_free_lv_sanlock(ls, r);
|
||||
else if (ls->lm_type == LD_LM_DLM)
|
||||
return 0;
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1798,9 +1886,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
|
||||
act->result = -EINVAL;
|
||||
list_del(&act->list);
|
||||
add_client_result(act);
|
||||
}
|
||||
|
||||
if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN) {
|
||||
} else if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN) {
|
||||
rv = res_unlock(ls, r, act);
|
||||
|
||||
if (rv == -ENOENT && (act->flags & LD_AF_UNLOCK_CANCEL))
|
||||
@@ -2680,7 +2766,7 @@ out_rem:
|
||||
|
||||
log_debug("S %s clearing locks", ls->name);
|
||||
|
||||
rv = clear_locks(ls, free_vg, drop_vg);
|
||||
(void) clear_locks(ls, free_vg, drop_vg);
|
||||
|
||||
/*
|
||||
* Tell any other hosts in the lockspace to leave it
|
||||
@@ -2758,6 +2844,8 @@ out_act:
|
||||
ls->drop_vg = drop_vg;
|
||||
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
|
||||
global_dlm_lockspace_exists = 0;
|
||||
if (ls->lm_type == LD_LM_IDM && !strcmp(ls->name, gl_lsname_idm))
|
||||
global_idm_lockspace_exists = 0;
|
||||
|
||||
/*
|
||||
* Avoid a name collision of the same lockspace is added again before
|
||||
@@ -2849,6 +2937,8 @@ static void gl_ls_name(char *ls_name)
|
||||
memcpy(ls_name, gl_lsname_dlm, MAX_NAME);
|
||||
else if (gl_use_sanlock)
|
||||
memcpy(ls_name, gl_lsname_sanlock, MAX_NAME);
|
||||
else if (gl_use_idm)
|
||||
memcpy(ls_name, gl_lsname_idm, MAX_NAME);
|
||||
else
|
||||
memset(ls_name, 0, MAX_NAME);
|
||||
}
|
||||
@@ -2877,9 +2967,20 @@ static int add_lockspace_thread(const char *ls_name,
|
||||
strncpy(ls->name, ls_name, MAX_NAME);
|
||||
ls->lm_type = lm_type;
|
||||
|
||||
if (act)
|
||||
if (act) {
|
||||
ls->start_client_id = act->client_id;
|
||||
|
||||
/*
|
||||
* Copy PV list to lockspact structure, so this is
|
||||
* used for VG locking for idm scheme.
|
||||
*/
|
||||
if (lm_type == LD_LM_IDM &&
|
||||
!alloc_and_copy_pvs_path(&ls->pvs, &act->pvs)) {
|
||||
free(ls);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (vg_uuid)
|
||||
strncpy(ls->vg_uuid, vg_uuid, 64);
|
||||
|
||||
@@ -2906,6 +3007,18 @@ static int add_lockspace_thread(const char *ls_name,
|
||||
pthread_mutex_lock(&lockspaces_mutex);
|
||||
ls2 = find_lockspace_name(ls->name);
|
||||
if (ls2) {
|
||||
/*
|
||||
* If find an existed lockspace, we need to update the PV list
|
||||
* based on the latest information, and release for the old
|
||||
* PV list in case it keeps stale information.
|
||||
*/
|
||||
free_pvs_path(&ls2->pvs);
|
||||
if (lm_type == LD_LM_IDM &&
|
||||
!alloc_and_copy_pvs_path(&ls2->pvs, &ls->pvs)) {
|
||||
log_debug("add_lockspace_thread %s fails to allocate pvs", ls->name);
|
||||
rv = -ENOMEM;
|
||||
}
|
||||
|
||||
if (ls2->thread_stop) {
|
||||
log_debug("add_lockspace_thread %s exists and stopping", ls->name);
|
||||
rv = -EAGAIN;
|
||||
@@ -2918,6 +3031,7 @@ static int add_lockspace_thread(const char *ls_name,
|
||||
}
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
free_resource(r);
|
||||
free_pvs_path(&ls->pvs);
|
||||
free(ls);
|
||||
return rv;
|
||||
}
|
||||
@@ -2931,6 +3045,8 @@ static int add_lockspace_thread(const char *ls_name,
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
|
||||
global_dlm_lockspace_exists = 1;
|
||||
if (ls->lm_type == LD_LM_IDM && !strcmp(ls->name, gl_lsname_idm))
|
||||
global_idm_lockspace_exists = 1;
|
||||
list_add_tail(&ls->list, &lockspaces);
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
|
||||
@@ -2941,6 +3057,7 @@ static int add_lockspace_thread(const char *ls_name,
|
||||
list_del(&ls->list);
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
free_resource(r);
|
||||
free_pvs_path(&ls->pvs);
|
||||
free(ls);
|
||||
return rv;
|
||||
}
|
||||
@@ -2949,16 +3066,15 @@ static int add_lockspace_thread(const char *ls_name,
|
||||
}
|
||||
|
||||
/*
|
||||
* There is no add_sanlock_global_lockspace or
|
||||
* rem_sanlock_global_lockspace because with sanlock,
|
||||
* the global lockspace is one of the vg lockspaces.
|
||||
* There is no variant for sanlock because, with sanlock, the global
|
||||
* lockspace is one of the vg lockspaces.
|
||||
*/
|
||||
|
||||
static int add_dlm_global_lockspace(struct action *act)
|
||||
static int add_global_lockspace(char *ls_name, int lm_type,
|
||||
struct action *act)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (global_dlm_lockspace_exists)
|
||||
if (global_dlm_lockspace_exists || global_idm_lockspace_exists)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@@ -2966,9 +3082,9 @@ static int add_dlm_global_lockspace(struct action *act)
|
||||
* lock request, insert an internal gl sh lock request?
|
||||
*/
|
||||
|
||||
rv = add_lockspace_thread(gl_lsname_dlm, NULL, NULL, LD_LM_DLM, NULL, act);
|
||||
rv = add_lockspace_thread(ls_name, NULL, NULL, lm_type, NULL, act);
|
||||
if (rv < 0)
|
||||
log_debug("add_dlm_global_lockspace add_lockspace_thread %d", rv);
|
||||
log_debug("add_global_lockspace add_lockspace_thread %d", rv);
|
||||
|
||||
/*
|
||||
* EAGAIN may be returned for a short period because
|
||||
@@ -2981,12 +3097,12 @@ static int add_dlm_global_lockspace(struct action *act)
|
||||
}
|
||||
|
||||
/*
|
||||
* If dlm gl lockspace is the only one left, then stop it.
|
||||
* This is not used for an explicit rem_lockspace action from
|
||||
* the client, only for auto remove.
|
||||
* When DLM or IDM locking scheme is used for global lock, if the global
|
||||
* lockspace is the only one left, then stop it. This is not used for
|
||||
* an explicit rem_lockspace action from the client, only for auto
|
||||
* remove.
|
||||
*/
|
||||
|
||||
static int rem_dlm_global_lockspace(void)
|
||||
static int rem_global_lockspace(char *ls_name)
|
||||
{
|
||||
struct lockspace *ls, *ls_gl = NULL;
|
||||
int others = 0;
|
||||
@@ -2994,7 +3110,7 @@ static int rem_dlm_global_lockspace(void)
|
||||
|
||||
pthread_mutex_lock(&lockspaces_mutex);
|
||||
list_for_each_entry(ls, &lockspaces, list) {
|
||||
if (!strcmp(ls->name, gl_lsname_dlm)) {
|
||||
if (!strcmp(ls->name, ls_name)) {
|
||||
ls_gl = ls;
|
||||
continue;
|
||||
}
|
||||
@@ -3026,6 +3142,26 @@ out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int add_dlm_global_lockspace(struct action *act)
|
||||
{
|
||||
return add_global_lockspace(gl_lsname_dlm, LD_LM_DLM, act);
|
||||
}
|
||||
|
||||
static int rem_dlm_global_lockspace(void)
|
||||
{
|
||||
return rem_global_lockspace(gl_lsname_dlm);
|
||||
}
|
||||
|
||||
static int add_idm_global_lockspace(struct action *act)
|
||||
{
|
||||
return add_global_lockspace(gl_lsname_idm, LD_LM_IDM, act);
|
||||
}
|
||||
|
||||
static int rem_idm_global_lockspace(void)
|
||||
{
|
||||
return rem_global_lockspace(gl_lsname_idm);
|
||||
}
|
||||
|
||||
/*
|
||||
* When the first dlm lockspace is added for a vg, automatically add a separate
|
||||
* dlm lockspace for the global lock.
|
||||
@@ -3051,6 +3187,9 @@ static int add_lockspace(struct action *act)
|
||||
if (gl_use_dlm) {
|
||||
rv = add_dlm_global_lockspace(act);
|
||||
return rv;
|
||||
} else if (gl_use_idm) {
|
||||
rv = add_idm_global_lockspace(act);
|
||||
return rv;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -3059,6 +3198,8 @@ static int add_lockspace(struct action *act)
|
||||
if (act->rt == LD_RT_VG) {
|
||||
if (gl_use_dlm)
|
||||
add_dlm_global_lockspace(NULL);
|
||||
else if (gl_use_idm)
|
||||
add_idm_global_lockspace(NULL);
|
||||
|
||||
vg_ls_name(act->vg_name, ls_name);
|
||||
|
||||
@@ -3126,14 +3267,15 @@ static int rem_lockspace(struct action *act)
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
|
||||
/*
|
||||
* The dlm global lockspace was automatically added when
|
||||
* the first dlm vg lockspace was added, now reverse that
|
||||
* by automatically removing the dlm global lockspace when
|
||||
* the last dlm vg lockspace is removed.
|
||||
* For DLM and IDM locking scheme, the global lockspace was
|
||||
* automatically added when the first vg lockspace was added,
|
||||
* now reverse that by automatically removing the dlm global
|
||||
* lockspace when the last vg lockspace is removed.
|
||||
*/
|
||||
|
||||
if (rt == LD_RT_VG && gl_use_dlm)
|
||||
rem_dlm_global_lockspace();
|
||||
else if (rt == LD_RT_VG && gl_use_idm)
|
||||
rem_idm_global_lockspace();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3257,6 +3399,7 @@ static int for_each_lockspace(int do_stop, int do_free, int do_force)
|
||||
if (ls->free_vg) {
|
||||
/* In future we may need to free ls->actions here */
|
||||
free_ls_resources(ls);
|
||||
free_pvs_path(&ls->pvs);
|
||||
free(ls);
|
||||
free_count++;
|
||||
}
|
||||
@@ -3270,6 +3413,7 @@ static int for_each_lockspace(int do_stop, int do_free, int do_force)
|
||||
if (!gl_type_static) {
|
||||
gl_use_dlm = 0;
|
||||
gl_use_sanlock = 0;
|
||||
gl_use_idm = 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&lockspaces_mutex);
|
||||
@@ -3345,6 +3489,9 @@ static int work_init_vg(struct action *act)
|
||||
rv = lm_init_vg_sanlock(ls_name, act->vg_name, act->flags, act->vg_args);
|
||||
else if (act->lm_type == LD_LM_DLM)
|
||||
rv = lm_init_vg_dlm(ls_name, act->vg_name, act->flags, act->vg_args);
|
||||
else if (act->lm_type == LD_LM_IDM)
|
||||
/* Non't do anything for IDM when initialize VG */
|
||||
rv = 0;
|
||||
else
|
||||
rv = -EINVAL;
|
||||
|
||||
@@ -3448,6 +3595,8 @@ static int work_init_lv(struct action *act)
|
||||
|
||||
} else if (act->lm_type == LD_LM_DLM) {
|
||||
return 0;
|
||||
} else if (act->lm_type == LD_LM_IDM) {
|
||||
return 0;
|
||||
} else {
|
||||
log_error("init_lv ls_name %s bad lm_type %d", ls_name, act->lm_type);
|
||||
return -EINVAL;
|
||||
@@ -3511,20 +3660,29 @@ static void *worker_thread_main(void *arg_in)
|
||||
if (act->op == LD_OP_RUNNING_LM) {
|
||||
int run_sanlock = lm_is_running_sanlock();
|
||||
int run_dlm = lm_is_running_dlm();
|
||||
int run_idm = lm_is_running_idm();
|
||||
|
||||
if (daemon_test) {
|
||||
run_sanlock = gl_use_sanlock;
|
||||
run_dlm = gl_use_dlm;
|
||||
run_idm = gl_use_idm;
|
||||
}
|
||||
|
||||
if (run_sanlock && run_dlm)
|
||||
/*
|
||||
* It's not possible to enable multiple locking schemes
|
||||
* for global lock, otherwise, it must be conflict and
|
||||
* reports it!
|
||||
*/
|
||||
if ((run_sanlock + run_dlm + run_idm) >= 2)
|
||||
act->result = -EXFULL;
|
||||
else if (!run_sanlock && !run_dlm)
|
||||
else if (!run_sanlock && !run_dlm && !run_idm)
|
||||
act->result = -ENOLCK;
|
||||
else if (run_sanlock)
|
||||
act->result = LD_LM_SANLOCK;
|
||||
else if (run_dlm)
|
||||
act->result = LD_LM_DLM;
|
||||
else if (run_idm)
|
||||
act->result = LD_LM_IDM;
|
||||
add_client_result(act);
|
||||
|
||||
} else if ((act->op == LD_OP_LOCK) && (act->flags & LD_AF_SEARCH_LS)) {
|
||||
@@ -3812,6 +3970,9 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
} else if (gl_use_dlm) {
|
||||
if (!gl_lsname_dlm[0])
|
||||
strcat(result_flags, "NO_GL_LS,");
|
||||
} else if (gl_use_idm) {
|
||||
if (!gl_lsname_idm[0])
|
||||
strcat(result_flags, "NO_GL_LS,");
|
||||
} else {
|
||||
int found_lm = 0;
|
||||
|
||||
@@ -3819,6 +3980,8 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
found_lm++;
|
||||
if (lm_support_sanlock() && lm_is_running_sanlock())
|
||||
found_lm++;
|
||||
if (lm_support_idm() && lm_is_running_idm())
|
||||
found_lm++;
|
||||
|
||||
if (!found_lm)
|
||||
strcat(result_flags, "NO_GL_LS,NO_LM");
|
||||
@@ -3994,11 +4157,13 @@ static int add_lock_action(struct action *act)
|
||||
if (gl_use_sanlock && (act->op == LD_OP_ENABLE || act->op == LD_OP_DISABLE)) {
|
||||
vg_ls_name(act->vg_name, ls_name);
|
||||
} else {
|
||||
if (!gl_use_dlm && !gl_use_sanlock) {
|
||||
if (!gl_use_dlm && !gl_use_sanlock && !gl_use_idm) {
|
||||
if (lm_is_running_dlm())
|
||||
gl_use_dlm = 1;
|
||||
else if (lm_is_running_sanlock())
|
||||
gl_use_sanlock = 1;
|
||||
else if (lm_is_running_idm())
|
||||
gl_use_idm = 1;
|
||||
}
|
||||
gl_ls_name(ls_name);
|
||||
}
|
||||
@@ -4046,6 +4211,17 @@ static int add_lock_action(struct action *act)
|
||||
add_dlm_global_lockspace(NULL);
|
||||
goto retry;
|
||||
|
||||
} else if (act->op == LD_OP_LOCK && act->rt == LD_RT_GL && act->mode != LD_LK_UN && gl_use_idm) {
|
||||
/*
|
||||
* Automatically start the idm global lockspace when
|
||||
* a command tries to acquire the global lock.
|
||||
*/
|
||||
log_debug("lockspace \"%s\" not found for idm gl, adding...", ls_name);
|
||||
act->flags |= LD_AF_SEARCH_LS;
|
||||
act->flags |= LD_AF_WAIT_STARTING;
|
||||
add_idm_global_lockspace(NULL);
|
||||
goto retry;
|
||||
|
||||
} else if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN) {
|
||||
log_debug("lockspace \"%s\" not found for unlock ignored", ls_name);
|
||||
return -ENOLS;
|
||||
@@ -4266,6 +4442,8 @@ static int str_to_lm(const char *str)
|
||||
return LD_LM_SANLOCK;
|
||||
if (!strcmp(str, "dlm"))
|
||||
return LD_LM_DLM;
|
||||
if (!strcmp(str, "idm"))
|
||||
return LD_LM_IDM;
|
||||
return -2;
|
||||
}
|
||||
|
||||
@@ -4601,12 +4779,14 @@ static void client_recv_action(struct client *cl)
|
||||
const char *vg_sysid;
|
||||
const char *path;
|
||||
const char *str;
|
||||
struct pvs pvs;
|
||||
char buf[17]; /* "path[%d]\0", %d outputs signed integer so max to 10 bytes */
|
||||
int64_t val;
|
||||
uint32_t opts = 0;
|
||||
int result = 0;
|
||||
int cl_pid;
|
||||
int op, rt, lm, mode;
|
||||
int rv;
|
||||
int rv, i;
|
||||
|
||||
buffer_init(&req.buffer);
|
||||
|
||||
@@ -4695,11 +4875,13 @@ static void client_recv_action(struct client *cl)
|
||||
if (!cl->name[0] && cl_name)
|
||||
strncpy(cl->name, cl_name, MAX_NAME);
|
||||
|
||||
if (!gl_use_dlm && !gl_use_sanlock && (lm > 0)) {
|
||||
if (!gl_use_dlm && !gl_use_sanlock && !gl_use_idm && (lm > 0)) {
|
||||
if (lm == LD_LM_DLM && lm_support_dlm())
|
||||
gl_use_dlm = 1;
|
||||
else if (lm == LD_LM_SANLOCK && lm_support_sanlock())
|
||||
gl_use_sanlock = 1;
|
||||
else if (lm == LD_LM_IDM && lm_support_idm())
|
||||
gl_use_idm = 1;
|
||||
|
||||
log_debug("set gl_use_%s", lm_str(lm));
|
||||
}
|
||||
@@ -4756,6 +4938,40 @@ static void client_recv_action(struct client *cl)
|
||||
if (val)
|
||||
act->host_id = val;
|
||||
|
||||
/* Create PV list for idm */
|
||||
if (lm == LD_LM_IDM) {
|
||||
memset(&pvs, 0x0, sizeof(pvs));
|
||||
|
||||
pvs.num = daemon_request_int(req, "path_num", 0);
|
||||
log_error("pvs_num = %d", pvs.num);
|
||||
|
||||
if (!pvs.num)
|
||||
goto skip_pvs_path;
|
||||
|
||||
/* Receive the pv list which is transferred from LVM command */
|
||||
if (!alloc_pvs_path(&pvs, pvs.num)) {
|
||||
log_error("fail to allocate pvs path");
|
||||
rv = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < pvs.num; i++) {
|
||||
snprintf(buf, sizeof(buf), "path[%d]", i);
|
||||
pvs.path[i] = (char *)daemon_request_str(req, buf, NULL);
|
||||
}
|
||||
|
||||
if (!alloc_and_copy_pvs_path(&act->pvs, &pvs)) {
|
||||
log_error("fail to allocate pvs path");
|
||||
rv = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (pvs.path)
|
||||
free(pvs.path);
|
||||
pvs.path = NULL;
|
||||
}
|
||||
|
||||
skip_pvs_path:
|
||||
act->max_retries = daemon_request_int(req, "max_retries", DEFAULT_MAX_RETRIES);
|
||||
|
||||
dm_config_destroy(req.cft);
|
||||
@@ -4777,6 +4993,12 @@ static void client_recv_action(struct client *cl)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lm == LD_LM_IDM && !lm_support_idm()) {
|
||||
log_debug("idm not supported");
|
||||
rv = -EPROTONOSUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (act->op == LD_OP_LOCK && act->mode != LD_LK_UN)
|
||||
cl->lock_ops = 1;
|
||||
|
||||
@@ -4966,7 +5188,7 @@ static void *client_thread_main(void *arg_in)
|
||||
}
|
||||
out:
|
||||
if (adopt_opt && lock_acquire_written)
|
||||
unlink(adopt_file);
|
||||
(void) unlink(adopt_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -5375,6 +5597,7 @@ static void adopt_locks(void)
|
||||
}
|
||||
|
||||
list_del(&ls->list);
|
||||
free_pvs_path(&ls->pvs);
|
||||
free(ls);
|
||||
}
|
||||
|
||||
@@ -5415,6 +5638,7 @@ static void adopt_locks(void)
|
||||
if (rv < 0) {
|
||||
log_error("Failed to create lockspace thread for VG %s", ls->vg_name);
|
||||
list_del(&ls->list);
|
||||
free_pvs_path(&ls->pvs);
|
||||
free(ls);
|
||||
free_action(act);
|
||||
count_start_fail++;
|
||||
@@ -5738,13 +5962,13 @@ static void adopt_locks(void)
|
||||
if (count_start_fail || count_adopt_fail)
|
||||
goto fail;
|
||||
|
||||
unlink(adopt_file);
|
||||
(void) unlink(adopt_file);
|
||||
write_adopt_file();
|
||||
log_debug("adopt_locks done");
|
||||
return;
|
||||
|
||||
fail:
|
||||
unlink(adopt_file);
|
||||
(void) unlink(adopt_file);
|
||||
log_error("adopt_locks failed, reset host");
|
||||
}
|
||||
|
||||
@@ -5857,6 +6081,7 @@ static int main_loop(daemon_state *ds_arg)
|
||||
}
|
||||
|
||||
strcpy(gl_lsname_dlm, S_NAME_GL_DLM);
|
||||
strcpy(gl_lsname_idm, S_NAME_GL_IDM);
|
||||
|
||||
INIT_LIST_HEAD(&lockspaces);
|
||||
pthread_mutex_init(&lockspaces_mutex, NULL);
|
||||
@@ -6110,6 +6335,8 @@ int main(int argc, char *argv[])
|
||||
gl_use_dlm = 1;
|
||||
else if (lm == LD_LM_SANLOCK && lm_support_sanlock())
|
||||
gl_use_sanlock = 1;
|
||||
else if (lm == LD_LM_IDM && lm_support_idm())
|
||||
gl_use_idm = 1;
|
||||
else {
|
||||
fprintf(stderr, "invalid gl-type option\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
@@ -327,8 +327,7 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
|
||||
log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
|
||||
}
|
||||
out:
|
||||
if (rdd->vb)
|
||||
free(rdd->vb);
|
||||
free(rdd->vb);
|
||||
|
||||
memset(rdd, 0, sizeof(struct rd_dlm));
|
||||
r->lm_init = 0;
|
||||
|
||||
837
daemons/lvmlockd/lvmlockd-idm.c
Normal file
837
daemons/lvmlockd/lvmlockd-idm.c
Normal file
@@ -0,0 +1,837 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Seagate Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 500 /* pthread */
|
||||
#define _ISOC99_SOURCE
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "daemon-server.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
#include "daemons/lvmlockd/lvmlockd-client.h"
|
||||
|
||||
#include "ilm.h"
|
||||
|
||||
#include <blkid/blkid.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <regex.h>
|
||||
#include <stddef.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <time.h>
|
||||
|
||||
#define IDM_TIMEOUT 60000 /* unit: millisecond, 60 seconds */
|
||||
|
||||
/*
|
||||
* Each lockspace thread has its own In-Drive Mutex (IDM) lock manager's
|
||||
* connection. After established socket connection, the lockspace has
|
||||
* been created in IDM lock manager and afterwards use the socket file
|
||||
* descriptor to send any requests for lock related operations.
|
||||
*/
|
||||
|
||||
struct lm_idm {
|
||||
int sock; /* IDM lock manager connection */
|
||||
};
|
||||
|
||||
struct rd_idm {
|
||||
struct idm_lock_id id;
|
||||
struct idm_lock_op op;
|
||||
uint64_t vb_timestamp;
|
||||
struct val_blk *vb;
|
||||
};
|
||||
|
||||
int lm_data_size_idm(void)
|
||||
{
|
||||
return sizeof(struct rd_idm);
|
||||
}
|
||||
|
||||
static uint64_t read_utc_us(void)
|
||||
{
|
||||
struct timespec cur_time;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &cur_time);
|
||||
|
||||
/*
|
||||
* Convert to microseconds unit. IDM reserves the MSB in 8 bytes
|
||||
* and the low 56 bits are used for timestamp; 56 bits can support
|
||||
* calendar year to 2284, so it has 260 years for overflow. Thus it
|
||||
* is quite safe for overflow issue when wrote this code.
|
||||
*/
|
||||
return cur_time.tv_sec * 1000000 + cur_time.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
static int uuid_read_format(char *uuid_str, const char *buffer)
|
||||
{
|
||||
int out = 0;
|
||||
|
||||
/* just strip out any dashes */
|
||||
while (*buffer) {
|
||||
|
||||
if (*buffer == '-') {
|
||||
buffer++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (out >= 32) {
|
||||
log_error("Too many characters to be uuid.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uuid_str[out++] = *buffer;
|
||||
buffer++;
|
||||
}
|
||||
|
||||
if (out != 32) {
|
||||
log_error("Couldn't read uuid: incorrect number of "
|
||||
"characters.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SYSFS_ROOT "/sys"
|
||||
#define BUS_SCSI_DEVS "/bus/scsi/devices"
|
||||
|
||||
static struct idm_lock_op glb_lock_op;
|
||||
|
||||
static void lm_idm_free_dir_list(struct dirent **dir_list, int dir_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dir_num; ++i)
|
||||
free(dir_list[i]);
|
||||
free(dir_list);
|
||||
}
|
||||
|
||||
static int lm_idm_scsi_directory_select(const struct dirent *s)
|
||||
{
|
||||
regex_t regex;
|
||||
int ret;
|
||||
|
||||
/* Only select directory with the format x:x:x:x */
|
||||
ret = regcomp(®ex, "^[0-9]+:[0-9]+:[0-9]+:[0-9]+$", REG_EXTENDED);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
ret = regexec(®ex, s->d_name, 0, NULL, 0);
|
||||
if (!ret) {
|
||||
regfree(®ex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
regfree(®ex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm_idm_scsi_find_block_dirctory(const char *block_path)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
if ((stat(block_path, &stats) >= 0) && S_ISDIR(stats.st_mode))
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int lm_idm_scsi_block_node_select(const struct dirent *s)
|
||||
{
|
||||
if (DT_LNK != s->d_type && DT_DIR != s->d_type)
|
||||
return 0;
|
||||
|
||||
if (DT_DIR == s->d_type) {
|
||||
/* Skip this directory: '.' and parent: '..' */
|
||||
if (!strcmp(s->d_name, ".") || !strcmp(s->d_name, ".."))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lm_idm_scsi_find_block_node(const char *blk_path, char **blk_dev)
|
||||
{
|
||||
struct dirent **dir_list;
|
||||
int dir_num;
|
||||
|
||||
dir_num = scandir(blk_path, &dir_list, lm_idm_scsi_block_node_select, NULL);
|
||||
if (dir_num < 0) {
|
||||
log_error("Cannot find valid directory entry in %s", blk_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Should have only one block name under the path, if the dir_num is
|
||||
* not 1 (e.g. 0 or any number bigger than 1), it must be wrong and
|
||||
* should never happen.
|
||||
*/
|
||||
if (dir_num == 1)
|
||||
*blk_dev = strdup(dir_list[0]->d_name);
|
||||
else
|
||||
*blk_dev = NULL;
|
||||
|
||||
lm_idm_free_dir_list(dir_list, dir_num);
|
||||
|
||||
if (!*blk_dev)
|
||||
return -1;
|
||||
|
||||
return dir_num;
|
||||
}
|
||||
|
||||
static int lm_idm_scsi_search_propeller_partition(char *dev)
|
||||
{
|
||||
int i, nparts;
|
||||
blkid_probe pr;
|
||||
blkid_partlist ls;
|
||||
int found = -1;
|
||||
|
||||
pr = blkid_new_probe_from_filename(dev);
|
||||
if (!pr) {
|
||||
log_error("%s: failed to create a new libblkid probe", dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Binary interface */
|
||||
ls = blkid_probe_get_partitions(pr);
|
||||
if (!ls) {
|
||||
log_error("%s: failed to read partitions", dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* List partitions */
|
||||
nparts = blkid_partlist_numof_partitions(ls);
|
||||
if (!nparts)
|
||||
goto done;
|
||||
|
||||
for (i = 0; i < nparts; i++) {
|
||||
const char *p;
|
||||
blkid_partition par = blkid_partlist_get_partition(ls, i);
|
||||
|
||||
p = blkid_partition_get_name(par);
|
||||
if (p) {
|
||||
log_debug("partition name='%s'", p);
|
||||
|
||||
if (!strcmp(p, "propeller"))
|
||||
found = blkid_partition_get_partno(par);
|
||||
}
|
||||
|
||||
if (found >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
blkid_free_probe(pr);
|
||||
return found;
|
||||
}
|
||||
|
||||
static char *lm_idm_scsi_get_block_device_node(const char *scsi_path)
|
||||
{
|
||||
char *blk_path = NULL;
|
||||
char *blk_dev = NULL;
|
||||
char *dev_node = NULL;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Locate the "block" directory, such like:
|
||||
* /sys/bus/scsi/devices/1:0:0:0/block
|
||||
*/
|
||||
ret = asprintf(&blk_path, "%s/%s", scsi_path, "block");
|
||||
if (ret < 0) {
|
||||
log_error("Fail to allocate block path for %s", scsi_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = lm_idm_scsi_find_block_dirctory(blk_path);
|
||||
if (ret < 0) {
|
||||
log_error("Fail to find block path %s", blk_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate the block device name, such like:
|
||||
* /sys/bus/scsi/devices/1:0:0:0/block/sdb
|
||||
*
|
||||
* After return from this function and if it makes success,
|
||||
* the global variable "blk_dev" points to the block device
|
||||
* name, in this example it points to string "sdb".
|
||||
*/
|
||||
ret = lm_idm_scsi_find_block_node(blk_path, &blk_dev);
|
||||
if (ret < 0) {
|
||||
log_error("Fail to find block node");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = asprintf(&dev_node, "/dev/%s", blk_dev);
|
||||
if (ret < 0) {
|
||||
log_error("Fail to allocate memory for blk node path");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = lm_idm_scsi_search_propeller_partition(dev_node);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
free(blk_path);
|
||||
free(blk_dev);
|
||||
return dev_node;
|
||||
|
||||
fail:
|
||||
free(blk_path);
|
||||
free(blk_dev);
|
||||
free(dev_node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int lm_idm_get_gl_lock_pv_list(void)
|
||||
{
|
||||
struct dirent **dir_list;
|
||||
char scsi_bus_path[PATH_MAX];
|
||||
char *drive_path;
|
||||
int i, dir_num, ret;
|
||||
|
||||
if (glb_lock_op.drive_num)
|
||||
return 0;
|
||||
|
||||
snprintf(scsi_bus_path, sizeof(scsi_bus_path), "%s%s",
|
||||
SYSFS_ROOT, BUS_SCSI_DEVS);
|
||||
|
||||
dir_num = scandir(scsi_bus_path, &dir_list,
|
||||
lm_idm_scsi_directory_select, NULL);
|
||||
if (dir_num < 0) { /* scsi mid level may not be loaded */
|
||||
log_error("Attached devices: none");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < dir_num; i++) {
|
||||
char *scsi_path;
|
||||
|
||||
ret = asprintf(&scsi_path, "%s/%s", scsi_bus_path,
|
||||
dir_list[i]->d_name);
|
||||
if (ret < 0) {
|
||||
log_error("Fail to allocate memory for scsi directory");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (glb_lock_op.drive_num >= ILM_DRIVE_MAX_NUM) {
|
||||
log_error("Global lock: drive number %d exceeds limitation (%d) ?!",
|
||||
glb_lock_op.drive_num, ILM_DRIVE_MAX_NUM);
|
||||
free(scsi_path);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
drive_path = lm_idm_scsi_get_block_device_node(scsi_path);
|
||||
if (!drive_path) {
|
||||
free(scsi_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
glb_lock_op.drives[glb_lock_op.drive_num] = drive_path;
|
||||
glb_lock_op.drive_num++;
|
||||
|
||||
free(scsi_path);
|
||||
}
|
||||
|
||||
lm_idm_free_dir_list(dir_list, dir_num);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
lm_idm_free_dir_list(dir_list, dir_num);
|
||||
|
||||
for (i = 0; i < glb_lock_op.drive_num; i++) {
|
||||
if (glb_lock_op.drives[i]) {
|
||||
free(glb_lock_op.drives[i]);
|
||||
glb_lock_op.drives[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void lm_idm_update_vb_timestamp(uint64_t *vb_timestamp)
|
||||
{
|
||||
uint64_t utc_us = read_utc_us();
|
||||
|
||||
/*
|
||||
* It's possible that the multiple nodes have no clock
|
||||
* synchronization with microsecond prcision and the time
|
||||
* is going backward. For this case, simply increment the
|
||||
* existing timestamp and write out to drive.
|
||||
*/
|
||||
if (*vb_timestamp >= utc_us)
|
||||
(*vb_timestamp)++;
|
||||
else
|
||||
*vb_timestamp = utc_us;
|
||||
}
|
||||
|
||||
int lm_prepare_lockspace_idm(struct lockspace *ls)
|
||||
{
|
||||
struct lm_idm *lm = NULL;
|
||||
|
||||
lm = malloc(sizeof(struct lm_idm));
|
||||
if (!lm) {
|
||||
log_error("S %s prepare_lockspace_idm fail to allocate lm_idm for %s",
|
||||
ls->name, ls->vg_name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(lm, 0x0, sizeof(struct lm_idm));
|
||||
|
||||
ls->lm_data = lm;
|
||||
log_debug("S %s prepare_lockspace_idm done", ls->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
|
||||
{
|
||||
char killpath[IDM_FAILURE_PATH_LEN];
|
||||
char killargs[IDM_FAILURE_ARGS_LEN];
|
||||
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
|
||||
int rv;
|
||||
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(ls->name, S_NAME_GL_IDM)) {
|
||||
/*
|
||||
* Prepare the pv list for global lock, if the drive contains
|
||||
* "propeller" partition, then this drive will be considered
|
||||
* as a member of pv list.
|
||||
*/
|
||||
rv = lm_idm_get_gl_lock_pv_list();
|
||||
if (rv < 0) {
|
||||
log_error("S %s add_lockspace_idm fail to get pv list for glb lock",
|
||||
ls->name);
|
||||
return -EIO;
|
||||
} else {
|
||||
log_error("S %s add_lockspace_idm get pv list for glb lock",
|
||||
ls->name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the execution path for command "lvmlockctl" by using the
|
||||
* path to the lvm binary and appending "lockctl".
|
||||
*/
|
||||
memset(killpath, 0, sizeof(killpath));
|
||||
snprintf(killpath, IDM_FAILURE_PATH_LEN, "%slockctl", LVM_PATH);
|
||||
|
||||
/* Pass the argument "--kill vg_name" for killpath */
|
||||
memset(killargs, 0, sizeof(killargs));
|
||||
snprintf(killargs, IDM_FAILURE_ARGS_LEN, "--kill %s", ls->vg_name);
|
||||
|
||||
/* Connect with IDM lock manager per every lockspace. */
|
||||
rv = ilm_connect(&lmi->sock);
|
||||
if (rv < 0) {
|
||||
log_error("S %s add_lockspace_idm fail to connect the lock manager %d",
|
||||
ls->name, lmi->sock);
|
||||
lmi->sock = 0;
|
||||
rv = -EMANAGER;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rv = ilm_set_killpath(lmi->sock, killpath, killargs);
|
||||
if (rv < 0) {
|
||||
log_error("S %s add_lockspace_idm fail to set kill path %d",
|
||||
ls->name, rv);
|
||||
rv = -EMANAGER;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
log_debug("S %s add_lockspace_idm kill path is: \"%s %s\"",
|
||||
ls->name, killpath, killargs);
|
||||
|
||||
log_debug("S %s add_lockspace_idm done", ls->name);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (lmi && lmi->sock)
|
||||
close(lmi->sock);
|
||||
if (lmi)
|
||||
free(lmi);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
|
||||
{
|
||||
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
|
||||
int i, rv = 0;
|
||||
|
||||
if (daemon_test)
|
||||
goto out;
|
||||
|
||||
rv = ilm_disconnect(lmi->sock);
|
||||
if (rv < 0)
|
||||
log_error("S %s rem_lockspace_idm error %d", ls->name, rv);
|
||||
|
||||
/* Release pv list for global lock */
|
||||
if (!strcmp(ls->name, "lvm_global")) {
|
||||
for (i = 0; i < glb_lock_op.drive_num; i++) {
|
||||
if (glb_lock_op.drives[i]) {
|
||||
free(glb_lock_op.drives[i]);
|
||||
glb_lock_op.drives[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free(lmi);
|
||||
ls->lm_data = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
|
||||
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
|
||||
rdi->vb = zalloc(sizeof(struct val_blk));
|
||||
if (!rdi->vb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lm_rem_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
|
||||
if (rdi->vb)
|
||||
free(rdi->vb);
|
||||
|
||||
memset(rdi, 0, sizeof(struct rd_idm));
|
||||
r->lm_init = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int to_idm_mode(int ld_mode)
|
||||
{
|
||||
switch (ld_mode) {
|
||||
case LD_LK_EX:
|
||||
return IDM_MODE_EXCLUSIVE;
|
||||
case LD_LK_SH:
|
||||
return IDM_MODE_SHAREABLE;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
|
||||
int adopt)
|
||||
{
|
||||
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
char **drive_path = NULL;
|
||||
uint64_t timestamp;
|
||||
int reset_vb = 0;
|
||||
int rv, i;
|
||||
|
||||
if (!r->lm_init) {
|
||||
rv = lm_add_resource_idm(ls, r);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
r->lm_init = 1;
|
||||
}
|
||||
|
||||
rdi->op.mode = to_idm_mode(ld_mode);
|
||||
if (rv < 0) {
|
||||
log_error("lock_idm invalid mode %d", ld_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log_debug("S %s R %s lock_idm", ls->name, r->name);
|
||||
|
||||
if (daemon_test) {
|
||||
if (rdi->vb) {
|
||||
vb_out->version = le16_to_cpu(rdi->vb->version);
|
||||
vb_out->flags = le16_to_cpu(rdi->vb->flags);
|
||||
vb_out->r_version = le32_to_cpu(rdi->vb->r_version);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdi->op.timeout = IDM_TIMEOUT;
|
||||
|
||||
/*
|
||||
* Generate the UUID string, for RT_VG, it only needs to generate
|
||||
* UUID string for VG level, for RT_LV, it needs to generate
|
||||
* UUID strings for both VG and LV levels. At the end, these IDs
|
||||
* are used as identifier for IDM in drive firmware.
|
||||
*/
|
||||
if (r->type == LD_RT_VG || r->type == LD_RT_LV)
|
||||
log_debug("S %s R %s VG uuid %s", ls->name, r->name, ls->vg_uuid);
|
||||
if (r->type == LD_RT_LV)
|
||||
log_debug("S %s R %s LV uuid %s", ls->name, r->name, lv_uuid);
|
||||
|
||||
memset(&rdi->id, 0x0, sizeof(struct idm_lock_id));
|
||||
if (r->type == LD_RT_VG) {
|
||||
uuid_read_format(rdi->id.vg_uuid, ls->vg_uuid);
|
||||
} else if (r->type == LD_RT_LV) {
|
||||
uuid_read_format(rdi->id.vg_uuid, ls->vg_uuid);
|
||||
uuid_read_format(rdi->id.lv_uuid, lv_uuid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Establish the drive path list for lock, since different lock type
|
||||
* has different drive list; the GL lock uses the global pv list,
|
||||
* the VG lock uses the pv list spanned for the whole volume group,
|
||||
* the LV lock uses the pv list for the logical volume.
|
||||
*/
|
||||
switch (r->type) {
|
||||
case LD_RT_GL:
|
||||
drive_path = glb_lock_op.drives;
|
||||
rdi->op.drive_num = glb_lock_op.drive_num;
|
||||
break;
|
||||
case LD_RT_VG:
|
||||
drive_path = (char **)ls->pvs.path;
|
||||
rdi->op.drive_num = ls->pvs.num;
|
||||
break;
|
||||
case LD_RT_LV:
|
||||
drive_path = (char **)pvs->path;
|
||||
rdi->op.drive_num = pvs->num;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!drive_path) {
|
||||
log_error("S %s R %s cannot find the valid drive path array",
|
||||
ls->name, r->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (rdi->op.drive_num >= ILM_DRIVE_MAX_NUM) {
|
||||
log_error("S %s R %s exceeds limitation for drive path array",
|
||||
ls->name, r->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < rdi->op.drive_num; i++)
|
||||
rdi->op.drives[i] = drive_path[i];
|
||||
|
||||
log_debug("S %s R %s mode %d drive_num %d timeout %d",
|
||||
ls->name, r->name, rdi->op.mode,
|
||||
rdi->op.drive_num, rdi->op.timeout);
|
||||
|
||||
for (i = 0; i < rdi->op.drive_num; i++)
|
||||
log_debug("S %s R %s drive path[%d] %s",
|
||||
ls->name, r->name, i, rdi->op.drives[i]);
|
||||
|
||||
rv = ilm_lock(lmi->sock, &rdi->id, &rdi->op);
|
||||
if (rv < 0) {
|
||||
log_debug("S %s R %s lock_idm acquire mode %d rv %d",
|
||||
ls->name, r->name, ld_mode, rv);
|
||||
return -ELOCKIO;
|
||||
}
|
||||
|
||||
if (rdi->vb) {
|
||||
rv = ilm_read_lvb(lmi->sock, &rdi->id, (char *)×tamp,
|
||||
sizeof(uint64_t));
|
||||
|
||||
/*
|
||||
* If fail to read value block, which might be caused by drive
|
||||
* failure, notify up layer to invalidate metadata.
|
||||
*/
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s lock_idm get_lvb error %d",
|
||||
ls->name, r->name, rv);
|
||||
reset_vb = 1;
|
||||
|
||||
/* Reset timestamp */
|
||||
rdi->vb_timestamp = 0;
|
||||
|
||||
/*
|
||||
* If the cached timestamp mismatches with the stored value
|
||||
* in the IDM, this means another host has updated timestamp
|
||||
* for the new VB. Let's reset VB and notify up layer to
|
||||
* invalidate metadata.
|
||||
*/
|
||||
} else if (rdi->vb_timestamp != timestamp) {
|
||||
log_debug("S %s R %s lock_idm get lvb timestamp %lu:%lu",
|
||||
ls->name, r->name, rdi->vb_timestamp,
|
||||
timestamp);
|
||||
|
||||
rdi->vb_timestamp = timestamp;
|
||||
reset_vb = 1;
|
||||
}
|
||||
|
||||
if (reset_vb == 1) {
|
||||
memset(rdi->vb, 0, sizeof(struct val_blk));
|
||||
memset(vb_out, 0, sizeof(struct val_blk));
|
||||
|
||||
/*
|
||||
* The lock is still acquired, but the vb values has
|
||||
* been invalidated.
|
||||
*/
|
||||
rv = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Otherwise, copy the cached VB to up layer */
|
||||
memcpy(vb_out, rdi->vb, sizeof(struct val_blk));
|
||||
}
|
||||
|
||||
out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
int lm_convert_idm(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version)
|
||||
{
|
||||
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
int mode, rv;
|
||||
|
||||
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
|
||||
if (!rdi->vb->version) {
|
||||
/* first time vb has been written */
|
||||
rdi->vb->version = VAL_BLK_VERSION;
|
||||
}
|
||||
rdi->vb->r_version = r_version;
|
||||
|
||||
log_debug("S %s R %s convert_idm set r_version %u",
|
||||
ls->name, r->name, r_version);
|
||||
|
||||
lm_idm_update_vb_timestamp(&rdi->vb_timestamp);
|
||||
log_debug("S %s R %s convert_idm vb %x %x %u timestamp %lu",
|
||||
ls->name, r->name, rdi->vb->version, rdi->vb->flags,
|
||||
rdi->vb->r_version, rdi->vb_timestamp);
|
||||
}
|
||||
|
||||
mode = to_idm_mode(ld_mode);
|
||||
if (mode < 0) {
|
||||
log_error("S %s R %s convert_idm invalid mode %d",
|
||||
ls->name, r->name, ld_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log_debug("S %s R %s convert_idm", ls->name, r->name);
|
||||
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
|
||||
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
|
||||
rv = ilm_write_lvb(lmi->sock, &rdi->id,
|
||||
(char *)rdi->vb_timestamp, sizeof(uint64_t));
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s convert_idm write lvb error %d",
|
||||
ls->name, r->name, rv);
|
||||
return -ELMERR;
|
||||
}
|
||||
}
|
||||
|
||||
rv = ilm_convert(lmi->sock, &rdi->id, mode);
|
||||
if (rv < 0)
|
||||
log_error("S %s R %s convert_idm convert error %d",
|
||||
ls->name, r->name, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int lm_unlock_idm(struct lockspace *ls, struct resource *r,
|
||||
uint32_t r_version, uint32_t lmu_flags)
|
||||
{
|
||||
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
int rv;
|
||||
|
||||
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
|
||||
if (!rdi->vb->version) {
|
||||
/* first time vb has been written */
|
||||
rdi->vb->version = VAL_BLK_VERSION;
|
||||
}
|
||||
if (r_version)
|
||||
rdi->vb->r_version = r_version;
|
||||
|
||||
lm_idm_update_vb_timestamp(&rdi->vb_timestamp);
|
||||
log_debug("S %s R %s unlock_idm vb %x %x %u timestamp %lu",
|
||||
ls->name, r->name, rdi->vb->version, rdi->vb->flags,
|
||||
rdi->vb->r_version, rdi->vb_timestamp);
|
||||
}
|
||||
|
||||
log_debug("S %s R %s unlock_idm", ls->name, r->name);
|
||||
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
|
||||
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
|
||||
rv = ilm_write_lvb(lmi->sock, &rdi->id,
|
||||
(char *)&rdi->vb_timestamp, sizeof(uint64_t));
|
||||
if (rv < 0) {
|
||||
log_error("S %s R %s unlock_idm set_lvb error %d",
|
||||
ls->name, r->name, rv);
|
||||
return -ELMERR;
|
||||
}
|
||||
}
|
||||
|
||||
rv = ilm_unlock(lmi->sock, &rdi->id);
|
||||
if (rv < 0)
|
||||
log_error("S %s R %s unlock_idm error %d", ls->name, r->name, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int lm_hosts_idm(struct lockspace *ls, int notify)
|
||||
{
|
||||
struct resource *r;
|
||||
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
|
||||
struct rd_idm *rdi;
|
||||
int count, self, found_others = 0;
|
||||
int rv;
|
||||
|
||||
list_for_each_entry(r, &ls->resources, list) {
|
||||
if (!r->lm_init)
|
||||
continue;
|
||||
|
||||
rdi = (struct rd_idm *)r->lm_data;
|
||||
|
||||
rv = ilm_get_host_count(lmi->sock, &rdi->id, &rdi->op,
|
||||
&count, &self);
|
||||
if (rv < 0) {
|
||||
log_error("S %s lm_hosts_idm error %d", ls->name, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Fixup: need to reduce self count */
|
||||
if (count > found_others)
|
||||
found_others = count;
|
||||
}
|
||||
|
||||
return found_others;
|
||||
}
|
||||
|
||||
int lm_get_lockspaces_idm(struct list_head *ls_rejoin)
|
||||
{
|
||||
/* TODO: Need to add support for adoption. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lm_is_running_idm(void)
|
||||
{
|
||||
int sock, rv;
|
||||
|
||||
if (daemon_test)
|
||||
return gl_use_idm;
|
||||
|
||||
rv = ilm_connect(&sock);
|
||||
if (rv < 0) {
|
||||
log_error("Fail to connect seagate IDM lock manager %d", rv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ilm_disconnect(sock);
|
||||
return 1;
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
#define R_NAME_GL "GLLK"
|
||||
#define R_NAME_VG "VGLK"
|
||||
#define S_NAME_GL_DLM "lvm_global"
|
||||
#define S_NAME_GL_IDM "lvm_global"
|
||||
#define LVM_LS_PREFIX "lvm_" /* ls name is prefix + vg_name */
|
||||
/* global lockspace name for sanlock is a vg name */
|
||||
|
||||
@@ -29,6 +30,7 @@ enum {
|
||||
LD_LM_UNUSED = 1, /* place holder so values match lib/locking/lvmlockd.h */
|
||||
LD_LM_DLM = 2,
|
||||
LD_LM_SANLOCK = 3,
|
||||
LD_LM_IDM = 4,
|
||||
};
|
||||
|
||||
/* operation types */
|
||||
@@ -118,6 +120,11 @@ struct client {
|
||||
*/
|
||||
#define DEFAULT_MAX_RETRIES 4
|
||||
|
||||
struct pvs {
|
||||
char **path;
|
||||
int num;
|
||||
};
|
||||
|
||||
struct action {
|
||||
struct list_head list;
|
||||
uint32_t client_id;
|
||||
@@ -140,6 +147,7 @@ struct action {
|
||||
char vg_args[MAX_ARGS+1];
|
||||
char lv_args[MAX_ARGS+1];
|
||||
char vg_sysid[MAX_NAME+1];
|
||||
struct pvs pvs; /* PV list for idm */
|
||||
};
|
||||
|
||||
struct resource {
|
||||
@@ -184,6 +192,7 @@ struct lockspace {
|
||||
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
|
||||
int free_lock_sector_size; /* for sanlock */
|
||||
int free_lock_align_size; /* for sanlock */
|
||||
struct pvs pvs; /* for idm: PV list */
|
||||
|
||||
uint32_t start_client_id; /* client_id that started the lockspace */
|
||||
pthread_t thread; /* makes synchronous lock requests */
|
||||
@@ -325,10 +334,13 @@ static inline int list_empty(const struct list_head *head)
|
||||
EXTERN int gl_type_static;
|
||||
EXTERN int gl_use_dlm;
|
||||
EXTERN int gl_use_sanlock;
|
||||
EXTERN int gl_use_idm;
|
||||
EXTERN int gl_vg_removed;
|
||||
EXTERN char gl_lsname_dlm[MAX_NAME+1];
|
||||
EXTERN char gl_lsname_sanlock[MAX_NAME+1];
|
||||
EXTERN char gl_lsname_idm[MAX_NAME+1];
|
||||
EXTERN int global_dlm_lockspace_exists;
|
||||
EXTERN int global_idm_lockspace_exists;
|
||||
|
||||
EXTERN int daemon_test; /* run as much as possible without a live lock manager */
|
||||
EXTERN int daemon_debug;
|
||||
@@ -619,4 +631,102 @@ static inline int lm_support_sanlock(void)
|
||||
|
||||
#endif /* sanlock support */
|
||||
|
||||
#ifdef LOCKDIDM_SUPPORT
|
||||
|
||||
int lm_data_size_idm(void);
|
||||
int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
||||
int lm_prepare_lockspace_idm(struct lockspace *ls);
|
||||
int lm_add_lockspace_idm(struct lockspace *ls, int adopt);
|
||||
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg);
|
||||
int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
|
||||
int adopt);
|
||||
int lm_convert_idm(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version);
|
||||
int lm_unlock_idm(struct lockspace *ls, struct resource *r,
|
||||
uint32_t r_version, uint32_t lmu_flags);
|
||||
int lm_hosts_idm(struct lockspace *ls, int notify);
|
||||
int lm_get_lockspaces_idm(struct list_head *ls_rejoin);
|
||||
int lm_is_running_idm(void);
|
||||
int lm_rem_resource_idm(struct lockspace *ls, struct resource *r);
|
||||
|
||||
static inline int lm_support_idm(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int lm_data_size_idm(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags,
|
||||
char *vg_args)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_prepare_lockspace_idm(struct lockspace *ls)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
|
||||
int adopt)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_convert_idm(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_unlock_idm(struct lockspace *ls, struct resource *r,
|
||||
uint32_t r_version, uint32_t lmu_flags)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_hosts_idm(struct lockspace *ls, int notify)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_get_lockspaces_idm(struct list_head *ls_rejoin)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_is_running_idm(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lm_rem_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_support_idm(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* Seagate IDM support */
|
||||
|
||||
#endif /* _LVM_LVMLOCKD_INTERNAL_H */
|
||||
|
||||
@@ -1503,8 +1503,7 @@ out:
|
||||
fail:
|
||||
if (lms && lms->sock)
|
||||
close(lms->sock);
|
||||
if (lms)
|
||||
free(lms);
|
||||
free(lms);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1634,8 +1633,7 @@ int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r)
|
||||
|
||||
/* FIXME: assert r->mode == UN or unlock if it's not? */
|
||||
|
||||
if (rds->vb)
|
||||
free(rds->vb);
|
||||
free(rds->vb);
|
||||
|
||||
memset(rds, 0, sizeof(struct rd_sanlock));
|
||||
r->lm_init = 0;
|
||||
|
||||
@@ -19,11 +19,10 @@ SOURCES = lvmpolld-core.c lvmpolld-data-utils.c lvmpolld-cmd-utils.c
|
||||
|
||||
TARGETS = lvmpolld
|
||||
|
||||
.PHONY: install_lvmpolld
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
CFLOW_TARGET := $(TARGETS)
|
||||
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
CFLOW_TARGET = lvmpolld
|
||||
.PHONY: install_lvmpolld
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
|
||||
@@ -92,6 +92,12 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary,
|
||||
if (!add_to_cmd_arr(&cmd_argv, "-An", &i))
|
||||
goto err;
|
||||
|
||||
if (pdlv->devicesfile) {
|
||||
if (!add_to_cmd_arr(&cmd_argv, "--devicesfile", &i) ||
|
||||
!add_to_cmd_arr(&cmd_argv, pdlv->devicesfile, &i))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* terminating NULL */
|
||||
if (!add_to_cmd_arr(&cmd_argv, NULL, &i))
|
||||
goto err;
|
||||
|
||||
@@ -149,7 +149,7 @@ static void _lvmpolld_global_unlock(struct lvmpolld_state *ls)
|
||||
static int _fini(struct daemon_state *s)
|
||||
{
|
||||
int done;
|
||||
const struct timespec t = { .tv_nsec = 250000000 }; /* .25 sec */
|
||||
const struct timespec t = { .tv_nsec = 10000000 }; /* .01 sec */
|
||||
struct lvmpolld_state *ls = s->private;
|
||||
|
||||
DEBUGLOG(s, "fini");
|
||||
@@ -236,9 +236,7 @@ static int poll_for_output(struct lvmpolld_lv *pdlv, struct lvmpolld_thread_data
|
||||
}
|
||||
|
||||
while (1) {
|
||||
do {
|
||||
r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000);
|
||||
} while (r < 0 && errno == EINTR);
|
||||
r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000);
|
||||
|
||||
DEBUGLOG(pdlv->ls, "%s: %s %d", PD_LOG_PREFIX, "poll() returned", r);
|
||||
if (r < 0) {
|
||||
@@ -555,14 +553,15 @@ static struct lvmpolld_lv *construct_pdlv(request req, struct lvmpolld_state *ls
|
||||
const char *interval, const char *id,
|
||||
const char *vgname, const char *lvname,
|
||||
const char *sysdir, enum poll_type type,
|
||||
unsigned abort_polling, unsigned uinterval)
|
||||
unsigned abort_polling, unsigned uinterval,
|
||||
const char *devicesfile)
|
||||
{
|
||||
const char **cmdargv, **cmdenvp;
|
||||
struct lvmpolld_lv *pdlv;
|
||||
unsigned handle_missing_pvs = daemon_request_int(req, LVMPD_PARM_HANDLE_MISSING_PVS, 0);
|
||||
|
||||
pdlv = pdlv_create(ls, id, vgname, lvname, sysdir, type,
|
||||
interval, uinterval, pdst);
|
||||
interval, uinterval, pdst, devicesfile);
|
||||
|
||||
if (!pdlv) {
|
||||
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to create internal LV data structure.");
|
||||
@@ -621,6 +620,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
|
||||
const char *lvname = daemon_request_str(req, LVMPD_PARM_LVNAME, NULL);
|
||||
const char *vgname = daemon_request_str(req, LVMPD_PARM_VGNAME, NULL);
|
||||
const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL);
|
||||
const char *devicesfile = daemon_request_str(req, LVMPD_PARM_DEVICESFILE, NULL);
|
||||
unsigned abort_polling = daemon_request_int(req, LVMPD_PARM_ABORT, 0);
|
||||
|
||||
assert(type < POLL_TYPE_MAX);
|
||||
@@ -680,7 +680,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
|
||||
pdlv->init_rq_count++; /* safe. protected by store lock */
|
||||
} else {
|
||||
pdlv = construct_pdlv(req, ls, pdst, interval, id, vgname,
|
||||
lvname, sysdir, type, abort_polling, 2 * uinterval);
|
||||
lvname, sysdir, type, abort_polling, 2 * uinterval, devicesfile);
|
||||
if (!pdlv) {
|
||||
pdst_unlock(pdst);
|
||||
free(id);
|
||||
|
||||
@@ -93,11 +93,13 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
const char *vgname, const char *lvname,
|
||||
const char *sysdir, enum poll_type type,
|
||||
const char *sinterval, unsigned pdtimeout,
|
||||
struct lvmpolld_store *pdst)
|
||||
struct lvmpolld_store *pdst,
|
||||
const char *devicesfile)
|
||||
{
|
||||
char *lvmpolld_id = strdup(id), /* copy */
|
||||
*full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
|
||||
*lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
|
||||
char *devicesfile_dup = devicesfile ? strdup(devicesfile) : NULL;
|
||||
|
||||
struct lvmpolld_lv tmp = {
|
||||
.ls = ls,
|
||||
@@ -105,6 +107,7 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
.lvmpolld_id = lvmpolld_id,
|
||||
.lvid = _get_lvid(lvmpolld_id, sysdir),
|
||||
.lvname = full_lvname,
|
||||
.devicesfile = devicesfile_dup,
|
||||
.lvm_system_dir_env = lvm_system_dir_env,
|
||||
.sinterval = strdup(sinterval), /* copy */
|
||||
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
|
||||
@@ -124,6 +127,7 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
return pdlv;
|
||||
|
||||
err:
|
||||
free((void *)devicesfile_dup);
|
||||
free((void *)full_lvname);
|
||||
free((void *)lvmpolld_id);
|
||||
free((void *)lvm_system_dir_env);
|
||||
@@ -136,6 +140,7 @@ err:
|
||||
void pdlv_destroy(struct lvmpolld_lv *pdlv)
|
||||
{
|
||||
free((void *)pdlv->lvmpolld_id);
|
||||
free((void *)pdlv->devicesfile);
|
||||
free((void *)pdlv->lvname);
|
||||
free((void *)pdlv->sinterval);
|
||||
free((void *)pdlv->lvm_system_dir_env);
|
||||
|
||||
@@ -49,6 +49,7 @@ struct lvmpolld_lv {
|
||||
const enum poll_type type;
|
||||
const char *const lvid;
|
||||
const char *const lvmpolld_id;
|
||||
const char *const devicesfile;
|
||||
const char *const lvname; /* full vg/lv name */
|
||||
const unsigned pdtimeout; /* in seconds */
|
||||
const char *const sinterval;
|
||||
@@ -101,7 +102,8 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
const char *vgname, const char *lvname,
|
||||
const char *sysdir, enum poll_type type,
|
||||
const char *sinterval, unsigned pdtimeout,
|
||||
struct lvmpolld_store *pdst);
|
||||
struct lvmpolld_store *pdst,
|
||||
const char *devicesfile);
|
||||
|
||||
/* only call with appropriate struct lvmpolld_store lock held */
|
||||
void pdlv_destroy(struct lvmpolld_lv *pdlv);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#define LVMPD_PARM_SYSDIR "sysdir"
|
||||
#define LVMPD_PARM_VALUE "value" /* either retcode or signal value */
|
||||
#define LVMPD_PARM_VGNAME "vgname"
|
||||
#define LVMPD_PARM_DEVICESFILE "devicesfile"
|
||||
|
||||
#define LVMPD_RESP_FAILED "failed"
|
||||
#define LVMPD_RESP_FINISHED "finished"
|
||||
|
||||
@@ -1072,10 +1072,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
|
||||
#define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128))
|
||||
#define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
|
||||
/*
|
||||
* Max supported size for thin pool metadata device (17112760320 bytes)
|
||||
* Limitation is hardcoded into the kernel and bigger device size
|
||||
* is not accepted.
|
||||
* Max supported size for thin pool metadata device (17045913600 bytes)
|
||||
* drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS
|
||||
* But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly
|
||||
* Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9)))
|
||||
*/
|
||||
#define DM_THIN_MAX_METADATA_SIZE (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024)
|
||||
|
||||
@@ -1088,6 +1088,16 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
|
||||
uint64_t low_water_mark,
|
||||
unsigned skip_block_zeroing);
|
||||
|
||||
int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
uint64_t transaction_id,
|
||||
const char *metadata_uuid,
|
||||
const char *pool_uuid,
|
||||
uint32_t data_block_size,
|
||||
uint64_t low_water_mark,
|
||||
unsigned skip_block_zeroing,
|
||||
unsigned crop_metadata);
|
||||
|
||||
/* Supported messages for thin provision target */
|
||||
typedef enum {
|
||||
DM_THIN_MESSAGE_CREATE_SNAP, /* device_id, origin_id */
|
||||
|
||||
@@ -242,18 +242,3 @@ bad:
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/*
|
||||
* Maintain backward compatibility with older versions that did not
|
||||
* accept a 'min_num_bits' argument to dm_bitset_parse_list().
|
||||
*/
|
||||
dm_bitset_t dm_bitset_parse_list_v1_02_129(const char *str, struct dm_pool *mem);
|
||||
dm_bitset_t dm_bitset_parse_list_v1_02_129(const char *str, struct dm_pool *mem)
|
||||
{
|
||||
return dm_bitset_parse_list(str, mem, 0);
|
||||
}
|
||||
|
||||
#else /* if defined(__GNUC__) */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -493,7 +493,10 @@ static void _dm_task_free_targets(struct dm_task *dmt)
|
||||
|
||||
for (t = dmt->head; t; t = n) {
|
||||
n = t->next;
|
||||
_dm_zfree_string(t->params);
|
||||
if (dmt->secure_data)
|
||||
_dm_zfree_string(t->params);
|
||||
else
|
||||
free(t->params);
|
||||
free(t->type);
|
||||
free(t);
|
||||
}
|
||||
@@ -504,7 +507,10 @@ static void _dm_task_free_targets(struct dm_task *dmt)
|
||||
void dm_task_destroy(struct dm_task *dmt)
|
||||
{
|
||||
_dm_task_free_targets(dmt);
|
||||
_dm_zfree_dmi(dmt->dmi.v4);
|
||||
if (dmt->secure_data)
|
||||
_dm_zfree_dmi(dmt->dmi.v4);
|
||||
else
|
||||
free(dmt->dmi.v4);
|
||||
free(dmt->dev_name);
|
||||
free(dmt->mangled_dev_name);
|
||||
free(dmt->newname);
|
||||
@@ -1112,7 +1118,7 @@ static int _add_params(int type)
|
||||
|
||||
static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
{
|
||||
const size_t min_size = 16 * 1024;
|
||||
size_t min_size;
|
||||
const int (*version)[3];
|
||||
|
||||
struct dm_ioctl *dmi;
|
||||
@@ -1131,6 +1137,18 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
else if (dmt->head)
|
||||
log_debug_activation(INTERNAL_ERROR "dm '%s' ioctl should not define parameters.",
|
||||
_cmd_data_v4[dmt->type].name);
|
||||
switch (dmt->type) {
|
||||
case DM_DEVICE_CREATE:
|
||||
case DM_DEVICE_DEPS:
|
||||
case DM_DEVICE_LIST:
|
||||
case DM_DEVICE_STATUS:
|
||||
case DM_DEVICE_TABLE:
|
||||
case DM_DEVICE_TARGET_MSG:
|
||||
min_size = 16 * 1024;
|
||||
break;
|
||||
default:
|
||||
min_size = 2 * 1024;
|
||||
}
|
||||
|
||||
if (count && (dmt->sector || dmt->message)) {
|
||||
log_error("targets and message are incompatible");
|
||||
@@ -1334,7 +1352,7 @@ static int _process_mapper_dir(struct dm_task *dmt)
|
||||
}
|
||||
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", dir);
|
||||
log_sys_debug("closedir", dir);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -1582,23 +1600,30 @@ static int _reload_with_suppression_v4(struct dm_task *dmt)
|
||||
t2->params[len] = '\0';
|
||||
|
||||
if (t1->start != t2->start) {
|
||||
log_debug("reload %u:%u start diff", task->major, task->minor);
|
||||
log_debug("reload %u:%u diff start %llu %llu type %s %s", task->major, task->minor,
|
||||
(unsigned long long)t1->start, (unsigned long long)t2->start, t1->type, t2->type);
|
||||
goto no_match;
|
||||
}
|
||||
if (t1->length != t2->length) {
|
||||
log_debug("reload %u:%u length diff", task->major, task->minor);
|
||||
log_debug("reload %u:%u diff length %llu %llu type %s %s", task->major, task->minor,
|
||||
(unsigned long long)t1->length, (unsigned long long)t2->length, t1->type, t2->type);
|
||||
goto no_match;
|
||||
}
|
||||
if (strcmp(t1->type, t2->type)) {
|
||||
log_debug("reload %u:%u type diff %s %s", task->major, task->minor, t1->type, t2->type);
|
||||
log_debug("reload %u:%u diff type %s %s", task->major, task->minor, t1->type, t2->type);
|
||||
goto no_match;
|
||||
}
|
||||
if (strcmp(t1->params, t2->params)) {
|
||||
if (dmt->skip_reload_params_compare)
|
||||
log_debug("reload %u:%u skip params ignore %s %s",
|
||||
task->major, task->minor, t1->params, t2->params);
|
||||
else {
|
||||
log_debug("reload %u:%u params diff", task->major, task->minor);
|
||||
if (dmt->skip_reload_params_compare) {
|
||||
log_debug("reload %u:%u diff params ignore for type %s",
|
||||
task->major, task->minor, t1->type);
|
||||
log_debug("reload params1 %s", t1->params);
|
||||
log_debug("reload params2 %s", t2->params);
|
||||
} else {
|
||||
log_debug("reload %u:%u diff params for type %s",
|
||||
task->major, task->minor, t1->type);
|
||||
log_debug("reload params1 %s", t1->params);
|
||||
log_debug("reload params2 %s", t2->params);
|
||||
goto no_match;
|
||||
}
|
||||
}
|
||||
@@ -2184,52 +2209,3 @@ void dm_lib_exit(void)
|
||||
_version_ok = 1;
|
||||
_version_checked = 0;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/*
|
||||
* Maintain binary backward compatibility.
|
||||
* Version script mechanism works with 'gcc' compatible compilers only.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This following code is here to retain ABI compatibility after adding
|
||||
* the field deferred_remove to struct dm_info in version 1.02.89.
|
||||
*
|
||||
* Binaries linked against version 1.02.88 of libdevmapper or earlier
|
||||
* will use this function that returns dm_info without the
|
||||
* deferred_remove field.
|
||||
*
|
||||
* Binaries compiled against version 1.02.89 onwards will use
|
||||
* the new function dm_task_get_info_with_deferred_remove due to the
|
||||
* #define.
|
||||
*
|
||||
* N.B. Keep this function at the end of the file to make sure that
|
||||
* no code in this file accidentally calls it.
|
||||
*/
|
||||
|
||||
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info);
|
||||
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info)
|
||||
{
|
||||
struct dm_info new_info;
|
||||
|
||||
if (!dm_task_get_info(dmt, &new_info))
|
||||
return 0;
|
||||
|
||||
memcpy(info, &new_info, offsetof(struct dm_info, deferred_remove));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *info);
|
||||
int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *info)
|
||||
{
|
||||
struct dm_info new_info;
|
||||
|
||||
if (!dm_task_get_info(dmt, &new_info))
|
||||
return 0;
|
||||
|
||||
memcpy(info, &new_info, offsetof(struct dm_info, internal_suspend));
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -382,7 +382,7 @@ static int _find_dm_name_of_device(dev_t st_rdev, char *buf, size_t buf_len)
|
||||
}
|
||||
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", _dm_dir);
|
||||
log_sys_debug("closedir", _dm_dir);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -931,7 +931,7 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
static int _selabel_lookup(const char *path, mode_t mode,
|
||||
security_context_t *scontext)
|
||||
char **scontext)
|
||||
{
|
||||
#ifdef HAVE_SELINUX_LABEL_H
|
||||
if (!_selabel_handle &&
|
||||
@@ -974,7 +974,7 @@ static int _is_selinux_enabled(void)
|
||||
int dm_prepare_selinux_context(const char *path, mode_t mode)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
security_context_t scontext = NULL;
|
||||
char *scontext = NULL;
|
||||
|
||||
if (_is_selinux_enabled() <= 0)
|
||||
return 1;
|
||||
@@ -1002,7 +1002,7 @@ int dm_prepare_selinux_context(const char *path, mode_t mode)
|
||||
int dm_set_selinux_context(const char *path, mode_t mode)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
security_context_t scontext = NULL;
|
||||
char *scontext = NULL;
|
||||
|
||||
if (_is_selinux_enabled() <= 0)
|
||||
return 1;
|
||||
@@ -1224,7 +1224,7 @@ int get_dev_node_read_ahead(const char *dev_name, uint32_t major, uint32_t minor
|
||||
int len;
|
||||
int r = 1;
|
||||
int fd;
|
||||
long read_ahead_long;
|
||||
long read_ahead_long = 0;
|
||||
|
||||
/*
|
||||
* If we know the device number, use sysfs if we can.
|
||||
|
||||
@@ -599,7 +599,7 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
|
||||
match(TOK_IDENTIFIER);
|
||||
}
|
||||
|
||||
if (!strlen(str)) {
|
||||
if (!*str) {
|
||||
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): empty section identifier",
|
||||
p->tb - p->fb + 1, p->line);
|
||||
return NULL;
|
||||
@@ -983,7 +983,7 @@ static const char *_find_config_str(const void *start, node_lookup_fn find_fn,
|
||||
}
|
||||
|
||||
if (fail)
|
||||
log_very_verbose("%s not found in config: defaulting to %s",
|
||||
log_very_verbose("%s not found in config: defaulting to \"%s\"",
|
||||
path, fail);
|
||||
return fail;
|
||||
}
|
||||
|
||||
@@ -380,13 +380,13 @@ struct dm_tree *dm_tree_create(void)
|
||||
dtree->mem = dmem;
|
||||
dtree->optional_uuid_suffixes = NULL;
|
||||
|
||||
if (!(dtree->devs = dm_hash_create(8))) {
|
||||
if (!(dtree->devs = dm_hash_create(61))) {
|
||||
log_error("dtree hash creation failed");
|
||||
dm_pool_destroy(dtree->mem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(dtree->uuids = dm_hash_create(32))) {
|
||||
if (!(dtree->uuids = dm_hash_create(31))) {
|
||||
log_error("dtree uuid hash creation failed");
|
||||
dm_hash_destroy(dtree->devs);
|
||||
dm_pool_destroy(dtree->mem);
|
||||
@@ -2382,7 +2382,7 @@ static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *s
|
||||
|
||||
EMIT_PARAMS(pos, " %u ", seg->mirror_area_count);
|
||||
|
||||
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
|
||||
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
|
||||
return_0;
|
||||
|
||||
if (handle_errors)
|
||||
@@ -2584,7 +2584,7 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
|
||||
/* Print number of metadata/data device pairs */
|
||||
EMIT_PARAMS(pos, " %u", area_count);
|
||||
|
||||
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
|
||||
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
@@ -2824,6 +2824,9 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
|
||||
if (set->sectors_per_bit_set)
|
||||
EMIT_PARAMS(pos, " sectors_per_bit:%llu", (unsigned long long)set->sectors_per_bit);
|
||||
|
||||
if (!dm_task_secure_data(dmt))
|
||||
stack;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2927,7 +2930,6 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
|
||||
size_t paramsize)
|
||||
{
|
||||
int pos = 0;
|
||||
int r;
|
||||
int target_type_is_raid = 0;
|
||||
char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
|
||||
|
||||
@@ -2938,8 +2940,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
|
||||
break;
|
||||
case SEG_MIRRORED:
|
||||
/* Mirrors are pretty complicated - now in separate function */
|
||||
r = _mirror_emit_segment_line(dmt, seg, params, paramsize);
|
||||
if (!r)
|
||||
if (!_mirror_emit_segment_line(dmt, seg, params, paramsize))
|
||||
return_0;
|
||||
break;
|
||||
case SEG_SNAPSHOT:
|
||||
@@ -2960,7 +2961,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
|
||||
EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size);
|
||||
break;
|
||||
case SEG_VDO:
|
||||
if (!(r = _vdo_emit_segment_line(dmt, seg, params, paramsize)))
|
||||
if (!_vdo_emit_segment_line(dmt, seg, params, paramsize))
|
||||
return_0;
|
||||
break;
|
||||
case SEG_CRYPT:
|
||||
@@ -2989,9 +2990,8 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
|
||||
case SEG_RAID6_LA_6:
|
||||
case SEG_RAID6_RA_6:
|
||||
target_type_is_raid = 1;
|
||||
r = _raid_emit_segment_line(dmt, major, minor, seg, seg_start,
|
||||
params, paramsize);
|
||||
if (!r)
|
||||
if (!_raid_emit_segment_line(dmt, major, minor, seg, seg_start,
|
||||
params, paramsize))
|
||||
return_0;
|
||||
|
||||
break;
|
||||
@@ -3032,10 +3032,9 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
|
||||
case SEG_CRYPT:
|
||||
case SEG_LINEAR:
|
||||
case SEG_STRIPED:
|
||||
if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
|
||||
stack;
|
||||
return r;
|
||||
}
|
||||
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
|
||||
return_0;
|
||||
|
||||
if (!params[0]) {
|
||||
log_error("No parameters supplied for %s target "
|
||||
"%u:%u.", _dm_segtypes[seg->type].target,
|
||||
@@ -3978,6 +3977,24 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
|
||||
uint32_t data_block_size,
|
||||
uint64_t low_water_mark,
|
||||
unsigned skip_block_zeroing)
|
||||
{
|
||||
return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id,
|
||||
metadata_uuid, pool_uuid,
|
||||
data_block_size,
|
||||
low_water_mark,
|
||||
skip_block_zeroing,
|
||||
1);
|
||||
}
|
||||
|
||||
int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
uint64_t transaction_id,
|
||||
const char *metadata_uuid,
|
||||
const char *pool_uuid,
|
||||
uint32_t data_block_size,
|
||||
uint64_t low_water_mark,
|
||||
unsigned skip_block_zeroing,
|
||||
unsigned crop_metadata)
|
||||
{
|
||||
struct load_segment *seg, *mseg;
|
||||
uint64_t devsize = 0;
|
||||
@@ -4005,17 +4022,18 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
|
||||
if (!_link_tree_nodes(node, seg->metadata))
|
||||
return_0;
|
||||
|
||||
/* FIXME: more complex target may need more tweaks */
|
||||
dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
|
||||
devsize += mseg->size;
|
||||
if (devsize > DM_THIN_MAX_METADATA_SIZE) {
|
||||
log_debug_activation("Ignoring %" PRIu64 " of device.",
|
||||
devsize - DM_THIN_MAX_METADATA_SIZE);
|
||||
mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
|
||||
devsize = DM_THIN_MAX_METADATA_SIZE;
|
||||
/* FIXME: drop remaining segs */
|
||||
if (crop_metadata)
|
||||
/* FIXME: more complex target may need more tweaks */
|
||||
dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
|
||||
devsize += mseg->size;
|
||||
if (devsize > DM_THIN_MAX_METADATA_SIZE) {
|
||||
log_debug_activation("Ignoring %" PRIu64 " of device.",
|
||||
devsize - DM_THIN_MAX_METADATA_SIZE);
|
||||
mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
|
||||
devsize = DM_THIN_MAX_METADATA_SIZE;
|
||||
/* FIXME: drop remaining segs */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) {
|
||||
log_error("Missing pool uuid %s.", pool_uuid);
|
||||
@@ -4310,61 +4328,6 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode,
|
||||
dnode->callback_data = data;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/*
|
||||
* Backward compatible implementations.
|
||||
*
|
||||
* Keep these at the end of the file to make sure that
|
||||
* no code in this file accidentally calls it.
|
||||
*/
|
||||
|
||||
/* Backward compatible dm_tree_node_size_changed() implementations. */
|
||||
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode);
|
||||
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
|
||||
{
|
||||
/* Base does not make difference between smaller and bigger */
|
||||
return dm_tree_node_size_changed(dnode) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retain ABI compatibility after adding the DM_CACHE_FEATURE_METADATA2
|
||||
* in version 1.02.138.
|
||||
*
|
||||
* Binaries compiled against version 1.02.138 onwards will use
|
||||
* the new function dm_tree_node_add_cache_target which detects unknown
|
||||
* feature flags and returns error for them.
|
||||
*/
|
||||
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
uint64_t feature_flags, /* DM_CACHE_FEATURE_* */
|
||||
const char *metadata_uuid,
|
||||
const char *data_uuid,
|
||||
const char *origin_uuid,
|
||||
const char *policy_name,
|
||||
const struct dm_config_node *policy_settings,
|
||||
uint32_t data_block_size);
|
||||
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
uint64_t feature_flags,
|
||||
const char *metadata_uuid,
|
||||
const char *data_uuid,
|
||||
const char *origin_uuid,
|
||||
const char *policy_name,
|
||||
const struct dm_config_node *policy_settings,
|
||||
uint32_t data_block_size)
|
||||
{
|
||||
/* Old version supported only these FEATURE bits, others were ignored so masked them */
|
||||
static const uint64_t _mask =
|
||||
DM_CACHE_FEATURE_WRITEBACK |
|
||||
DM_CACHE_FEATURE_WRITETHROUGH |
|
||||
DM_CACHE_FEATURE_PASSTHROUGH;
|
||||
|
||||
return dm_tree_node_add_cache_target(node, size, feature_flags & _mask,
|
||||
metadata_uuid, data_uuid, origin_uuid,
|
||||
policy_name, policy_settings, 0, 0, 0, 0, data_block_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
|
||||
uint64_t size,
|
||||
const char *vdo_pool_name,
|
||||
|
||||
@@ -110,7 +110,7 @@ int dm_is_empty_dir(const char *dir)
|
||||
DIR *d;
|
||||
|
||||
if (!(d = opendir(dir))) {
|
||||
log_sys_error("opendir", dir);
|
||||
log_sys_debug("opendir", dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ int dm_is_empty_dir(const char *dir)
|
||||
break;
|
||||
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", dir);
|
||||
log_sys_debug("closedir", dir);
|
||||
|
||||
return dirent ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -492,7 +492,7 @@ static int _report_field_string_list(struct dm_report *rh,
|
||||
delimiter = ",";
|
||||
delimiter_len = strlen(delimiter);
|
||||
|
||||
i = pos = len = 0;
|
||||
i = pos = 0;
|
||||
dm_list_iterate_items(sl, data) {
|
||||
arr[i].str = sl->str;
|
||||
if (!sort) {
|
||||
@@ -2474,7 +2474,7 @@ dm_percent_t dm_make_percent(uint64_t numerator, uint64_t denominator)
|
||||
|
||||
int dm_report_value_cache_set(struct dm_report *rh, const char *name, const void *data)
|
||||
{
|
||||
if (!rh->value_cache && (!(rh->value_cache = dm_hash_create(64)))) {
|
||||
if (!rh->value_cache && (!(rh->value_cache = dm_hash_create(63)))) {
|
||||
log_error("Failed to create cache for values used during reporting.");
|
||||
return 0;
|
||||
}
|
||||
@@ -3774,7 +3774,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
struct field_selection *fs;
|
||||
struct selection_node *sn;
|
||||
const char *ws, *we; /* field name */
|
||||
const char *vs, *ve; /* value */
|
||||
const char *vs = NULL, *ve = NULL; /* value */
|
||||
const char *last;
|
||||
uint32_t flags, field_num;
|
||||
int implicit;
|
||||
|
||||
@@ -94,7 +94,7 @@ journal_watermark:number
|
||||
|
||||
commit_time:number
|
||||
Commit time in milliseconds. When this time passes, the journal is
|
||||
written. The journal is also written immediatelly if the FLUSH
|
||||
written. The journal is also written immediately if the FLUSH
|
||||
request is received.
|
||||
|
||||
internal_hash:algorithm(:key) (the key is optional)
|
||||
|
||||
2
include/.gitignore
vendored
2
include/.gitignore
vendored
@@ -1 +1,3 @@
|
||||
*.h
|
||||
.symlinks
|
||||
.symlinks_created
|
||||
|
||||
@@ -132,6 +132,9 @@
|
||||
/* Path to fsadm binary. */
|
||||
#undef FSADM_PATH
|
||||
|
||||
/* Define to use GNU versioning in the shared library. */
|
||||
#undef GNU_SYMVER
|
||||
|
||||
/* Define to 1 if you have the `alarm' function. */
|
||||
#undef HAVE_ALARM
|
||||
|
||||
@@ -182,9 +185,6 @@
|
||||
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
||||
#undef HAVE_DOPRNT
|
||||
|
||||
/* Define to 1 if you have the <editline/history.h> header file. */
|
||||
#undef HAVE_EDITLINE_HISTORY_H
|
||||
|
||||
/* Define to 1 if you have the <editline/readline.h> header file. */
|
||||
#undef HAVE_EDITLINE_READLINE_H
|
||||
|
||||
@@ -561,6 +561,9 @@
|
||||
/* Define to 1 to include code that uses lvmlockd sanlock option. */
|
||||
#undef LOCKDSANLOCK_SUPPORT
|
||||
|
||||
/* Define to 1 to include code that uses lvmlockd IDM option. */
|
||||
#undef LOCKDIDM_SUPPORT
|
||||
|
||||
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
|
||||
slash. */
|
||||
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
|
||||
SOURCES =\
|
||||
activate/activate.c \
|
||||
@@ -29,6 +30,7 @@ SOURCES =\
|
||||
device/bcache.c \
|
||||
device/bcache-utils.c \
|
||||
device/dev-cache.c \
|
||||
device/device_id.c \
|
||||
device/dev-ext.c \
|
||||
device/dev-io.c \
|
||||
device/dev-md.c \
|
||||
@@ -52,6 +54,7 @@ SOURCES =\
|
||||
filters/filter-usable.c \
|
||||
filters/filter-internal.c \
|
||||
filters/filter-signature.c \
|
||||
filters/filter-deviceid.c \
|
||||
format_text/archive.c \
|
||||
format_text/archiver.c \
|
||||
format_text/export.c \
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "lib/metadata/segtype.h"
|
||||
#include "lib/misc/sharedlib.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/misc/lvm-signal.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
@@ -177,6 +178,22 @@ int lv_passes_auto_activation_filter(struct cmd_context *cmd, struct logical_vol
|
||||
return _lv_passes_volumes_filter(cmd, lv, cn, activation_auto_activation_volume_list_CFG);
|
||||
}
|
||||
|
||||
static int _passes_readonly_filter(struct cmd_context *cmd,
|
||||
const struct logical_volume *lv)
|
||||
{
|
||||
const struct dm_config_node *cn;
|
||||
|
||||
if (!(cn = find_config_tree_array(cmd, activation_read_only_volume_list_CFG, NULL)))
|
||||
return 0;
|
||||
|
||||
return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
|
||||
}
|
||||
|
||||
int lv_passes_readonly_filter(const struct logical_volume *lv)
|
||||
{
|
||||
return _passes_readonly_filter(lv->vg->cmd, lv);
|
||||
}
|
||||
|
||||
#ifndef DEVMAPPER_SUPPORT
|
||||
void set_activation(int act, int silent)
|
||||
{
|
||||
@@ -274,6 +291,10 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int lv_writecache_message(const struct logical_volume *lv, const char *msg)
|
||||
{
|
||||
return 0;
|
||||
@@ -392,7 +413,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
int device_is_usable(struct device *dev, struct dev_usable_check_params check, int *is_lv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -455,17 +476,6 @@ static int _passes_activation_filter(struct cmd_context *cmd,
|
||||
return _lv_passes_volumes_filter(cmd, lv, cn, activation_volume_list_CFG);
|
||||
}
|
||||
|
||||
static int _passes_readonly_filter(struct cmd_context *cmd,
|
||||
const struct logical_volume *lv)
|
||||
{
|
||||
const struct dm_config_node *cn;
|
||||
|
||||
if (!(cn = find_config_tree_array(cmd, activation_read_only_volume_list_CFG, NULL)))
|
||||
return 0;
|
||||
|
||||
return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
|
||||
}
|
||||
|
||||
int library_version(char *version, size_t size)
|
||||
{
|
||||
if (!activation())
|
||||
@@ -564,13 +574,9 @@ int module_present(struct cmd_context *cmd, const char *target_name)
|
||||
}
|
||||
|
||||
#ifdef MODPROBE_CMD
|
||||
if (strcmp(target_name, MODULE_NAME_VDO) == 0) {
|
||||
argv[1] = target_name; /* ATM kvdo is without dm- prefix */
|
||||
if ((ret = exec_cmd(cmd, argv, NULL, 0)))
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
|
||||
if (strcmp(target_name, TARGET_NAME_VDO) == 0)
|
||||
argv[1] = MODULE_NAME_VDO; /* ATM kvdo is without dm- prefix */
|
||||
else if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
|
||||
log_error("module_present module name too long: %s",
|
||||
target_name);
|
||||
return 0;
|
||||
@@ -823,12 +829,15 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
|
||||
#define OPEN_COUNT_CHECK_USLEEP_DELAY 200000
|
||||
|
||||
/* Only report error if error_if_used is set */
|
||||
/* Returns 0 if in use, 1 if it is unused, 2 when it is not present in table */
|
||||
int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
|
||||
{
|
||||
struct lvinfo info;
|
||||
unsigned int open_count_check_retries;
|
||||
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists || !info.open_count)
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists)
|
||||
return 2;
|
||||
else if (!info.open_count)
|
||||
return 1;
|
||||
|
||||
/* If sysfs is not used, use open_count information only. */
|
||||
@@ -855,25 +864,24 @@ int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
|
||||
}
|
||||
|
||||
open_count_check_retries = retry_deactivation() ? OPEN_COUNT_CHECK_RETRIES : 1;
|
||||
while (info.open_count > 0 && open_count_check_retries--) {
|
||||
if (!open_count_check_retries) {
|
||||
if (error_if_used)
|
||||
log_error("Logical volume %s in use.", display_lvname(lv));
|
||||
else
|
||||
log_debug_activation("Logical volume %s in use.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
while (open_count_check_retries--) {
|
||||
if (interruptible_usleep(OPEN_COUNT_CHECK_USLEEP_DELAY))
|
||||
break; /* interrupted */
|
||||
|
||||
usleep(OPEN_COUNT_CHECK_USLEEP_DELAY);
|
||||
log_debug_activation("Retrying open_count check for %s.",
|
||||
display_lvname(lv));
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0)) {
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists) {
|
||||
stack; /* device dissappeared? */
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
} else if (!info.open_count)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
if (error_if_used)
|
||||
log_error("Logical volume %s in use.", display_lvname(lv));
|
||||
else
|
||||
log_debug_activation("Logical volume %s in use.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -964,35 +972,28 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
|
||||
|
||||
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
struct dm_status_raid *status;
|
||||
struct lv_status_raid *raid_status;
|
||||
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking raid data offset and dev sectors for LV %s/%s",
|
||||
lv->vg->name, lv->name);
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_raid_status(dm, lv, &status))) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
}
|
||||
if (!lv_raid_status(lv, &raid_status))
|
||||
return_0;
|
||||
|
||||
*data_offset = status->data_offset;
|
||||
*data_offset = raid_status->raid->data_offset;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
dm_pool_destroy(raid_status->mem);
|
||||
|
||||
return r;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
struct dm_status_raid *status;
|
||||
int r = 1;
|
||||
struct lv_status_raid *raid_status;
|
||||
|
||||
*dev_health = NULL;
|
||||
|
||||
@@ -1002,25 +1003,23 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
|
||||
log_debug_activation("Checking raid device health for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
if (!lv_raid_status(lv, &raid_status))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_raid_status(dm, lv, &status)) ||
|
||||
!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem,
|
||||
status->dev_health))) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
if (!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem,
|
||||
raid_status->raid->dev_health))) {
|
||||
stack;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
dm_pool_destroy(raid_status->mem);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
struct dm_status_raid *status;
|
||||
struct lv_status_raid *raid_status;
|
||||
|
||||
*dev_cnt = 0;
|
||||
|
||||
@@ -1029,24 +1028,20 @@ int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
|
||||
|
||||
log_debug_activation("Checking raid device count for LV %s/%s",
|
||||
lv->vg->name, lv->name);
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
|
||||
if (!lv_raid_status(lv, &raid_status))
|
||||
return_0;
|
||||
|
||||
if (!dev_manager_raid_status(dm, lv, &status)) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
}
|
||||
*dev_cnt = status->dev_count;
|
||||
*dev_cnt = raid_status->raid->dev_count;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
dm_pool_destroy(raid_status->mem);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
struct dm_status_raid *status;
|
||||
struct lv_status_raid *raid_status;
|
||||
|
||||
*cnt = 0;
|
||||
|
||||
@@ -1056,25 +1051,20 @@ int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
|
||||
log_debug_activation("Checking raid mismatch count for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
if (!lv_raid_status(lv, &raid_status))
|
||||
return_0;
|
||||
|
||||
if (!dev_manager_raid_status(dm, lv, &status)) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
}
|
||||
*cnt = status->mismatch_count;
|
||||
*cnt = raid_status->raid->mismatch_count;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
dm_pool_destroy(raid_status->mem);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
struct dm_status_raid *status;
|
||||
char *action;
|
||||
struct lv_status_raid *raid_status;
|
||||
int r = 1;
|
||||
|
||||
*sync_action = NULL;
|
||||
|
||||
@@ -1084,30 +1074,27 @@ int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
|
||||
log_debug_activation("Checking raid sync_action for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
if (!lv_raid_status(lv, &raid_status))
|
||||
return_0;
|
||||
|
||||
/* status->sync_action can be NULL if dm-raid version < 1.5.0 */
|
||||
if (!dev_manager_raid_status(dm, lv, &status) ||
|
||||
!status->sync_action ||
|
||||
!(action = dm_pool_strdup(lv->vg->cmd->mem,
|
||||
status->sync_action))) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
if (!raid_status->raid->sync_action ||
|
||||
!(*sync_action = dm_pool_strdup(lv->vg->cmd->mem,
|
||||
raid_status->raid->sync_action))) {
|
||||
stack;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
*sync_action = action;
|
||||
dm_pool_destroy(raid_status->mem);
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
|
||||
return 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_raid_message(const struct logical_volume *lv, const char *msg)
|
||||
{
|
||||
struct lv_status_raid *raid_status;
|
||||
struct dev_manager *dm = NULL;
|
||||
int r = 0;
|
||||
struct dev_manager *dm;
|
||||
struct dm_status_raid *status;
|
||||
|
||||
if (!seg_is_raid(first_seg(lv))) {
|
||||
/*
|
||||
@@ -1132,16 +1119,10 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
if (!lv_raid_status(lv, &raid_status))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_raid_status(dm, lv, &status))) {
|
||||
log_error("Failed to retrieve status of %s.",
|
||||
display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!status->sync_action) {
|
||||
if (!raid_status->raid->sync_action) {
|
||||
log_error("Kernel driver does not support this action: %s", msg);
|
||||
goto out;
|
||||
}
|
||||
@@ -1163,19 +1144,43 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
|
||||
log_error("\"%s\" is not a supported sync operation.", msg);
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(status->sync_action, "idle")) {
|
||||
if (strcmp(raid_status->raid->sync_action, "idle")) {
|
||||
log_error("%s state is currently \"%s\". Unable to switch to \"%s\".",
|
||||
display_lvname(lv), status->sync_action, msg);
|
||||
display_lvname(lv), raid_status->raid->sync_action, msg);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
r = dev_manager_raid_message(dm, lv, msg);
|
||||
out:
|
||||
dev_manager_destroy(dm);
|
||||
if (dm)
|
||||
dev_manager_destroy(dm);
|
||||
dm_pool_destroy(raid_status->mem);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
int exists;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!dev_manager_raid_status(dm, lv, status, &exists)) {
|
||||
dev_manager_destroy(dm);
|
||||
if (exists)
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
/* User has to call dm_pool_destroy(status->mem)! */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_writecache_message(const struct logical_volume *lv, const char *msg)
|
||||
{
|
||||
int r = 0;
|
||||
@@ -1208,6 +1213,7 @@ int lv_cache_status(const struct logical_volume *cache_lv,
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
struct lv_segment *cache_seg;
|
||||
int exists;
|
||||
|
||||
if (lv_is_cache_pool(cache_lv)) {
|
||||
if (dm_list_empty(&cache_lv->segs_using_this_lv) ||
|
||||
@@ -1225,21 +1231,14 @@ int lv_cache_status(const struct logical_volume *cache_lv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_info(cache_lv->vg->cmd, cache_lv, 1, NULL, 0, 0)) {
|
||||
log_error("Cannot check status for locally inactive cache volume %s.",
|
||||
display_lvname(cache_lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug_activation("Checking status for cache volume %s.",
|
||||
display_lvname(cache_lv));
|
||||
|
||||
if (!(dm = dev_manager_create(cache_lv->vg->cmd, cache_lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!dev_manager_cache_status(dm, cache_lv, status)) {
|
||||
if (!dev_manager_cache_status(dm, cache_lv, status, &exists)) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
if (exists)
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
/* User has to call dm_pool_destroy(status->mem)! */
|
||||
|
||||
@@ -1250,19 +1249,16 @@ int lv_thin_pool_status(const struct logical_volume *lv, int flush,
|
||||
struct lv_status_thin_pool **thin_pool_status)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking thin pool status for LV %s.",
|
||||
display_lvname(lv));
|
||||
int exists;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!dev_manager_thin_pool_status(dm, lv, flush, thin_pool_status)) {
|
||||
if (!dev_manager_thin_pool_status(dm, lv, flush, thin_pool_status, &exists)) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
if (exists)
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* User has to call dm_pool_destroy(thin_pool_status->mem)! */
|
||||
@@ -1274,19 +1270,16 @@ int lv_thin_status(const struct logical_volume *lv, int flush,
|
||||
struct lv_status_thin **thin_status)
|
||||
{
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking thin status for LV %s.",
|
||||
display_lvname(lv));
|
||||
int exists;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!dev_manager_thin_status(dm, lv, flush, thin_status)) {
|
||||
if (!dev_manager_thin_status(dm, lv, flush, thin_status, &exists)) {
|
||||
dev_manager_destroy(dm);
|
||||
return_0;
|
||||
if (exists)
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* User has to call dm_pool_destroy(thin_status->mem)! */
|
||||
@@ -1296,20 +1289,16 @@ int lv_thin_status(const struct logical_volume *lv, int flush,
|
||||
|
||||
int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
|
||||
{
|
||||
int r;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking device id for LV %s.",
|
||||
display_lvname(lv));
|
||||
int exists;
|
||||
int r;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
|
||||
return_0;
|
||||
|
||||
if (!(r = dev_manager_thin_device_id(dm, lv, device_id)))
|
||||
stack;
|
||||
if (!(r = dev_manager_thin_device_id(dm, lv, device_id, &exists)))
|
||||
if (exists)
|
||||
stack;
|
||||
|
||||
dev_manager_destroy(dm);
|
||||
|
||||
@@ -1326,28 +1315,22 @@ int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
|
||||
int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
|
||||
struct lv_status_vdo **vdo_status)
|
||||
{
|
||||
int r = 0;
|
||||
struct dev_manager *dm;
|
||||
|
||||
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
|
||||
return 0;
|
||||
|
||||
log_debug_activation("Checking VDO pool status for LV %s.",
|
||||
display_lvname(lv));
|
||||
int exists;
|
||||
|
||||
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, !lv_is_pvmove(lv))))
|
||||
return_0;
|
||||
|
||||
if (!dev_manager_vdo_pool_status(dm, lv, vdo_status, flush))
|
||||
goto_out;
|
||||
if (!dev_manager_vdo_pool_status(dm, lv, flush, vdo_status, &exists)) {
|
||||
dev_manager_destroy(dm);
|
||||
if (exists)
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* User has to call dm_pool_destroy(vdo_status->mem) */
|
||||
r = 1;
|
||||
out:
|
||||
if (!r)
|
||||
dev_manager_destroy(dm);
|
||||
|
||||
return r;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent)
|
||||
@@ -2043,12 +2026,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
if (!activation())
|
||||
return 1;
|
||||
|
||||
/* Ignore origin_only unless LV is origin in both old and new metadata */
|
||||
/* or LV is thin or thin pool volume */
|
||||
if (!lv_is_thin_volume(lv) && !lv_is_thin_pool(lv) &&
|
||||
!(lv_is_origin(lv) && lv_is_origin(lv_pre)))
|
||||
laopts->origin_only = 0;
|
||||
|
||||
if (test_mode()) {
|
||||
_skip("Suspending %s%s.", display_lvname(lv),
|
||||
laopts->origin_only ? " origin without snapshots" : "");
|
||||
@@ -2070,6 +2047,12 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
|
||||
lv_calculate_readahead(lv, NULL);
|
||||
|
||||
/* Ignore origin_only unless LV is origin in both old and new metadata */
|
||||
/* or LV is thin or thin pool volume */
|
||||
if (!lv_is_thin_volume(lv) && !lv_is_thin_pool(lv) &&
|
||||
!(lv_is_origin(lv) && lv_is_origin(lv_pre)))
|
||||
laopts->origin_only = 0;
|
||||
|
||||
/*
|
||||
* Preload devices for the LV.
|
||||
* If the PVMOVE LV is being removed, it's only present in the old
|
||||
@@ -2403,44 +2386,47 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
|
||||
|
||||
log_debug_activation("Deactivating %s.", display_lvname(lv));
|
||||
|
||||
if (!lv_info(cmd, lv, 0, &info, 0, 0))
|
||||
goto_out;
|
||||
|
||||
if (!info.exists) {
|
||||
r = 1;
|
||||
/* Check attached snapshot segments are also inactive */
|
||||
dm_list_iterate(snh, &lv->snapshot_segs) {
|
||||
if (!lv_info(cmd, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow,
|
||||
0, &info, 0, 0))
|
||||
goto_out;
|
||||
if (info.exists) {
|
||||
r = 0; /* Snapshot left in table? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lv_is_vdo_pool(lv)) {
|
||||
/* If someone has remove 'linear' mapping over VDO device
|
||||
* we may still be able to deactivate the rest of the tree
|
||||
* i.e. in test-suite we simulate this via 'dmsetup remove' */
|
||||
if (!lv_info(cmd, lv, 1, &info, 1, 0))
|
||||
goto_out;
|
||||
|
||||
if (info.exists && !info.open_count)
|
||||
r = 0; /* Unused VDO device left in table? */
|
||||
}
|
||||
|
||||
if (r)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lv_is_visible(lv) || lv_is_virtual_origin(lv) ||
|
||||
lv_is_merging_thin_snapshot(lv)) {
|
||||
if (!lv_check_not_in_use(lv, 1))
|
||||
goto_out;
|
||||
switch (lv_check_not_in_use(lv, 1)) {
|
||||
case 0: goto_out;
|
||||
case 2: goto no_exists;
|
||||
}
|
||||
|
||||
if (lv_is_origin(lv) && _lv_has_open_snapshots(lv))
|
||||
goto_out;
|
||||
} else {
|
||||
if (!lv_info(cmd, lv, 0, &info, 0, 0))
|
||||
goto_out;
|
||||
|
||||
if (!info.exists) {
|
||||
no_exists:
|
||||
r = 1;
|
||||
/* Check attached snapshot segments are also inactive */
|
||||
dm_list_iterate(snh, &lv->snapshot_segs) {
|
||||
if (!lv_info(cmd, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow,
|
||||
0, &info, 0, 0))
|
||||
goto_out;
|
||||
if (info.exists) {
|
||||
r = 0; /* Snapshot left in table? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lv_is_vdo_pool(lv)) {
|
||||
/* If someone has remove 'linear' mapping over VDO device
|
||||
* we may still be able to deactivate the rest of the tree
|
||||
* i.e. in test-suite we simulate this via 'dmsetup remove' */
|
||||
if (!lv_info(cmd, lv, 1, &info, 1, 0))
|
||||
goto_out;
|
||||
|
||||
if (info.exists && !info.open_count)
|
||||
r = 0; /* Unused VDO device left in table? */
|
||||
}
|
||||
|
||||
if (r)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!monitor_dev_for_events(cmd, lv, &laopts, 0))
|
||||
@@ -2837,7 +2823,7 @@ static int _deactivate_sub_lv_cb(struct logical_volume *lv, void *data)
|
||||
*/
|
||||
int deactivate_lv_with_sub_lv(const struct logical_volume *lv)
|
||||
{
|
||||
struct logical_volume *flv;
|
||||
struct logical_volume *flv = NULL;
|
||||
|
||||
if (!deactivate_lv(lv->vg->cmd, lv)) {
|
||||
log_error("Cannot deactivate logical volume %s.",
|
||||
@@ -2847,7 +2833,7 @@ int deactivate_lv_with_sub_lv(const struct logical_volume *lv)
|
||||
|
||||
if (!for_each_sub_lv((struct logical_volume *)lv, _deactivate_sub_lv_cb, &flv)) {
|
||||
log_error("Cannot deactivate subvolume %s of logical volume %s.",
|
||||
display_lvname(flv), display_lvname(lv));
|
||||
(flv) ? display_lvname(flv) : "", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -188,6 +188,7 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
|
||||
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
|
||||
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
|
||||
int lv_raid_message(const struct logical_volume *lv, const char *msg);
|
||||
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status);
|
||||
int lv_writecache_message(const struct logical_volume *lv, const char *msg);
|
||||
int lv_cache_status(const struct logical_volume *cache_lv,
|
||||
struct lv_status_cache **status);
|
||||
@@ -208,6 +209,8 @@ int lvs_in_vg_opened(const struct volume_group *vg);
|
||||
|
||||
int lv_is_active(const struct logical_volume *lv);
|
||||
|
||||
int lv_passes_readonly_filter(const struct logical_volume *lv);
|
||||
|
||||
/* Check is any component LV is active */
|
||||
const struct logical_volume *lv_component_is_active(const struct logical_volume *lv);
|
||||
const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv);
|
||||
@@ -251,7 +254,7 @@ struct dev_usable_check_params {
|
||||
* Returns 1 if mapped device is not suspended, blocked or
|
||||
* is using a reserved name.
|
||||
*/
|
||||
int device_is_usable(struct device *dev, struct dev_usable_check_params check);
|
||||
int device_is_usable(struct device *dev, struct dev_usable_check_params check, int *is_lv);
|
||||
|
||||
/*
|
||||
* Declaration moved here from fs.h to keep header fs.h hidden
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/misc/lvm-exec.h"
|
||||
#include "lib/datastruct/str_list.h"
|
||||
#include "lib/misc/lvm-signal.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
@@ -261,7 +262,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
|
||||
int dmtask;
|
||||
int with_flush; /* TODO: arg for _info_run */
|
||||
void *target = NULL;
|
||||
uint64_t target_start, target_length, start, length;
|
||||
uint64_t target_start, target_length, start, length, length_crop = 0;
|
||||
char *target_name, *target_params;
|
||||
const char *devname;
|
||||
|
||||
@@ -297,7 +298,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
|
||||
/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */
|
||||
if (lv_is_thin_pool_metadata(seg_status->seg->lv) &&
|
||||
(length > DM_THIN_MAX_METADATA_SIZE))
|
||||
length = DM_THIN_MAX_METADATA_SIZE;
|
||||
length_crop = DM_THIN_MAX_METADATA_SIZE;
|
||||
|
||||
/* Uses virtual size with headers for VDO pool device */
|
||||
if (lv_is_vdo_pool(seg_status->seg->lv))
|
||||
@@ -310,7 +311,9 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
|
||||
target = dm_get_next_target(dmt, target, &target_start,
|
||||
&target_length, &target_name, &target_params);
|
||||
|
||||
if ((start == target_start) && (length == target_length))
|
||||
if ((start == target_start) &&
|
||||
((length == target_length) ||
|
||||
(length_crop && (length_crop == target_length))))
|
||||
break; /* Keep target_params when matching segment is found */
|
||||
|
||||
target_params = NULL; /* Marking this target_params unusable */
|
||||
@@ -403,7 +406,7 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
|
||||
.check_blocked = 1,
|
||||
.check_suspended = ignore_suspended_devices(),
|
||||
.check_error_target = 1,
|
||||
.check_reserved = 0 }))
|
||||
.check_reserved = 0 }, NULL))
|
||||
goto out; /* safe to use */
|
||||
stack;
|
||||
}
|
||||
@@ -618,16 +621,17 @@ static int _ignore_frozen_raid(struct device *dev, const char *params)
|
||||
*
|
||||
* Returns: 1 if usable, 0 otherwise
|
||||
*/
|
||||
int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
int device_is_usable(struct device *dev, struct dev_usable_check_params check, int *is_lv)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
const char *name, *uuid;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params, *vgname = NULL, *lvname, *layer;
|
||||
char *params, *vgname, *lvname, *layer;
|
||||
char vg_name[NAME_LEN];
|
||||
void *next = NULL;
|
||||
int only_error_target = 1;
|
||||
int only_error_or_zero_target = 1;
|
||||
int r = 0;
|
||||
|
||||
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, NULL, NULL,
|
||||
@@ -650,44 +654,51 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check internal lvm devices */
|
||||
if (check.check_reserved &&
|
||||
uuid && !strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) {
|
||||
if (strlen(uuid) > (sizeof(UUID_PREFIX) + 2 * ID_LEN)) { /* 68 */
|
||||
log_debug_activation("%s: Reserved uuid %s on internal LV device %s not usable.",
|
||||
dev_name(dev), uuid, name);
|
||||
goto out;
|
||||
if (uuid && (check.check_reserved || check.check_lv)) {
|
||||
if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) { /* with LVM- prefix */
|
||||
if (check.check_reserved) {
|
||||
/* Check internal lvm devices */
|
||||
if (strlen(uuid) > (sizeof(UUID_PREFIX) + 2 * ID_LEN)) { /* 68 with suffix */
|
||||
log_debug_activation("%s: Reserved uuid %s on internal LV device %s not usable.",
|
||||
dev_name(dev), uuid, name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Recognize some older reserved LVs just from the LV name (snapshot, pvmove...) */
|
||||
vgname = vg_name;
|
||||
if (!dm_strncpy(vg_name, name, sizeof(vg_name)) ||
|
||||
!dm_split_lvm_name(NULL, NULL, &vgname, &lvname, &layer))
|
||||
goto_out;
|
||||
|
||||
/* FIXME: fails to handle dev aliases i.e. /dev/dm-5, replace with UUID suffix */
|
||||
if (lvname && (is_reserved_lvname(lvname) || *layer)) {
|
||||
log_debug_activation("%s: Reserved internal LV device %s/%s%s%s not usable.",
|
||||
dev_name(dev), vgname, lvname, *layer ? "-" : "", layer);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (check.check_lv) {
|
||||
/* Skip LVs */
|
||||
if (is_lv)
|
||||
*is_lv = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(vgname = strdup(name)) ||
|
||||
!dm_split_lvm_name(NULL, NULL, &vgname, &lvname, &layer))
|
||||
goto_out;
|
||||
|
||||
/* FIXME: fails to handle dev aliases i.e. /dev/dm-5, replace with UUID suffix */
|
||||
if (lvname && (is_reserved_lvname(lvname) || *layer)) {
|
||||
log_debug_activation("%s: Reserved internal LV device %s/%s%s%s not usable.",
|
||||
dev_name(dev), vgname, lvname, *layer ? "-" : "", layer);
|
||||
if (check.check_reserved &&
|
||||
(!strncmp(uuid, CRYPT_TEMP, sizeof(CRYPT_TEMP) - 1) ||
|
||||
!strncmp(uuid, CRYPT_SUBDEV, sizeof(CRYPT_SUBDEV) - 1) ||
|
||||
!strncmp(uuid, STRATIS, sizeof(STRATIS) - 1))) {
|
||||
/* Skip private crypto devices */
|
||||
log_debug_activation("%s: Reserved uuid %s on %s device %s not usable.",
|
||||
dev_name(dev), uuid,
|
||||
uuid[0] == 'C' ? "crypto" : "stratis",
|
||||
name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (check.check_lv && uuid && !strncmp(uuid, "LVM-", 4)) {
|
||||
/* Skip LVs */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (check.check_reserved && uuid &&
|
||||
(!strncmp(uuid, CRYPT_TEMP, sizeof(CRYPT_TEMP) - 1) ||
|
||||
!strncmp(uuid, CRYPT_SUBDEV, sizeof(CRYPT_SUBDEV) - 1) ||
|
||||
!strncmp(uuid, STRATIS, sizeof(STRATIS) - 1))) {
|
||||
/* Skip private crypto devices */
|
||||
log_debug_activation("%s: Reserved uuid %s on %s device %s not usable.",
|
||||
dev_name(dev), uuid,
|
||||
uuid[0] == 'C' ? "crypto" : "stratis",
|
||||
name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* FIXME Also check for mpath no paths */
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
@@ -756,13 +767,15 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(target_type, TARGET_NAME_ERROR))
|
||||
only_error_target = 0;
|
||||
if (only_error_or_zero_target &&
|
||||
strcmp(target_type, TARGET_NAME_ERROR) &&
|
||||
strcmp(target_type, TARGET_NAME_ZERO))
|
||||
only_error_or_zero_target = 0;
|
||||
} while (next);
|
||||
|
||||
/* Skip devices consisting entirely of error targets. */
|
||||
/* Skip devices consisting entirely of error or zero targets. */
|
||||
/* FIXME Deal with device stacked above error targets? */
|
||||
if (check.check_error_target && only_error_target) {
|
||||
if (check.check_error_target && only_error_or_zero_target) {
|
||||
log_debug_activation("%s: Error device %s not usable.",
|
||||
dev_name(dev), name);
|
||||
goto out;
|
||||
@@ -773,7 +786,6 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check)
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
free(vgname);
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
@@ -830,8 +842,7 @@ static int _info(struct cmd_context *cmd,
|
||||
if (strcmp(suffix_position + 1, suffix))
|
||||
continue;
|
||||
|
||||
(void) strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
|
||||
old_style_dlid[sizeof(old_style_dlid) - 1] = '\0';
|
||||
(void) dm_strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
|
||||
if (!_info_run(old_style_dlid, dminfo, read_ahead, seg_status,
|
||||
name_check, with_open_count, with_read_ahead,
|
||||
0, 0))
|
||||
@@ -1113,7 +1124,8 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
const char *dlid,
|
||||
const char *target_type, int wait,
|
||||
const struct logical_volume *lv, dm_percent_t *overall_percent,
|
||||
uint32_t *event_nr, int fail_if_percent_unsupported)
|
||||
uint32_t *event_nr, int fail_if_percent_unsupported,
|
||||
int *interrupted)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
@@ -1134,9 +1146,12 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
if (!(segtype = get_segtype_from_string(dm->cmd, target_type)))
|
||||
return_0;
|
||||
|
||||
if (wait)
|
||||
sigint_allow();
|
||||
|
||||
if (!(dmt = _setup_task_run(wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, &info,
|
||||
name, dlid, event_nr, 0, 0, 0, 0, 0)))
|
||||
return_0;
|
||||
goto_bad;
|
||||
|
||||
if (!info.exists)
|
||||
goto_out;
|
||||
@@ -1204,8 +1219,19 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
display_percent(dm->cmd, *overall_percent));
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
|
||||
bad:
|
||||
if (wait) {
|
||||
sigint_restore();
|
||||
|
||||
if (sigint_caught()) {
|
||||
*interrupted = 1;
|
||||
return_0;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1214,20 +1240,24 @@ static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
|
||||
const struct logical_volume *lv, dm_percent_t *percent,
|
||||
uint32_t *event_nr, int fail_if_percent_unsupported)
|
||||
{
|
||||
int interrupted = 0;
|
||||
|
||||
if (dlid && *dlid) {
|
||||
if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
event_nr, fail_if_percent_unsupported, &interrupted))
|
||||
return 1;
|
||||
|
||||
if (_original_uuid_format_check_required(dm->cmd) &&
|
||||
if (!interrupted &&
|
||||
_original_uuid_format_check_required(dm->cmd) &&
|
||||
_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
|
||||
target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
event_nr, fail_if_percent_unsupported, &interrupted))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported))
|
||||
if (!interrupted && name &&
|
||||
_percent_run(dm, name, NULL, target_type, wait, lv, percent,
|
||||
event_nr, fail_if_percent_unsupported, &interrupted))
|
||||
return 1;
|
||||
|
||||
return_0;
|
||||
@@ -1429,7 +1459,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
|
||||
int dev_manager_raid_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
struct dm_status_raid **status)
|
||||
struct lv_status_raid **status, int *exists)
|
||||
{
|
||||
int r = 0;
|
||||
const char *dlid;
|
||||
@@ -1439,6 +1469,11 @@ int dev_manager_raid_status(struct dev_manager *dm,
|
||||
char *type = NULL;
|
||||
char *params = NULL;
|
||||
const char *layer = lv_layer(lv);
|
||||
struct dm_status_raid *sr;
|
||||
|
||||
*exists = -1;
|
||||
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
|
||||
return_0;
|
||||
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
|
||||
return_0;
|
||||
@@ -1446,8 +1481,11 @@ int dev_manager_raid_status(struct dev_manager *dm,
|
||||
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!info.exists)
|
||||
goto_out;
|
||||
if (!(*exists = info.exists))
|
||||
goto out;
|
||||
|
||||
log_debug_activation("Checking raid status for volume %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms);
|
||||
|
||||
@@ -1459,9 +1497,13 @@ int dev_manager_raid_status(struct dev_manager *dm,
|
||||
|
||||
/* FIXME Check there's only one target */
|
||||
|
||||
if (!dm_get_status_raid(dm->mem, params, status))
|
||||
if (!dm_get_status_raid(dm->mem, params, &sr))
|
||||
goto_out;
|
||||
|
||||
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
|
||||
(*status)->raid = sr;
|
||||
(*status)->in_sync = dm_make_percent(sr->insync_regions, sr->total_regions);
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
@@ -1550,7 +1592,7 @@ out:
|
||||
|
||||
int dev_manager_cache_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
struct lv_status_cache **status)
|
||||
struct lv_status_cache **status, int *exists)
|
||||
{
|
||||
int r = 0;
|
||||
const char *dlid;
|
||||
@@ -1561,14 +1603,18 @@ int dev_manager_cache_status(struct dev_manager *dm,
|
||||
char *params = NULL;
|
||||
struct dm_status_cache *c;
|
||||
|
||||
*exists = -1;
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0)))
|
||||
return_0;
|
||||
|
||||
if (!info.exists)
|
||||
goto_out;
|
||||
if (!(*exists = info.exists))
|
||||
goto out;
|
||||
|
||||
log_debug_activation("Checking status for cache volume %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms);
|
||||
|
||||
@@ -1613,7 +1659,7 @@ out:
|
||||
|
||||
int dev_manager_thin_pool_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv, int flush,
|
||||
struct lv_status_thin_pool **status)
|
||||
struct lv_status_thin_pool **status, int *exists)
|
||||
{
|
||||
struct dm_status_thin_pool *dm_status;
|
||||
const char *dlid;
|
||||
@@ -1624,6 +1670,10 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
|
||||
char *params = NULL;
|
||||
int r = 0;
|
||||
|
||||
*exists = -1;
|
||||
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin_pool))))
|
||||
return_0;
|
||||
|
||||
/* Build dlid for the thin pool layer */
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
|
||||
return_0;
|
||||
@@ -1631,8 +1681,11 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
|
||||
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
|
||||
return_0;
|
||||
|
||||
if (!info.exists)
|
||||
goto_out;
|
||||
if (!(*exists = info.exists))
|
||||
goto out;
|
||||
|
||||
log_debug_activation("Checking thin pool status for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms);
|
||||
|
||||
@@ -1645,9 +1698,6 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
|
||||
if (!dm_get_status_thin_pool(dm->mem, params, &dm_status))
|
||||
goto_out;
|
||||
|
||||
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin_pool))))
|
||||
goto_out;
|
||||
|
||||
(*status)->mem = dm->mem;
|
||||
(*status)->thin_pool = dm_status;
|
||||
|
||||
@@ -1670,7 +1720,7 @@ out:
|
||||
|
||||
int dev_manager_thin_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv, int flush,
|
||||
struct lv_status_thin **status)
|
||||
struct lv_status_thin **status, int *exists)
|
||||
{
|
||||
struct dm_status_thin *dm_status;
|
||||
const char *dlid;
|
||||
@@ -1682,14 +1732,21 @@ int dev_manager_thin_status(struct dev_manager *dm,
|
||||
uint64_t csize;
|
||||
int r = 0;
|
||||
|
||||
*exists = -1;
|
||||
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin))))
|
||||
return_0;
|
||||
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
|
||||
return_0;
|
||||
|
||||
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
|
||||
return_0;
|
||||
|
||||
if (!info.exists)
|
||||
goto_out;
|
||||
if (!(*exists = info.exists))
|
||||
goto out;
|
||||
|
||||
log_debug_activation("Checking thin status for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms);
|
||||
|
||||
@@ -1702,9 +1759,6 @@ int dev_manager_thin_status(struct dev_manager *dm,
|
||||
if (!dm_get_status_thin(dm->mem, params, &dm_status))
|
||||
goto_out;
|
||||
|
||||
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin))))
|
||||
goto_out;
|
||||
|
||||
(*status)->mem = dm->mem;
|
||||
(*status)->thin = dm_status;
|
||||
|
||||
@@ -1737,7 +1791,7 @@ out:
|
||||
*/
|
||||
int dev_manager_thin_device_id(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
uint32_t *device_id)
|
||||
uint32_t *device_id, int *exists)
|
||||
{
|
||||
const char *dlid;
|
||||
struct dm_task *dmt;
|
||||
@@ -1747,6 +1801,7 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
|
||||
const char *layer = lv_layer(lv);
|
||||
int r = 0;
|
||||
|
||||
*exists = -1;
|
||||
if (lv_is_merging_origin(lv) && !lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
|
||||
/* If the merge has already happened, that table
|
||||
* can already be using correct LV without -real layer */
|
||||
@@ -1759,8 +1814,11 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
|
||||
if (!(dmt = _setup_task_run(DM_DEVICE_TABLE, &info, NULL, dlid, 0, 0, 0, 0, 1, 0)))
|
||||
return_0;
|
||||
|
||||
if (!info.exists)
|
||||
goto_out;
|
||||
if (!(*exists = info.exists))
|
||||
goto out;
|
||||
|
||||
log_debug_activation("Checking device id for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
if (dm_get_next_target(dmt, NULL, &start, &length,
|
||||
&target_type, ¶ms)) {
|
||||
@@ -1789,11 +1847,9 @@ out:
|
||||
}
|
||||
|
||||
int dev_manager_vdo_pool_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
struct lv_status_vdo **vdo_status,
|
||||
int flush)
|
||||
const struct logical_volume *lv, int flush,
|
||||
struct lv_status_vdo **status, int *exists)
|
||||
{
|
||||
struct lv_status_vdo *status;
|
||||
const char *dlid;
|
||||
struct dm_info info;
|
||||
uint64_t start, length;
|
||||
@@ -1802,12 +1858,9 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
|
||||
char *params = NULL;
|
||||
int r = 0;
|
||||
|
||||
*vdo_status = NULL;
|
||||
|
||||
if (!(status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_vdo)))) {
|
||||
log_error("Cannot allocate VDO status structure.");
|
||||
return 0;
|
||||
}
|
||||
*exists = -1;
|
||||
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_vdo))))
|
||||
return_0;
|
||||
|
||||
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
|
||||
return_0;
|
||||
@@ -1815,8 +1868,11 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
|
||||
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
|
||||
return_0;
|
||||
|
||||
if (!info.exists)
|
||||
goto_out;
|
||||
if (!(*exists = info.exists))
|
||||
goto out;
|
||||
|
||||
log_debug_activation("Checking VDO pool status for LV %s.",
|
||||
display_lvname(lv));
|
||||
|
||||
if (dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms)) {
|
||||
log_error("More then one table line found for %s.",
|
||||
@@ -1830,11 +1886,10 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!parse_vdo_pool_status(dm->mem, lv, params, status))
|
||||
if (!parse_vdo_pool_status(dm->mem, lv, params, *status))
|
||||
goto_out;
|
||||
|
||||
status->mem = dm->mem;
|
||||
*vdo_status = status;
|
||||
(*status)->mem = dm->mem;
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
@@ -2270,21 +2325,31 @@ static int _pool_callback(struct dm_tree_node *node,
|
||||
const struct pool_cb_data *data = cb_data;
|
||||
const struct logical_volume *pool_lv = data->pool_lv;
|
||||
const struct logical_volume *mlv = first_seg(pool_lv)->metadata_lv;
|
||||
struct cmd_context *cmd = pool_lv->vg->cmd;
|
||||
long buf[64 / sizeof(long)]; /* buffer for short disk header (64B) */
|
||||
int args = 0;
|
||||
char *mpath;
|
||||
const char *argv[19] = { /* Max supported 15 args */
|
||||
find_config_tree_str_allow_empty(pool_lv->vg->cmd, data->exec, NULL)
|
||||
find_config_tree_str_allow_empty(cmd, data->exec, NULL)
|
||||
};
|
||||
|
||||
if (!*argv[0]) /* *_check tool is unconfigured/disabled with "" setting */
|
||||
return 1;
|
||||
|
||||
if (!(mpath = lv_dmpath_dup(data->dm->mem, mlv))) {
|
||||
log_error("Failed to build device path for checking pool metadata %s.",
|
||||
display_lvname(mlv));
|
||||
return 0;
|
||||
if (lv_is_cache_vol(pool_lv)) {
|
||||
if (!(mpath = lv_dmpath_suffix_dup(data->dm->mem, pool_lv, "-cmeta"))) {
|
||||
log_error("Failed to build device path for checking cachevol metadata %s.",
|
||||
display_lvname(pool_lv));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!(mpath = lv_dmpath_dup(data->dm->mem, mlv))) {
|
||||
log_error("Failed to build device path for checking pool metadata %s.",
|
||||
display_lvname(mlv));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
log_debug("Running check command on %s", mpath);
|
||||
|
||||
if (data->skip_zero) {
|
||||
if ((fd = open(mpath, O_RDONLY)) < 0) {
|
||||
@@ -2312,7 +2377,7 @@ static int _pool_callback(struct dm_tree_node *node,
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cn = find_config_tree_array(mlv->vg->cmd, data->opts, NULL))) {
|
||||
if (!(cn = find_config_tree_array(cmd, data->opts, NULL))) {
|
||||
log_error(INTERNAL_ERROR "Unable to find configuration for pool check options.");
|
||||
return 0;
|
||||
}
|
||||
@@ -2334,7 +2399,7 @@ static int _pool_callback(struct dm_tree_node *node,
|
||||
|
||||
argv[++args] = mpath;
|
||||
|
||||
if (!(ret = exec_cmd(pool_lv->vg->cmd, (const char * const *)argv,
|
||||
if (!(ret = exec_cmd(cmd, (const char * const *)argv,
|
||||
&status, 0))) {
|
||||
if (status == ENOENT) {
|
||||
log_warn("WARNING: Check is skipped, please install recommended missing binary %s!",
|
||||
@@ -2343,7 +2408,7 @@ static int _pool_callback(struct dm_tree_node *node,
|
||||
}
|
||||
|
||||
if ((data->version.maj || data->version.min || data->version.patch) &&
|
||||
!_check_tool_version(pool_lv->vg->cmd, argv[0],
|
||||
!_check_tool_version(cmd, argv[0],
|
||||
data->version.maj, data->version.min, data->version.patch)) {
|
||||
log_warn("WARNING: Check is skipped, please upgrade installed version of %s!",
|
||||
argv[0]);
|
||||
@@ -2387,10 +2452,6 @@ static int _pool_register_callback(struct dev_manager *dm,
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
/* Skip for single-device cache pool */
|
||||
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv))
|
||||
return 1;
|
||||
|
||||
if (!(data = dm_pool_zalloc(dm->mem, sizeof(*data)))) {
|
||||
log_error("Failed to allocated path for callback.");
|
||||
return 0;
|
||||
@@ -3483,6 +3544,12 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
!_pool_register_callback(dm, dnode, lv))
|
||||
return_0;
|
||||
|
||||
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv) &&
|
||||
/* Register callback only for layer activation or non-layered cache LV */
|
||||
(layer || !lv_layer(lv)) &&
|
||||
!_pool_register_callback(dm, dnode, lv))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* Update tables for ANY PVMOVE holders for active LV where the name starts with 'pvmove',
|
||||
* but it's not anymore PVMOVE LV and also it's not a PVMOVE _mimage LV.
|
||||
|
||||
@@ -59,7 +59,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
|
||||
dm_percent_t *percent, uint32_t *event_nr);
|
||||
int dev_manager_raid_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
struct dm_status_raid **status);
|
||||
struct lv_status_raid **status, int *exists);
|
||||
int dev_manager_raid_message(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
const char *msg);
|
||||
@@ -68,20 +68,19 @@ int dev_manager_writecache_message(struct dev_manager *dm,
|
||||
const char *msg);
|
||||
int dev_manager_cache_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
struct lv_status_cache **status);
|
||||
struct lv_status_cache **status, int *exists);
|
||||
int dev_manager_thin_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv, int flush,
|
||||
struct lv_status_thin **status);
|
||||
struct lv_status_thin **status, int *exists);
|
||||
int dev_manager_thin_device_id(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
uint32_t *device_id);
|
||||
uint32_t *device_id, int *exist);
|
||||
int dev_manager_thin_pool_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv, int flush,
|
||||
struct lv_status_thin_pool **status);
|
||||
struct lv_status_thin_pool **status, int *exists);
|
||||
int dev_manager_vdo_pool_status(struct dev_manager *dm,
|
||||
const struct logical_volume *lv,
|
||||
struct lv_status_vdo **vdo_status,
|
||||
int flush);
|
||||
const struct logical_volume *lv, int flush,
|
||||
struct lv_status_vdo **status, int *exists);
|
||||
int dev_manager_suspend(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
struct lv_activate_opts *laopts, int lockfs, int flush_required);
|
||||
int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv,
|
||||
|
||||
@@ -76,7 +76,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
|
||||
if (dir_exists(vg_path) && dm_is_empty_dir(vg_path)) {
|
||||
log_very_verbose("Removing directory %s", vg_path);
|
||||
rmdir(vg_path);
|
||||
}
|
||||
@@ -93,7 +93,7 @@ static void _rm_blks(const char *dir)
|
||||
DIR *d;
|
||||
|
||||
if (!(d = opendir(dir))) {
|
||||
log_sys_error("opendir", dir);
|
||||
log_sys_debug("opendir", dir);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ static void _rm_blks(const char *dir)
|
||||
continue;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
|
||||
log_error("Couldn't create path for %s", name);
|
||||
log_debug("Couldn't create path for %s.", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -113,12 +113,12 @@ static void _rm_blks(const char *dir)
|
||||
continue;
|
||||
log_very_verbose("Removing %s", path);
|
||||
if (unlink(path) < 0)
|
||||
log_sys_error("unlink", path);
|
||||
log_sys_debug("unlink", path);
|
||||
}
|
||||
}
|
||||
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", dir);
|
||||
log_sys_debug("closedir", dir);
|
||||
}
|
||||
|
||||
static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
@@ -169,7 +169,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
|
||||
|
||||
log_very_verbose("Removing %s", lvm1_group_path);
|
||||
if (unlink(lvm1_group_path) < 0)
|
||||
log_sys_error("unlink", lvm1_group_path);
|
||||
log_sys_debug("unlink", lvm1_group_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
354
lib/cache/lvmcache.c
vendored
354
lib/cache/lvmcache.c
vendored
@@ -18,6 +18,7 @@
|
||||
#include "lib/cache/lvmcache.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/dev-cache.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "lib/locking/locking.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/mm/memlock.h"
|
||||
@@ -87,6 +88,9 @@ static int _vgs_locked = 0;
|
||||
static int _found_duplicate_vgnames = 0;
|
||||
static int _outdated_warning = 0;
|
||||
|
||||
static const char *_scan_lock_global_file = DEFAULT_RUN_DIR "/scan_lock_global";
|
||||
static int _scan_lock_global_file_exists = 0;
|
||||
|
||||
int lvmcache_init(struct cmd_context *cmd)
|
||||
{
|
||||
/*
|
||||
@@ -100,13 +104,13 @@ int lvmcache_init(struct cmd_context *cmd)
|
||||
dm_list_init(&_unused_duplicates);
|
||||
dm_list_init(&_prev_unused_duplicate_devs);
|
||||
|
||||
if (!(_vgname_hash = dm_hash_create(128)))
|
||||
if (!(_vgname_hash = dm_hash_create(127)))
|
||||
return 0;
|
||||
|
||||
if (!(_vgid_hash = dm_hash_create(128)))
|
||||
if (!(_vgid_hash = dm_hash_create(126)))
|
||||
return 0;
|
||||
|
||||
if (!(_pvid_hash = dm_hash_create(128)))
|
||||
if (!(_pvid_hash = dm_hash_create(125)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@@ -125,6 +129,19 @@ void lvmcache_unlock_vgname(const char *vgname)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int lvmcache_vg_info_count(void)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
unsigned int count = 0;
|
||||
|
||||
dm_list_iterate_items(vginfo, &_vginfos) {
|
||||
if (is_orphan_vg(vginfo->vgname))
|
||||
continue;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int lvmcache_found_duplicate_vgnames(void)
|
||||
{
|
||||
return _found_duplicate_vgnames;
|
||||
@@ -507,6 +524,25 @@ static const char *_get_pvsummary_device_hint(char *pvid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *_get_pvsummary_device_id(char *pvid, const char **device_id_type)
|
||||
{
|
||||
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct pv_list *pvl;
|
||||
|
||||
dm_list_iterate_items(vginfo, &_vginfos) {
|
||||
dm_list_iterate_items(pvl, &vginfo->pvsummaries) {
|
||||
(void) dm_strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s));
|
||||
if (!strcmp(pvid_s, pvid)) {
|
||||
*device_id_type = pvl->pv->device_id_type;
|
||||
return pvl->pv->device_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if any PVs in vg->pvs have the same PVID as any
|
||||
* entries in _unused_duplicates.
|
||||
@@ -612,6 +648,8 @@ static void _choose_duplicates(struct cmd_context *cmd,
|
||||
struct device_list *devl, *devl_safe, *devl_add, *devl_del;
|
||||
struct lvmcache_info *info;
|
||||
struct device *dev1, *dev2;
|
||||
const char *device_id = NULL, *device_id_type = NULL;
|
||||
const char *idname1 = NULL, *idname2 = NULL;
|
||||
uint32_t dev1_major, dev1_minor, dev2_major, dev2_minor;
|
||||
uint64_t dev1_size, dev2_size, pvsummary_size;
|
||||
int in_subsys1, in_subsys2;
|
||||
@@ -620,6 +658,7 @@ static void _choose_duplicates(struct cmd_context *cmd,
|
||||
int has_lv1, has_lv2;
|
||||
int same_size1, same_size2;
|
||||
int same_name1 = 0, same_name2 = 0;
|
||||
int same_id1 = 0, same_id2 = 0;
|
||||
int prev_unchosen1, prev_unchosen2;
|
||||
int change;
|
||||
|
||||
@@ -750,6 +789,19 @@ next:
|
||||
same_name2 = !strcmp(device_hint, dev_name(dev2));
|
||||
}
|
||||
|
||||
if ((device_id = _get_pvsummary_device_id(devl->dev->pvid, &device_id_type))) {
|
||||
uint16_t idtype = idtype_from_str(device_id_type);
|
||||
|
||||
if (idtype) {
|
||||
idname1 = device_id_system_read(cmd, dev1, idtype);
|
||||
idname2 = device_id_system_read(cmd, dev2, idtype);
|
||||
}
|
||||
if (idname1)
|
||||
same_id1 = !strcmp(idname1, device_id);
|
||||
if (idname2)
|
||||
same_id2 = !strcmp(idname2, device_id);
|
||||
}
|
||||
|
||||
has_lv1 = (dev1->flags & DEV_USED_FOR_LV) ? 1 : 0;
|
||||
has_lv2 = (dev2->flags & DEV_USED_FOR_LV) ? 1 : 0;
|
||||
|
||||
@@ -768,6 +820,12 @@ next:
|
||||
dev_name(dev2), dev2_major, dev2_minor,
|
||||
device_hint ?: "none");
|
||||
|
||||
log_debug_cache("PV %s: device_id %s. %s is %s. %s is %s.",
|
||||
devl->dev->pvid,
|
||||
device_id ?: ".",
|
||||
dev_name(dev1), idname1 ?: ".",
|
||||
dev_name(dev2), idname2 ?: ".");
|
||||
|
||||
log_debug_cache("PV %s: size %llu. %s is %llu. %s is %llu.",
|
||||
devl->dev->pvid,
|
||||
(unsigned long long)pvsummary_size,
|
||||
@@ -808,6 +866,13 @@ next:
|
||||
} else if (prev_unchosen2 && !prev_unchosen1) {
|
||||
/* keep 1 (NB when unchosen is set we unprefer) */
|
||||
reason = "of previous preference";
|
||||
} else if (same_id1 && !same_id2) {
|
||||
/* keep 1 */
|
||||
reason = "device id";
|
||||
} else if (same_id2 && !same_id1) {
|
||||
/* change to 2 */
|
||||
change = 1;
|
||||
reason = "device id";
|
||||
} else if (has_lv1 && !has_lv2) {
|
||||
/* keep 1 */
|
||||
reason = "device is used by LV";
|
||||
@@ -1028,6 +1093,127 @@ int lvmcache_label_reopen_vg_rw(struct cmd_context *cmd, const char *vgname, con
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* During label_scan, the md component filter is applied to each device after
|
||||
* the device header has been read. This often just checks the start of the
|
||||
* device for an md header, and if the device has an md header at the end, the
|
||||
* md component filter wouldn't detect it. In some cases, the full md filter
|
||||
* is enabled during label_scan, in which case the md component filter will
|
||||
* check both the start and end of the device for md superblocks.
|
||||
*
|
||||
* In this function, after label_scan is done, we may decide that a full md
|
||||
* component check should be applied to a device if it hasn't been yet. This
|
||||
* is based on some clues or uncertainty that arose during label_scan.
|
||||
*
|
||||
* label_scan saved metadata info about pvs in lvmcache pvsummaries. That
|
||||
* pvsummary metadata includes the pv size. So now, after label_scan is done,
|
||||
* we can compare the pv size with the size of the device the pv was read from.
|
||||
* If the pv and dev sizes do not match, it can sometimes be normal, but other
|
||||
* times it can be a clue that label_scan mistakenly read the pv from an md
|
||||
* component device instead of from the md device itself. So for unmatching
|
||||
* sizes, we do a full md component check on the device.
|
||||
*/
|
||||
|
||||
void lvmcache_extra_md_component_checks(struct cmd_context *cmd)
|
||||
{
|
||||
struct lvmcache_vginfo *vginfo, *vginfo2;
|
||||
struct lvmcache_info *info, *info2;
|
||||
struct device *dev;
|
||||
const char *device_hint;
|
||||
uint64_t devsize, pvsize;
|
||||
int do_check_size, do_check_name;
|
||||
int md_check_start;
|
||||
|
||||
/*
|
||||
* use_full_md_check: if set then no more needs to be done here,
|
||||
* all devs have already been fully checked as md components.
|
||||
*
|
||||
* md_component_checks "full": use_full_md_check was set, and caused
|
||||
* filter-md to already do a full check, no more is needed.
|
||||
*
|
||||
* md_component_checks "start": skip end of device md component checks,
|
||||
* the start of device has already been checked by filter-md.
|
||||
*
|
||||
* md_component_checks "auto": do full checks only when lvm finds some
|
||||
* clue or reasons to believe it might be useful, which is what this
|
||||
* function is looking for.
|
||||
*/
|
||||
if (!cmd->md_component_detection || cmd->use_full_md_check ||
|
||||
!strcmp(cmd->md_component_checks, "none"))
|
||||
return;
|
||||
|
||||
md_check_start = !strcmp(cmd->md_component_checks, "start");
|
||||
|
||||
/*
|
||||
* We want to avoid extra scanning for end-of-device md superblocks
|
||||
* whenever possible, since it can add up to a lot of extra io if we're
|
||||
* not careful to do it only when there's a good reason to believe a
|
||||
* dev is an md component.
|
||||
*
|
||||
* If the pv/dev size mismatches are commonly occuring for
|
||||
* non-md-components then we'll want to stop using that as a trigger
|
||||
* for the full md check.
|
||||
*/
|
||||
|
||||
dm_list_iterate_items_safe(vginfo, vginfo2, &_vginfos) {
|
||||
dm_list_iterate_items_safe(info, info2, &vginfo->infos) {
|
||||
dev = info->dev;
|
||||
device_hint = _get_pvsummary_device_hint(dev->pvid);
|
||||
pvsize = _get_pvsummary_size(dev->pvid);
|
||||
devsize = dev->size;
|
||||
do_check_size = 0;
|
||||
do_check_name = 0;
|
||||
|
||||
if (!devsize && !dev_get_size(dev, &devsize))
|
||||
log_debug("No size for %s.", dev_name(dev));
|
||||
|
||||
/*
|
||||
* PV larger than dev not common; dev larger than PV
|
||||
* can be common, but not as often as PV larger.
|
||||
*/
|
||||
if (pvsize && devsize && (pvsize != devsize))
|
||||
do_check_size = 1;
|
||||
if (device_hint && !strncmp(device_hint, "/dev/md", 7))
|
||||
do_check_name = 1;
|
||||
|
||||
if (!do_check_size && !do_check_name)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If only the size is different (which can be fairly
|
||||
* common for non-md-component devs) and the user has
|
||||
* set "start" to disable full md checks, then skip it.
|
||||
* If the size is different, *and* the device name hint
|
||||
* looks like an md device, then it seems very likely
|
||||
* to be an md component, so do a full check on it even
|
||||
* if the user has set "start".
|
||||
*
|
||||
* In "auto" mode, do a full check if either the size
|
||||
* or the name indicates a possible md component.
|
||||
*/
|
||||
if (do_check_size && !do_check_name && md_check_start) {
|
||||
log_debug("extra md component check skip %llu %llu device_hint %s dev %s",
|
||||
(unsigned long long)pvsize, (unsigned long long)devsize,
|
||||
device_hint ?: "none", dev_name(dev));
|
||||
continue;
|
||||
}
|
||||
|
||||
log_debug("extra md component check %llu %llu device_hint %s dev %s",
|
||||
(unsigned long long)pvsize, (unsigned long long)devsize,
|
||||
device_hint ?: "none", dev_name(dev));
|
||||
|
||||
if (dev_is_md_component(dev, NULL, 1)) {
|
||||
log_debug("dropping PV from md component %s", dev_name(dev));
|
||||
dev->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
/* lvmcache_del will also delete vginfo if info was last one */
|
||||
lvmcache_del(info);
|
||||
lvmcache_del_dev_from_duplicates(dev);
|
||||
cmd->filter->wipe(cmd, cmd->filter, dev, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Uses label_scan to populate lvmcache with 'vginfo' struct for each VG
|
||||
* and associated 'info' structs for those VGs. Only VG summary information
|
||||
@@ -1056,14 +1242,13 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
{
|
||||
struct dm_list del_cache_devs;
|
||||
struct dm_list add_cache_devs;
|
||||
struct dm_list renamed_devs;
|
||||
struct lvmcache_info *info;
|
||||
struct lvmcache_vginfo *vginfo;
|
||||
struct device_list *devl;
|
||||
int vginfo_count = 0;
|
||||
|
||||
int r = 0;
|
||||
dm_list_init(&renamed_devs);
|
||||
|
||||
log_debug_cache("Finding VG info");
|
||||
log_debug_cache("lvmcache label scan begin");
|
||||
|
||||
/*
|
||||
* Duplicates found during this label scan are added to _initial_duplicates.
|
||||
@@ -1075,13 +1260,24 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
* Do the actual scanning. This populates lvmcache
|
||||
* with infos/vginfos based on reading headers from
|
||||
* each device, and a vg summary from each mda.
|
||||
*
|
||||
* Note that this will *skip* scanning a device if
|
||||
* an info struct already exists in lvmcache for
|
||||
* the device.
|
||||
*/
|
||||
label_scan(cmd);
|
||||
|
||||
/*
|
||||
* When devnames are used as device ids (which is dispreferred),
|
||||
* changing/unstable devnames can lead to entries in the devices file
|
||||
* not being matched to a dev even if the PV is present on the system.
|
||||
* Or, a devices file entry may have been matched to the wrong device
|
||||
* (with the previous name) that does not have the PVID specified in
|
||||
* the entry. This function detects that problem, scans labels on all
|
||||
* devs on the system to find the missing PVIDs, and corrects the
|
||||
* devices file. We then need to run label scan on these correct
|
||||
* devices.
|
||||
*/
|
||||
device_ids_find_renamed_devs(cmd, &renamed_devs, NULL, 0);
|
||||
if (!dm_list_empty(&renamed_devs))
|
||||
label_scan_devs(cmd, cmd->filter, &renamed_devs);
|
||||
|
||||
/*
|
||||
* _choose_duplicates() returns:
|
||||
*
|
||||
@@ -1125,17 +1321,8 @@ int lvmcache_label_scan(struct cmd_context *cmd)
|
||||
_warn_unused_duplicates(cmd);
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
dm_list_iterate_items(vginfo, &_vginfos) {
|
||||
if (is_orphan_vg(vginfo->vgname))
|
||||
continue;
|
||||
vginfo_count++;
|
||||
}
|
||||
|
||||
log_debug_cache("Found VG info for %d VGs", vginfo_count);
|
||||
|
||||
return r;
|
||||
log_debug_cache("lvmcache label scan done");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lvmcache_get_vgnameids(struct cmd_context *cmd,
|
||||
@@ -1222,8 +1409,7 @@ static void _free_vginfo(struct lvmcache_vginfo *vginfo)
|
||||
free(vginfo->vgname);
|
||||
free(vginfo->system_id);
|
||||
free(vginfo->creation_host);
|
||||
if (vginfo->lock_type)
|
||||
free(vginfo->lock_type);
|
||||
free(vginfo->lock_type);
|
||||
free(vginfo);
|
||||
}
|
||||
|
||||
@@ -2559,19 +2745,115 @@ bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const c
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint64_t _max_metadata_size;
|
||||
/*
|
||||
* max_size_bytes and max_size_percent may come from different areas and
|
||||
* different vgs because of different area sizes.
|
||||
*/
|
||||
static uint64_t _max_metadata_size_bytes;
|
||||
static dm_percent_t _max_metadata_size_percent = DM_PERCENT_INVALID;
|
||||
|
||||
void lvmcache_save_metadata_size(uint64_t val)
|
||||
void lvmcache_save_metadata_size_bytes(uint64_t val)
|
||||
{
|
||||
if (!_max_metadata_size)
|
||||
_max_metadata_size = val;
|
||||
else if (_max_metadata_size < val)
|
||||
_max_metadata_size = val;
|
||||
if (!_max_metadata_size_bytes)
|
||||
_max_metadata_size_bytes = val;
|
||||
else if (_max_metadata_size_bytes < val)
|
||||
_max_metadata_size_bytes = val;
|
||||
}
|
||||
|
||||
uint64_t lvmcache_max_metadata_size(void)
|
||||
uint64_t lvmcache_max_metadata_size_bytes(void)
|
||||
{
|
||||
return _max_metadata_size;
|
||||
return _max_metadata_size_bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: enable/disable scan_lock_global with config setting:
|
||||
* y: always use it
|
||||
* n: never use it
|
||||
* auto (default): use based on /run/lvm/scan_lock_global
|
||||
*/
|
||||
void lvmcache_save_metadata_size_percent(uint64_t meta_size, uint64_t mdah_size)
|
||||
{
|
||||
|
||||
dm_percent_t pc = dm_make_percent(meta_size, mdah_size);
|
||||
|
||||
if (pc == DM_PERCENT_INVALID || pc == DM_PERCENT_FAILED ||
|
||||
pc == DM_PERCENT_0 || pc == DM_PERCENT_1)
|
||||
return;
|
||||
|
||||
if (_max_metadata_size_percent == DM_PERCENT_INVALID) {
|
||||
_max_metadata_size_percent = pc;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_max_metadata_size_percent < pc)
|
||||
_max_metadata_size_percent = pc;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: make the percent at which scan_lock_global is used
|
||||
* configurable?
|
||||
*/
|
||||
#define SCAN_LOCK_GLOBAL_METADATA_PERCENT (DM_PERCENT_1 * 25)
|
||||
|
||||
void set_scan_lock_global(struct cmd_context *cmd)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (_max_metadata_size_percent == DM_PERCENT_INVALID)
|
||||
return;
|
||||
|
||||
if (_max_metadata_size_percent >= SCAN_LOCK_GLOBAL_METADATA_PERCENT) {
|
||||
if (_scan_lock_global_file_exists)
|
||||
return;
|
||||
log_debug("Creating %s.", _scan_lock_global_file);
|
||||
if (!(fp = fopen(_scan_lock_global_file, "w")))
|
||||
return;
|
||||
if (fclose(fp))
|
||||
stack;
|
||||
} else {
|
||||
if (_scan_lock_global_file_exists) {
|
||||
log_debug("Unlinking %s.", _scan_lock_global_file);
|
||||
if (unlink(_scan_lock_global_file))
|
||||
stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int do_scan_lock_global(struct cmd_context *cmd, int *gl_ex)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if (cmd->nolocking)
|
||||
return 0;
|
||||
|
||||
/* global lock is already held */
|
||||
if (cmd->lockf_global_ex)
|
||||
return 0;
|
||||
|
||||
if (!stat(_scan_lock_global_file, &buf)) {
|
||||
_scan_lock_global_file_exists = 1;
|
||||
|
||||
/*
|
||||
* Tell the caller to use sh or ex. A command that may write
|
||||
* vg metadata should use ex, otherwise sh.
|
||||
*
|
||||
* lockd_vg_default_sh/LOCKD_VG_SH is set for commands that
|
||||
* do not modify vg metadata.
|
||||
*
|
||||
* FIXME: this variable/flag was previously used only for
|
||||
* lvmlockd locking logic, but is now more general, so
|
||||
* it should be renamed.
|
||||
*/
|
||||
if (cmd->lockd_vg_default_sh)
|
||||
*gl_ex = 0;
|
||||
else
|
||||
*gl_ex = 1;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid)
|
||||
@@ -2635,7 +2917,7 @@ void lvmcache_get_outdated_devs(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
dm_list_iterate_items(info, &vginfo->outdated_infos) {
|
||||
if (!(devl = zalloc(sizeof(*devl))))
|
||||
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
|
||||
return;
|
||||
devl->dev = info->dev;
|
||||
dm_list_add(devs, &devl->list);
|
||||
@@ -2722,6 +3004,12 @@ const char *dev_filtered_reason(struct device *dev)
|
||||
return "device is too small (pv_min_size)";
|
||||
if (dev->filtered_flags & DEV_FILTERED_UNUSABLE)
|
||||
return "device is not in a usable state";
|
||||
if (dev->filtered_flags & DEV_FILTERED_DEVICES_FILE)
|
||||
return "device is not in devices file";
|
||||
if (dev->filtered_flags & DEV_FILTERED_DEVICES_LIST)
|
||||
return "device is not in devices list";
|
||||
if (dev->filtered_flags & DEV_FILTERED_IS_LV)
|
||||
return "device is an LV";
|
||||
|
||||
/* flag has not been added here */
|
||||
if (dev->filtered_flags)
|
||||
|
||||
13
lib/cache/lvmcache.h
vendored
13
lib/cache/lvmcache.h
vendored
@@ -183,8 +183,9 @@ bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const c
|
||||
|
||||
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid);
|
||||
|
||||
uint64_t lvmcache_max_metadata_size(void);
|
||||
void lvmcache_save_metadata_size(uint64_t val);
|
||||
uint64_t lvmcache_max_metadata_size_bytes(void);
|
||||
void lvmcache_save_metadata_size_bytes(uint64_t val);
|
||||
void lvmcache_save_metadata_size_percent(uint64_t meta_size, uint64_t mdah_size);
|
||||
|
||||
int dev_in_device_list(struct device *dev, struct dm_list *head);
|
||||
|
||||
@@ -222,4 +223,12 @@ const char *devname_error_reason(const char *devname);
|
||||
|
||||
struct metadata_area *lvmcache_get_dev_mda(struct device *dev, int mda_num);
|
||||
|
||||
void lvmcache_extra_md_component_checks(struct cmd_context *cmd);
|
||||
|
||||
unsigned int lvmcache_vg_info_count(void);
|
||||
|
||||
void set_scan_lock_global(struct cmd_context *cmd);
|
||||
int do_scan_lock_global(struct cmd_context *cmd, int *gl_ex);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "lib/cache/lvmcache.h"
|
||||
#include "lib/format_text/archiver.h"
|
||||
#include "lib/lvmpolld/lvmpolld-client.h"
|
||||
#include "lib/device/device_id.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -229,7 +230,7 @@ static void _get_sysfs_dir(struct cmd_context *cmd, char *buf, size_t buf_size)
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy(buf, sys_mnt, buf_size);
|
||||
(void) dm_strncpy(buf, sys_mnt, buf_size);
|
||||
}
|
||||
|
||||
static uint32_t _parse_debug_fields(struct cmd_context *cmd, int cfg, const char *cfgname)
|
||||
@@ -660,6 +661,8 @@ static int _process_config(struct cmd_context *cmd)
|
||||
*/
|
||||
cmd->default_settings.udev_fallback = udev_disabled ? 1 : -1;
|
||||
|
||||
cmd->default_settings.issue_discards = find_config_tree_bool(cmd, devices_issue_discards_CFG, NULL);
|
||||
|
||||
init_retry_deactivation(find_config_tree_bool(cmd, activation_retry_deactivation_CFG, NULL));
|
||||
|
||||
init_activation_checks(find_config_tree_bool(cmd, activation_checks_CFG, NULL));
|
||||
@@ -963,8 +966,8 @@ static void _destroy_config(struct cmd_context *cmd)
|
||||
/* CONFIG_FILE/CONFIG_MERGED_FILES */
|
||||
if ((cft = remove_config_tree_by_source(cmd, CONFIG_MERGED_FILES)))
|
||||
config_destroy(cft);
|
||||
else
|
||||
remove_config_tree_by_source(cmd, CONFIG_FILE);
|
||||
else if ((cft = remove_config_tree_by_source(cmd, CONFIG_FILE)))
|
||||
config_destroy(cft);
|
||||
|
||||
dm_list_iterate_items(cfl, &cmd->config_files)
|
||||
config_destroy(cfl->cft);
|
||||
@@ -1066,7 +1069,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_FILTERS 10
|
||||
#define MAX_FILTERS 11
|
||||
|
||||
static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
|
||||
{
|
||||
@@ -1085,6 +1088,9 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
|
||||
* sysfs filter. Only available on 2.6 kernels. Non-critical.
|
||||
* Listed first because it's very efficient at eliminating
|
||||
* unavailable devices.
|
||||
*
|
||||
* TODO: I suspect that using the lvm_type and device_id
|
||||
* filters before this one may be more efficient.
|
||||
*/
|
||||
if (find_config_tree_bool(cmd, devices_sysfs_scan_CFG, NULL)) {
|
||||
if ((filters[nr_filt] = sysfs_filter_create()))
|
||||
@@ -1100,7 +1106,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
|
||||
|
||||
/* global regex filter. Optional. */
|
||||
if ((cn = find_config_tree_node(cmd, devices_global_filter_CFG, NULL))) {
|
||||
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
|
||||
if (!(filters[nr_filt] = regex_filter_create(cn->v, 0, 1))) {
|
||||
log_error("Failed to create global regex device filter");
|
||||
goto bad;
|
||||
}
|
||||
@@ -1109,7 +1115,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
|
||||
|
||||
/* regex filter. Optional. */
|
||||
if ((cn = find_config_tree_node(cmd, devices_filter_CFG, NULL))) {
|
||||
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
|
||||
if (!(filters[nr_filt] = regex_filter_create(cn->v, 1, 0))) {
|
||||
log_error("Failed to create regex device filter");
|
||||
goto bad;
|
||||
}
|
||||
@@ -1123,6 +1129,13 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
|
||||
}
|
||||
nr_filt++;
|
||||
|
||||
/* filter based on the device_ids saved in the devices file */
|
||||
if (!(filters[nr_filt] = deviceid_filter_create(cmd))) {
|
||||
log_error("Failed to create deviceid device filter");
|
||||
goto bad;
|
||||
}
|
||||
nr_filt++;
|
||||
|
||||
/* usable device filter. Required. */
|
||||
if (!(filters[nr_filt] = usable_filter_create(cmd, cmd->dev_types, FILTER_MODE_NO_LVMETAD))) {
|
||||
log_error("Failed to create usabled device filter");
|
||||
@@ -1485,6 +1498,7 @@ int init_run_by_dmeventd(struct cmd_context *cmd)
|
||||
init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
|
||||
init_ignore_suspended_devices(1);
|
||||
init_disable_dmeventd_monitoring(1); /* Lock settings */
|
||||
cmd->run_by_dmeventd = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1717,6 +1731,8 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
|
||||
if (!_init_dev_cache(cmd))
|
||||
goto_out;
|
||||
|
||||
devices_file_init(cmd);
|
||||
|
||||
memlock_init(cmd);
|
||||
|
||||
if (!_init_formats(cmd))
|
||||
@@ -1842,6 +1858,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(cmd, &cmd->formats);
|
||||
|
||||
devices_file_exit(cmd);
|
||||
if (!dev_cache_exit())
|
||||
stack;
|
||||
_destroy_dev_types(cmd);
|
||||
@@ -1921,6 +1938,8 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
if (!_init_dev_cache(cmd))
|
||||
return_0;
|
||||
|
||||
devices_file_init(cmd);
|
||||
|
||||
if (!_init_formats(cmd))
|
||||
return_0;
|
||||
|
||||
@@ -1970,6 +1989,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
_destroy_filters(cmd);
|
||||
if (cmd->mem)
|
||||
dm_pool_destroy(cmd->mem);
|
||||
devices_file_exit(cmd);
|
||||
dev_cache_exit();
|
||||
_destroy_dev_types(cmd);
|
||||
_destroy_tags(cmd);
|
||||
|
||||
@@ -39,7 +39,7 @@ struct config_info {
|
||||
int udev_rules;
|
||||
int udev_sync;
|
||||
int udev_fallback;
|
||||
int cache_vgmetadata;
|
||||
int issue_discards;
|
||||
const char *msg_prefix;
|
||||
const char *fmt_name;
|
||||
const char *dmeventd_executable;
|
||||
@@ -182,14 +182,27 @@ struct cmd_context {
|
||||
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
|
||||
unsigned scan_lvs:1;
|
||||
unsigned wipe_outdated_pvs:1;
|
||||
unsigned enable_devices_list:1; /* command is using --devices option */
|
||||
unsigned enable_devices_file:1; /* command is using devices file */
|
||||
unsigned pending_devices_file:1; /* command may create and enable devices file */
|
||||
unsigned create_edit_devices_file:1; /* command expects to create and/or edit devices file */
|
||||
unsigned edit_devices_file:1; /* command expects to edit devices file */
|
||||
unsigned filter_deviceid_skip:1; /* don't use filter-deviceid */
|
||||
unsigned filter_regex_with_devices_file:1; /* use filter-regex even when devices file is enabled */
|
||||
unsigned filter_nodata_only:1; /* only use filters that do not require data from the dev */
|
||||
unsigned run_by_dmeventd:1; /* command is being run by dmeventd */
|
||||
unsigned sysinit:1; /* --sysinit is used */
|
||||
|
||||
/*
|
||||
* Devices and filtering.
|
||||
*/
|
||||
struct dev_filter *filter;
|
||||
struct dm_list hints;
|
||||
struct dm_list use_devices; /* struct dev_use for each entry in devices file */
|
||||
const char *md_component_checks;
|
||||
const char *search_for_devnames; /* config file setting */
|
||||
const char *devicesfile; /* from --devicesfile option */
|
||||
struct dm_list deviceslist; /* from --devices option, struct dm_str_list */
|
||||
|
||||
/*
|
||||
* Configuration.
|
||||
@@ -221,6 +234,7 @@ struct cmd_context {
|
||||
char system_dir[PATH_MAX];
|
||||
char dev_dir[PATH_MAX];
|
||||
char proc_dir[PATH_MAX];
|
||||
char devices_file_path[PATH_MAX];
|
||||
|
||||
/*
|
||||
* Reporting.
|
||||
@@ -242,6 +256,7 @@ struct cmd_context {
|
||||
unsigned rand_seed;
|
||||
struct dm_list pending_delete; /* list of LVs for removal */
|
||||
struct dm_pool *pending_delete_mem; /* memory pool for pending deletes */
|
||||
int early_lock_vg_mode;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -710,7 +710,7 @@ static struct dm_config_value *_get_def_array_values(struct cmd_context *cmd,
|
||||
return array;
|
||||
}
|
||||
|
||||
if (!(p = token = enc_value = strdup(def_enc_value))) {
|
||||
if (!(token = enc_value = strdup(def_enc_value))) {
|
||||
log_error("_get_def_array_values: strdup failed");
|
||||
return NULL;
|
||||
}
|
||||
@@ -1141,8 +1141,10 @@ int config_def_check(struct cft_check_handle *handle)
|
||||
* sections and settings with full path as a key.
|
||||
* If section name is variable, use '#' as a substitute.
|
||||
*/
|
||||
*vp = 0;
|
||||
*rp = 0;
|
||||
if (!handle->cmd->cft_def_hash) {
|
||||
if (!(handle->cmd->cft_def_hash = dm_hash_create(64))) {
|
||||
if (!(handle->cmd->cft_def_hash = dm_hash_create(60))) {
|
||||
log_error("Failed to create configuration definition hash.");
|
||||
r = 0; goto out;
|
||||
}
|
||||
@@ -1708,6 +1710,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
const char *node_type_name = cn->v ? "option" : "section";
|
||||
char path[CFG_PATH_MAX_LEN];
|
||||
char commentline[MAX_COMMENT_LINE+1];
|
||||
int is_deprecated = 0;
|
||||
|
||||
if (cn->id <= 0)
|
||||
return 1;
|
||||
@@ -1721,13 +1724,14 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
|
||||
cfg_def = cfg_def_get_item_p(cn->id);
|
||||
|
||||
is_deprecated = _def_node_is_deprecated(cfg_def, out->tree_spec);
|
||||
|
||||
if (out->tree_spec->withsummary || out->tree_spec->withcomments) {
|
||||
_cfg_def_make_path(path, sizeof(path), cfg_def->id, cfg_def, 1);
|
||||
fprintf(out->fp, "\n");
|
||||
fprintf(out->fp, "%s# Configuration %s %s.\n", line, node_type_name, path);
|
||||
|
||||
if (out->tree_spec->withcomments &&
|
||||
_def_node_is_deprecated(cfg_def, out->tree_spec))
|
||||
if (out->tree_spec->withcomments && is_deprecated && cfg_def->deprecation_comment)
|
||||
fprintf(out->fp, "%s# %s", line, cfg_def->deprecation_comment);
|
||||
|
||||
if (cfg_def->comment) {
|
||||
@@ -1738,14 +1742,14 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
continue;
|
||||
commentline[0] = '\0';
|
||||
}
|
||||
fprintf(out->fp, "%s# %s\n", line, commentline);
|
||||
fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
|
||||
/* withsummary prints only the first comment line. */
|
||||
if (!out->tree_spec->withcomments)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_def_node_is_deprecated(cfg_def, out->tree_spec))
|
||||
if (is_deprecated)
|
||||
fprintf(out->fp, "%s# This configuration %s is deprecated.\n", line, node_type_name);
|
||||
|
||||
if (cfg_def->flags & CFG_ADVANCED)
|
||||
@@ -1773,7 +1777,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
return_0;
|
||||
fprintf(out->fp, "%s# Available since version %s.\n", line, version);
|
||||
|
||||
if (_def_node_is_deprecated(cfg_def, out->tree_spec)) {
|
||||
if (is_deprecated) {
|
||||
if (!_get_config_node_version(cfg_def->deprecated_since_version, version))
|
||||
return_0;
|
||||
fprintf(out->fp, "%s# Deprecated since version %s.\n", line, version);
|
||||
|
||||
@@ -288,6 +288,32 @@ cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, C
|
||||
"preferred_names = [ \"^/dev/mpath/\", \"^/dev/mapper/mpath\", \"^/dev/[hs]d\" ]\n"
|
||||
"#\n")
|
||||
|
||||
cfg(devices_use_devicesfile_CFG, "use_devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_DEVICES_FILE, vsn(2, 3, 12), NULL, 0, NULL,
|
||||
"Enable or disable the use of a devices file.\n"
|
||||
"When enabled, lvm will only use devices that\n"
|
||||
"are lised in the devices file. A devices file will\n"
|
||||
"be used, regardless of this setting, when the --devicesfile\n"
|
||||
"option is set to a specific file name.\n")
|
||||
|
||||
cfg(devices_devicesfile_CFG, "devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DEVICES_FILE, vsn(2, 3, 12), NULL, 0, NULL,
|
||||
"The name of the system devices file, listing devices that LVM should use.\n"
|
||||
"This should not be used to select a non-system devices file.\n"
|
||||
"The --devicesfile option is intended for alternative devices files.\n")
|
||||
|
||||
cfg(devices_search_for_devnames_CFG, "search_for_devnames", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SEARCH_FOR_DEVNAMES, vsn(2, 3, 12), NULL, 0, NULL,
|
||||
"Look outside of the devices file for missing devname entries.\n"
|
||||
"A devname entry is used for a device that does not have a stable\n"
|
||||
"device id, e.g. wwid, so the unstable device name is used as\n"
|
||||
"the device id. After reboot, or if the device is reattached,\n"
|
||||
"the device name may change, in which case lvm will not find\n"
|
||||
"the expected PV on the device listed in the devices file.\n"
|
||||
"This setting controls whether lvm will search other devices,\n"
|
||||
"outside the devices file, to look for the missing PV on a\n"
|
||||
"renamed device. If \"none\", lvm will not look at other devices,\n"
|
||||
"and the PV may appear to be missing. If \"auto\", lvm will look\n"
|
||||
"at other devices, but only those that are likely to have the PV.\n"
|
||||
"If \"all\", lvm will look at all devices on the system.\n")
|
||||
|
||||
cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*|", vsn(1, 0, 0), NULL, 0, NULL,
|
||||
"Limit the block devices that are used by LVM commands.\n"
|
||||
"This is a list of regular expressions used to accept or reject block\n"
|
||||
@@ -326,16 +352,16 @@ cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_D
|
||||
"global_filter are not opened by LVM.\n")
|
||||
|
||||
cfg_runtime(devices_cache_CFG, "cache", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), vsn(1, 2, 19), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg_runtime(devices_cache_dir_CFG, "cache_dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 2, 19), vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(devices_cache_file_prefix_CFG, "cache_file_prefix", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_CACHE_FILE_PREFIX, vsn(1, 2, 19), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(devices_write_cache_state_CFG, "write_cache_state", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_ADVANCED, CFG_TYPE_INT | CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
|
||||
"List of additional acceptable block device types.\n"
|
||||
@@ -401,15 +427,15 @@ cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devi
|
||||
cfg(devices_md_chunk_alignment_CFG, "md_chunk_alignment", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_CHUNK_ALIGNMENT, vsn(2, 2, 48), NULL, 0, NULL,
|
||||
"Align the start of a PV data area with md device's stripe-width.\n"
|
||||
"This applies if a PV is placed directly on an md device.\n"
|
||||
"default_data_alignment will be overriden if it is not aligned\n"
|
||||
"default_data_alignment will be overridden if it is not aligned\n"
|
||||
"with the value detected for this setting.\n"
|
||||
"This setting is overriden by data_alignment_detection,\n"
|
||||
"This setting is overridden by data_alignment_detection,\n"
|
||||
"data_alignment, and the --dataalignment option.\n")
|
||||
|
||||
cfg(devices_default_data_alignment_CFG, "default_data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, FIRST_PE_AT_ONE_MB_IN_MB, vsn(2, 2, 75), NULL, 0, NULL,
|
||||
"Align the start of a PV data area with this number of MiB.\n"
|
||||
"Set to 1 for 1MiB, 2 for 2MiB, etc. Set to 0 to disable.\n"
|
||||
"This setting is overriden by data_alignment and the --dataalignment\n"
|
||||
"This setting is overridden by data_alignment and the --dataalignment\n"
|
||||
"option.\n")
|
||||
|
||||
cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_DETECTION, vsn(2, 2, 51), NULL, 0, NULL,
|
||||
@@ -421,9 +447,9 @@ cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CF
|
||||
"preferred unit of receiving I/O, e.g. MD stripe width.\n"
|
||||
"minimum_io_size is used if optimal_io_size is undefined (0).\n"
|
||||
"If md_chunk_alignment is enabled, that detects the optimal_io_size.\n"
|
||||
"default_data_alignment and md_chunk_alignment will be overriden\n"
|
||||
"default_data_alignment and md_chunk_alignment will be overridden\n"
|
||||
"if they are not aligned with the value detected for this setting.\n"
|
||||
"This setting is overriden by data_alignment and the --dataalignment\n"
|
||||
"This setting is overridden by data_alignment and the --dataalignment\n"
|
||||
"option.\n")
|
||||
|
||||
cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 45), NULL, 0, NULL,
|
||||
@@ -431,7 +457,7 @@ cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, 0, CFG_TY
|
||||
"When non-zero, this setting overrides default_data_alignment.\n"
|
||||
"Set to 0 to disable, in which case default_data_alignment\n"
|
||||
"is used to align the first PE in units of MiB.\n"
|
||||
"This setting is overriden by the --dataalignment option.\n")
|
||||
"This setting is overridden by the --dataalignment option.\n")
|
||||
|
||||
cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION, vsn(2, 2, 50), NULL, 0, NULL,
|
||||
"Shift the start of an aligned PV data area based on sysfs information.\n"
|
||||
@@ -441,7 +467,7 @@ cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detectio
|
||||
"partitioning will have an alignment_offset of 3584 bytes (sector 7\n"
|
||||
"is the lowest aligned logical block, the 4KiB sectors start at\n"
|
||||
"LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).\n"
|
||||
"This setting is overriden by the --dataalignmentoffset option.\n")
|
||||
"This setting is overridden by the --dataalignmentoffset option.\n")
|
||||
|
||||
cfg(devices_ignore_suspended_devices_CFG, "ignore_suspended_devices", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_IGNORE_SUSPENDED_DEVICES, vsn(1, 2, 19), NULL, 0, NULL,
|
||||
"Ignore DM devices that have I/O suspended while scanning devices.\n"
|
||||
@@ -467,7 +493,7 @@ cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, 0
|
||||
"different way, making them a better choice for VG stacking.\n")
|
||||
|
||||
cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID, vsn(2, 2, 73), NULL, 0, NULL,
|
||||
"Allow use of pvcreate --uuid without requiring --restorefile.\n")
|
||||
@@ -628,6 +654,11 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
|
||||
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
|
||||
"Thin pool metadata and data will always use different PVs.\n")
|
||||
|
||||
cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
|
||||
"Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
|
||||
"This is slightly less then the actual maximum 15.88 GiB.\n"
|
||||
"For compatibility with older version and use of cropped size set to 1.\n")
|
||||
|
||||
cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
|
||||
"Thin pool data chunks are zeroed before they are first used.\n"
|
||||
"Zeroing with a larger thin pool chunk size reduces performance.\n")
|
||||
@@ -943,13 +974,13 @@ cfg(global_activation_CFG, "activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, D
|
||||
"the error messages.\n")
|
||||
|
||||
cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 18), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(global_format_CFG, "format", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.")
|
||||
NULL)
|
||||
|
||||
cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL, vsn(2, 3, 3), NULL, NULL)
|
||||
|
||||
@@ -960,16 +991,16 @@ cfg(global_etc_CFG, "etc", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ETC_D
|
||||
"Location of /etc system configuration directory.\n")
|
||||
|
||||
cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, 0, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.")
|
||||
NULL)
|
||||
|
||||
cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL, 0, NULL,
|
||||
"When disabled, fail if a lock request would block.\n")
|
||||
|
||||
cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(global_locking_dir_CFG, "locking_dir", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_LOCK_DIR, vsn(1, 0, 0), "@DEFAULT_LOCK_DIR@", 0, NULL,
|
||||
"Directory to use for LVM command file locks.\n"
|
||||
@@ -982,14 +1013,13 @@ cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECT
|
||||
"a volume group's metadata, instead of always granting the read-only\n"
|
||||
"requests immediately, delay them to allow the read-write requests to\n"
|
||||
"be serviced. Without this setting, write access may be stalled by a\n"
|
||||
"high volume of read-only requests. This option only affects\n"
|
||||
"locking_type 1 viz. local file-based locking.\n")
|
||||
"high volume of read-only requests. This option only affects file locks.\n")
|
||||
|
||||
cfg(global_library_dir_CFG, "library_dir", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
|
||||
"Search this directory first for shared libraries.\n")
|
||||
|
||||
cfg(global_locking_library_CFG, "locking_library", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCKING_LIB, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ABORT_ON_INTERNAL_ERRORS, vsn(2, 2, 57), NULL, 0, NULL,
|
||||
"Abort a command that encounters an internal error.\n"
|
||||
@@ -997,7 +1027,7 @@ cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_
|
||||
"encountered the internal error. Please only enable for debugging.\n")
|
||||
|
||||
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 96), NULL, vsn(2, 2, 174), NULL,
|
||||
"No longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_METADATA_READ_ONLY, vsn(2, 2, 75), NULL, 0, NULL,
|
||||
"No operations that change on-disk metadata are permitted.\n"
|
||||
@@ -1087,18 +1117,21 @@ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_pa
|
||||
|
||||
cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL,
|
||||
"Activate LVs based on system-generated device events.\n"
|
||||
"When a device appears on the system, a system-generated event runs\n"
|
||||
"the pvscan command to activate LVs if the new PV completes the VG.\n"
|
||||
"Use auto_activation_volume_list to select which LVs should be\n"
|
||||
"activated from these events (the default is all.)\n"
|
||||
"When event_activation is disabled, the system will generally run\n"
|
||||
"a direct activation command to activate LVs in complete VGs.\n")
|
||||
"When a PV appears on the system, a system-generated uevent triggers\n"
|
||||
"the lvm2-pvscan service which runs the pvscan --cache -aay command.\n"
|
||||
"If the new PV completes a VG, pvscan autoactivates LVs in the VG.\n"
|
||||
"When event_activation is disabled, the lvm2-activation services are\n"
|
||||
"generated and run at fixed points during system startup. These\n"
|
||||
"services run vgchange -aay to autoactivate LVs in VGs that happen\n"
|
||||
"to be present at that point in time.\n"
|
||||
"See the --setautoactivation option or the auto_activation_volume_list\n"
|
||||
"setting to configure autoactivation for specific VGs or LVs.\n")
|
||||
|
||||
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 151), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg(global_use_aio_CFG, "use_aio", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_AIO, vsn(2, 2, 183), NULL, 0, NULL,
|
||||
"Use async I/O when reading and writing devices.\n")
|
||||
@@ -1122,6 +1155,15 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D
|
||||
"and can cause lvcreate to fail. Applicable only if LVM is compiled\n"
|
||||
"with lockd support\n")
|
||||
|
||||
cfg(global_lvmlockctl_kill_command_CFG, "lvmlockctl_kill_command", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "", vsn(2, 3, 12), NULL, 0, NULL,
|
||||
"The command that lvmlockctl --kill should use to force LVs offline.\n"
|
||||
"The lvmlockctl --kill command is run when a shared VG has lost\n"
|
||||
"access to locks (e.g. when sanlock has lost access to storage.)\n"
|
||||
"An empty string means that there will be no automatic attempt by\n"
|
||||
"lvmlockctl --kill to forcibly shut down LVs in the VG, and the user\n"
|
||||
"can manually intervene as described in lvmlockd(8).\n"
|
||||
"The VG name will be appended to the command specified here.\n")
|
||||
|
||||
cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL,
|
||||
"The full path to the thin_check command.\n"
|
||||
"LVM uses this command to check that a thin metadata device is in a\n"
|
||||
@@ -1207,6 +1249,15 @@ cfg(global_vdo_format_executable_CFG, "vdo_format_executable", global_CFG_SECTIO
|
||||
cfg_array(global_vdo_format_options_CFG, "vdo_format_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_FORMAT_OPTIONS_CONFIG, VDO_1ST_VSN, NULL, 0, NULL,
|
||||
"List of options passed added to standard vdoformat command.\n")
|
||||
|
||||
cfg_array(global_vdo_disabled_features_CFG, "vdo_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 3, 11), NULL, 0, NULL,
|
||||
"Features to not use in the vdo driver.\n"
|
||||
"This can be helpful for testing, or to avoid using a feature that is\n"
|
||||
"causing problems. Features include: online_rename\n"
|
||||
"#\n"
|
||||
"Example\n"
|
||||
"vdo_disabled_features = [ \"online_rename\" ]\n"
|
||||
"#\n")
|
||||
|
||||
cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FSADM_PATH, vsn(2, 2, 170), "@FSADM_PATH@", 0, NULL,
|
||||
"The full path to the fsadm command.\n"
|
||||
"LVM uses this command to help with lvresize -r operations.\n")
|
||||
@@ -1275,7 +1326,7 @@ cfg(global_io_memory_size_CFG, "io_memory_size", global_CFG_SECTION, CFG_DEFAULT
|
||||
|
||||
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL,
|
||||
"Use udev notifications to synchronize udev and LVM.\n"
|
||||
"The --nodevsync option overrides this setting.\n"
|
||||
"The --noudevsync option overrides this setting.\n"
|
||||
"When disabled, LVM commands will not wait for notifications from\n"
|
||||
"udev, but continue irrespective of any possible udev processing in\n"
|
||||
"the background. Only use this if udev is not running or has rules\n"
|
||||
@@ -1354,22 +1405,22 @@ cfg_array(activation_volume_list_CFG, "volume_list", activation_CFG_SECTION, CFG
|
||||
"#\n")
|
||||
|
||||
cfg_array(activation_auto_activation_volume_list_CFG, "auto_activation_volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 97), NULL, 0, NULL,
|
||||
"Only LVs selected by this list are auto-activated.\n"
|
||||
"This list works like volume_list, but it is used only by\n"
|
||||
"auto-activation commands. It does not apply to direct activation\n"
|
||||
"commands. If this list is defined, an LV is only auto-activated\n"
|
||||
"if it matches an entry in this list. If this list is undefined, it\n"
|
||||
"imposes no limits on LV auto-activation (all are allowed.) If this\n"
|
||||
"list is defined and empty, i.e. \"[]\", then no LVs are selected for\n"
|
||||
"auto-activation. An LV that is selected by this list for\n"
|
||||
"auto-activation, must also be selected by volume_list (if defined)\n"
|
||||
"before it is activated. Auto-activation is an activation command that\n"
|
||||
"includes the 'a' argument: --activate ay or -a ay. The 'a' (auto)\n"
|
||||
"argument for auto-activation is meant to be used by activation\n"
|
||||
"commands that are run automatically by the system, as opposed to LVM\n"
|
||||
"commands run directly by a user. A user may also use the 'a' flag\n"
|
||||
"directly to perform auto-activation. Also see pvscan(8) for more\n"
|
||||
"information about auto-activation.\n"
|
||||
"A list of VGs or LVs that should be autoactivated.\n"
|
||||
"Autoactivation is an activation command run with -aay,\n"
|
||||
"i.e. vgchange -aay, lvchange -aay, or pvscan --cache -aay.\n"
|
||||
"When this list is defined, an autoactivation command will only\n"
|
||||
"activate LVs included in the list. If this list is undefined,\n"
|
||||
"it has no effect. If this list is defined but empty, then no\n"
|
||||
"LVs will be autoactivated. LVs can be included in the list by\n"
|
||||
"LV name, VG name (applies to all LVs in the VG), or tag name.\n"
|
||||
"VGs and LVs can also have an autoactivation property set in\n"
|
||||
"metadata, see --setautoactivation. LVs included in this list\n"
|
||||
"will not be autoactivated if the VG or LV autoactivation\n"
|
||||
"property is disabled (see vgs or lvs \"-o autoactivation\").\n"
|
||||
"The volume_list setting and the \"activation skip\" property\n"
|
||||
"also apply to autoactivation.\n"
|
||||
"The -aay option is meant to be used by activation commands that\n"
|
||||
"are run automatically by the system, e.g. from systemd services.\n"
|
||||
"#\n"
|
||||
"Accepted values:\n"
|
||||
" vgname\n"
|
||||
@@ -1725,7 +1776,7 @@ cfg(metadata_pvmetadataignore_CFG, "pvmetadataignore", metadata_CFG_SECTION, CFG
|
||||
cfg(metadata_stripesize_CFG, "stripesize", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_STRIPESIZE, vsn(1, 0, 0), NULL, 0, NULL, NULL)
|
||||
|
||||
cfg_array(metadata_dirs_CFG, "dirs", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
|
||||
"This setting is no longer used.\n")
|
||||
NULL)
|
||||
|
||||
cfg_section(metadata_disk_areas_CFG_SUBSECTION, "disk_areas", metadata_CFG_SECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL)
|
||||
cfg_section(disk_area_CFG_SUBSECTION, "disk_area", metadata_disk_areas_CFG_SUBSECTION, CFG_NAME_VARIABLE | CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL)
|
||||
|
||||
@@ -118,6 +118,8 @@
|
||||
#define DEFAULT_THIN_REPAIR_OPTION1 ""
|
||||
#define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1
|
||||
#define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
|
||||
#define DEFAULT_THIN_POOL_CROP_METADATA 0
|
||||
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4) /* KB */ /* 0x3f8040 blocks */
|
||||
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2) /* KB */
|
||||
#define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048 /* KB */
|
||||
#define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
|
||||
@@ -321,4 +323,9 @@
|
||||
|
||||
#define DEFAULT_MD_COMPONENT_CHECKS "auto"
|
||||
|
||||
#define DEFAULT_USE_DEVICES_FILE 0
|
||||
#define DEFAULT_DEVICES_FILE "system.devices"
|
||||
|
||||
#define DEFAULT_SEARCH_FOR_DEVNAMES "auto"
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
|
||||
@@ -218,7 +218,7 @@ struct dm_list *str_to_str_list(struct dm_pool *mem, const char *str,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p1 = p2 = str;
|
||||
p1 = str;
|
||||
while (*p1) {
|
||||
if (!(p2 = strstr(p1, delim)))
|
||||
next = p2 = str + strlen(str);
|
||||
|
||||
@@ -42,7 +42,7 @@ static int *_fd_table;
|
||||
|
||||
static void log_sys_warn(const char *call)
|
||||
{
|
||||
log_warn("%s failed: %s", call, strerror(errno));
|
||||
log_warn("WARNING: %s failed: %s.", call, strerror(errno));
|
||||
}
|
||||
|
||||
// Assumes the list is not empty.
|
||||
@@ -74,7 +74,7 @@ static struct cb_set *_cb_set_create(unsigned nr)
|
||||
unsigned i;
|
||||
struct cb_set *cbs = malloc(sizeof(*cbs) + nr * sizeof(*cbs->vec));
|
||||
|
||||
if (!cbs->vec)
|
||||
if (!cbs)
|
||||
return NULL;
|
||||
|
||||
dm_list_init(&cbs->free);
|
||||
@@ -92,7 +92,7 @@ static void _cb_set_destroy(struct cb_set *cbs)
|
||||
// never be in flight IO.
|
||||
if (!dm_list_empty(&cbs->allocated)) {
|
||||
// bail out
|
||||
log_error("async io still in flight");
|
||||
log_warn("WARNING: async io still in flight.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1351,26 +1351,26 @@ static bool _writeback_v(struct radix_tree_iterator *it,
|
||||
struct block *b = v.ptr;
|
||||
|
||||
if (_test_flags(b, BF_DIRTY))
|
||||
_issue_write(b);
|
||||
_issue_write(b);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _invalidate_v(struct radix_tree_iterator *it,
|
||||
uint8_t *kb, uint8_t *ke, union radix_value v)
|
||||
{
|
||||
struct block *b = v.ptr;
|
||||
struct invalidate_iterator *iit = container_of(it, struct invalidate_iterator, it);
|
||||
struct invalidate_iterator *iit = container_of(it, struct invalidate_iterator, it);
|
||||
|
||||
if (b->error || _test_flags(b, BF_DIRTY)) {
|
||||
log_warn("bcache_invalidate: block (%d, %llu) still dirty",
|
||||
b->di, (unsigned long long) b->index);
|
||||
iit->success = false;
|
||||
return true;
|
||||
log_warn("WARNING: bcache_invalidate: block (%d, %llu) still dirty.",
|
||||
b->di, (unsigned long long) b->index);
|
||||
iit->success = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (b->ref_count) {
|
||||
log_warn("bcache_invalidate: block (%d, %llu) still held",
|
||||
log_warn("WARNING: bcache_invalidate: block (%d, %llu) still held.",
|
||||
b->di, (unsigned long long) b->index);
|
||||
iit->success = false;
|
||||
return true;
|
||||
@@ -1386,7 +1386,7 @@ static bool _invalidate_v(struct radix_tree_iterator *it,
|
||||
|
||||
bool bcache_invalidate_di(struct bcache *cache, int di)
|
||||
{
|
||||
union key k;
|
||||
union key k;
|
||||
struct invalidate_iterator it;
|
||||
|
||||
k.parts.di = di;
|
||||
@@ -1401,7 +1401,7 @@ bool bcache_invalidate_di(struct bcache *cache, int di)
|
||||
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it.it);
|
||||
|
||||
if (it.success)
|
||||
radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di));
|
||||
(void) radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di));
|
||||
|
||||
return it.success;
|
||||
}
|
||||
@@ -1429,14 +1429,14 @@ static bool _abort_v(struct radix_tree_iterator *it,
|
||||
|
||||
void bcache_abort_di(struct bcache *cache, int di)
|
||||
{
|
||||
union key k;
|
||||
union key k;
|
||||
struct radix_tree_iterator it;
|
||||
|
||||
k.parts.di = di;
|
||||
|
||||
it.visit = _abort_v;
|
||||
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it);
|
||||
radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di));
|
||||
(void) radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
@@ -1512,10 +1512,9 @@ int bcache_change_fd(int di, int fd)
|
||||
if (di >= _fd_table_size)
|
||||
return 0;
|
||||
if (di < 0) {
|
||||
log_error(INTERNAL_ERROR "Cannot change not openned DI with FD:%d", fd);
|
||||
log_error(INTERNAL_ERROR "Cannot change not opened DI with FD:%d", fd);
|
||||
return 0;
|
||||
}
|
||||
_fd_table[di] = fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "lib/datastruct/btree.h"
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
@@ -27,6 +28,7 @@
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <locale.h>
|
||||
|
||||
struct dev_iter {
|
||||
struct btree_iter *current;
|
||||
@@ -68,11 +70,13 @@ static void _dev_init(struct device *dev)
|
||||
dev->bcache_fd = -1;
|
||||
dev->bcache_di = -1;
|
||||
dev->read_ahead = -1;
|
||||
dev->part = -1;
|
||||
|
||||
dev->ext.enabled = 0;
|
||||
dev->ext.src = DEV_EXT_NONE;
|
||||
|
||||
dm_list_init(&dev->aliases);
|
||||
dm_list_init(&dev->ids);
|
||||
}
|
||||
|
||||
void dev_destroy_file(struct device *dev)
|
||||
@@ -289,13 +293,13 @@ static int _compare_paths(const char *path0, const char *path1)
|
||||
/* We prefer symlinks - they exist for a reason!
|
||||
* So we prefer a shorter path before the first symlink in the name.
|
||||
* FIXME Configuration option to invert this? */
|
||||
while (s0) {
|
||||
s0 = strchr(s0, '/');
|
||||
s1 = strchr(s1, '/');
|
||||
if (s0) {
|
||||
while (s0 && s1) {
|
||||
if ((s0 = strchr(s0, '/')))
|
||||
*s0 = '\0';
|
||||
|
||||
if ((s1 = strchr(s1, '/')))
|
||||
*s1 = '\0';
|
||||
}
|
||||
|
||||
if (lstat(p0, &stat0)) {
|
||||
log_sys_very_verbose("lstat", p0);
|
||||
return 1;
|
||||
@@ -308,10 +312,10 @@ static int _compare_paths(const char *path0, const char *path1)
|
||||
return 0;
|
||||
if (!S_ISLNK(stat0.st_mode) && S_ISLNK(stat1.st_mode))
|
||||
return 1;
|
||||
if (s0) {
|
||||
if (s0)
|
||||
*s0++ = '/';
|
||||
if (s1)
|
||||
*s1++ = '/';
|
||||
}
|
||||
}
|
||||
|
||||
/* ASCII comparison */
|
||||
@@ -321,20 +325,38 @@ static int _compare_paths(const char *path0, const char *path1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_alias(struct device *dev, const char *path)
|
||||
enum add_hash {
|
||||
NO_HASH,
|
||||
HASH,
|
||||
REHASH
|
||||
};
|
||||
|
||||
static int _add_alias(struct device *dev, const char *path, enum add_hash hash)
|
||||
{
|
||||
struct dm_str_list *sl = _zalloc(sizeof(*sl));
|
||||
struct dm_str_list *sl;
|
||||
struct dm_str_list *strl;
|
||||
const char *oldpath;
|
||||
int prefer_old = 1;
|
||||
|
||||
if (!sl)
|
||||
return_0;
|
||||
if (hash == REHASH)
|
||||
dm_hash_remove(_cache.names, path);
|
||||
|
||||
/* Is name already there? */
|
||||
dm_list_iterate_items(strl, &dev->aliases) {
|
||||
if (!strcmp(strl->str, path))
|
||||
return 1;
|
||||
dm_list_iterate_items(strl, &dev->aliases)
|
||||
if (!strcmp(strl->str, path)) {
|
||||
path = strl->str;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(path = dm_pool_strdup(_cache.mem, path)) ||
|
||||
!(sl = _zalloc(sizeof(*sl)))) {
|
||||
log_error("Failed to add allias to dev cache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strncmp(path, "/dev/nvme", 9)) {
|
||||
log_debug("Found nvme device %s", dev_name(dev));
|
||||
dev->flags |= DEV_IS_NVME;
|
||||
}
|
||||
|
||||
sl->str = path;
|
||||
@@ -348,11 +370,17 @@ static int _add_alias(struct device *dev, const char *path)
|
||||
dm_list_add(&dev->aliases, &sl->list);
|
||||
else
|
||||
dm_list_add_h(&dev->aliases, &sl->list);
|
||||
out:
|
||||
if ((hash != NO_HASH) &&
|
||||
!dm_hash_insert(_cache.names, path, dev)) {
|
||||
log_error("Couldn't add name to hash in dev cache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
|
||||
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
|
||||
{
|
||||
FILE *fp;
|
||||
size_t len;
|
||||
@@ -379,7 +407,7 @@ static int _get_sysfs_value(const char *path, char *buf, size_t buf_size, int er
|
||||
r = 1;
|
||||
out:
|
||||
if (fclose(fp))
|
||||
log_sys_error("fclose", path);
|
||||
log_sys_debug("fclose", path);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -393,7 +421,7 @@ static int _get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int mi
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _get_sysfs_value(path, buf, buf_size, 0);
|
||||
return get_sysfs_value(path, buf, buf_size, 0);
|
||||
}
|
||||
|
||||
static struct dm_list *_get_or_add_list_by_index_key(struct dm_hash_table *idx, const char *key)
|
||||
@@ -423,7 +451,6 @@ static struct device *_insert_sysfs_dev(dev_t devno, const char *devname)
|
||||
static struct device _fake_dev = { .flags = DEV_USED_FOR_LV };
|
||||
struct stat stat0;
|
||||
char path[PATH_MAX];
|
||||
char *path_copy;
|
||||
struct device *dev;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s%s", _cache.dev_dir, devname) < 0) {
|
||||
@@ -441,15 +468,9 @@ static struct device *_insert_sysfs_dev(dev_t devno, const char *devname)
|
||||
if (!(dev = _dev_create(devno)))
|
||||
return_NULL;
|
||||
|
||||
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
|
||||
log_error("_insert_sysfs_dev: %s: dm_pool_strdup failed", devname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_add_alias(dev, path_copy)) {
|
||||
log_error("Couldn't add alias to dev cache.");
|
||||
if (!_add_alias(dev, path, NO_HASH)) {
|
||||
_free(dev);
|
||||
return NULL;
|
||||
return_NULL;
|
||||
}
|
||||
|
||||
if (!btree_insert(_cache.sysfs_only_devices, (uint32_t) devno, dev)) {
|
||||
@@ -474,7 +495,7 @@ static struct device *_get_device_for_sysfs_dev_name_using_devno(const char *dev
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_get_sysfs_value(path, buf, sizeof(buf), 1))
|
||||
if (!get_sysfs_value(path, buf, sizeof(buf), 1))
|
||||
return_NULL;
|
||||
|
||||
if (sscanf(buf, "%d:%d", &major, &minor) != 2) {
|
||||
@@ -645,7 +666,7 @@ static int _index_dev_by_vgid_and_lvid(struct device *dev)
|
||||
r = 1;
|
||||
out:
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", path);
|
||||
log_sys_debug("closedir", path);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -691,7 +712,6 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
struct device *dev;
|
||||
struct device *dev_by_devt;
|
||||
struct device *dev_by_path;
|
||||
char *path_copy;
|
||||
|
||||
dev_by_devt = (struct device *) btree_lookup(_cache.devices, (uint32_t) d);
|
||||
dev_by_path = (struct device *) dm_hash_lookup(_cache.names, path);
|
||||
@@ -725,20 +745,8 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
|
||||
log_error("Failed to duplicate path string.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_add_alias(dev, path_copy)) {
|
||||
log_error("Couldn't add alias to dev cache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
|
||||
log_error("Couldn't add name to hash in dev cache.");
|
||||
return 0;
|
||||
}
|
||||
if (!_add_alias(dev, path, HASH))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -750,20 +758,8 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
log_debug_devs("Found dev %d:%d %s - new alias.",
|
||||
(int)MAJOR(d), (int)MINOR(d), path);
|
||||
|
||||
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
|
||||
log_error("Failed to duplicate path string.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_add_alias(dev, path_copy)) {
|
||||
log_error("Couldn't add alias to dev cache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
|
||||
log_error("Couldn't add name to hash in dev cache.");
|
||||
return 0;
|
||||
}
|
||||
if (!_add_alias(dev, path, HASH))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -789,25 +785,10 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
|
||||
log_error("Failed to duplicate path string.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_add_alias(dev, path_copy)) {
|
||||
log_error("Couldn't add alias to dev cache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_hash_remove(_cache.names, path);
|
||||
|
||||
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
|
||||
log_error("Couldn't add name to hash in dev cache.");
|
||||
return 0;
|
||||
}
|
||||
if (!_add_alias(dev, path, REHASH))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -819,22 +800,8 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
(int)MAJOR(d), (int)MINOR(d), path,
|
||||
(int)MAJOR(dev_by_path->dev), (int)MINOR(dev_by_path->dev));
|
||||
|
||||
if (!(path_copy = dm_pool_strdup(_cache.mem, path))) {
|
||||
log_error("Failed to duplicate path string.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_add_alias(dev, path_copy)) {
|
||||
log_error("Couldn't add alias to dev cache.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dm_hash_remove(_cache.names, path);
|
||||
|
||||
if (!dm_hash_insert(_cache.names, path_copy, dev)) {
|
||||
log_error("Couldn't add name to hash in dev cache.");
|
||||
return 0;
|
||||
}
|
||||
if (!_add_alias(dev, path, REHASH))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -843,16 +810,6 @@ static int _insert_dev(const char *path, dev_t d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *_join(const char *dir, const char *name)
|
||||
{
|
||||
size_t len = strlen(dir) + strlen(name) + 2;
|
||||
char *r = malloc(len);
|
||||
if (r)
|
||||
snprintf(r, len, "%s/%s", dir, name);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get rid of extra slashes in the path string.
|
||||
*/
|
||||
@@ -879,27 +836,39 @@ static int _insert_dir(const char *dir)
|
||||
{
|
||||
int n, dirent_count, r = 1;
|
||||
struct dirent **dirent;
|
||||
char *path;
|
||||
char path[PATH_MAX];
|
||||
size_t len;
|
||||
|
||||
if (!dm_strncpy(path, dir, sizeof(path) - 1)) {
|
||||
log_debug_devs("Dir path %s is too long", path);
|
||||
return 0;
|
||||
}
|
||||
_collapse_slashes(path);
|
||||
len = strlen(path);
|
||||
if (len && path[len - 1] != '/')
|
||||
path[len++] = '/';
|
||||
|
||||
setlocale(LC_COLLATE, "C"); /* Avoid sorting by locales */
|
||||
dirent_count = scandir(dir, &dirent, NULL, alphasort);
|
||||
if (dirent_count > 0) {
|
||||
for (n = 0; n < dirent_count; n++) {
|
||||
if (dirent[n]->d_name[0] == '.') {
|
||||
free(dirent[n]);
|
||||
if (dirent[n]->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
if (!dm_strncpy(path + len, dirent[n]->d_name, sizeof(path) - len)) {
|
||||
log_debug_devs("Path %s/%s is too long.", dir, dirent[n]->d_name);
|
||||
r = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(path = _join(dir, dirent[n]->d_name)))
|
||||
return_0;
|
||||
|
||||
_collapse_slashes(path);
|
||||
r &= _insert(path, NULL, 1, 0);
|
||||
free(path);
|
||||
|
||||
free(dirent[n]);
|
||||
}
|
||||
|
||||
for (n = 0; n < dirent_count; n++)
|
||||
free(dirent[n]);
|
||||
free(dirent);
|
||||
}
|
||||
setlocale(LC_COLLATE, "");
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -967,12 +936,12 @@ static int _dev_cache_iterate_sysfs_for_index(const char *path)
|
||||
r = !partial_failure;
|
||||
|
||||
if (closedir(d))
|
||||
log_sys_error("closedir", path);
|
||||
log_sys_debug("closedir", path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int dev_cache_index_devs(void)
|
||||
static int dev_cache_index_devs(void)
|
||||
{
|
||||
static int sysfs_has_dev_block = -1;
|
||||
char path[PATH_MAX];
|
||||
@@ -993,7 +962,7 @@ int dev_cache_index_devs(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_sys_error("stat", path);
|
||||
log_sys_debug("stat", path);
|
||||
return 0;
|
||||
}
|
||||
} else if (!sysfs_has_dev_block)
|
||||
@@ -1253,9 +1222,9 @@ int dev_cache_init(struct cmd_context *cmd)
|
||||
if (!(_cache.mem = dm_pool_create("dev_cache", 10 * 1024)))
|
||||
return_0;
|
||||
|
||||
if (!(_cache.names = dm_hash_create(128)) ||
|
||||
!(_cache.vgid_index = dm_hash_create(32)) ||
|
||||
!(_cache.lvid_index = dm_hash_create(32))) {
|
||||
if (!(_cache.names = dm_hash_create(120)) ||
|
||||
!(_cache.vgid_index = dm_hash_create(30)) ||
|
||||
!(_cache.lvid_index = dm_hash_create(29))) {
|
||||
dm_pool_destroy(_cache.mem);
|
||||
_cache.mem = 0;
|
||||
return_0;
|
||||
@@ -1321,12 +1290,20 @@ int dev_cache_check_for_open_devices(void)
|
||||
|
||||
int dev_cache_exit(void)
|
||||
{
|
||||
struct device *dev;
|
||||
struct dm_hash_node *n;
|
||||
int num_open = 0;
|
||||
|
||||
if (_cache.names)
|
||||
if (_cache.names) {
|
||||
if ((num_open = _check_for_open_devices(1)) > 0)
|
||||
log_error(INTERNAL_ERROR "%d device(s) were left open and have been closed.", num_open);
|
||||
|
||||
dm_hash_iterate(n, _cache.names) {
|
||||
dev = (struct device *) dm_hash_get_data(_cache.names, n);
|
||||
free_dids(&dev->ids);
|
||||
}
|
||||
}
|
||||
|
||||
if (_cache.mem)
|
||||
dm_pool_destroy(_cache.mem);
|
||||
|
||||
@@ -1428,93 +1405,165 @@ struct device *dev_hash_get(const char *name)
|
||||
return (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
}
|
||||
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
|
||||
static void _remove_alias(struct device *dev, const char *name)
|
||||
{
|
||||
struct stat buf;
|
||||
struct device *d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
int info_available = 0;
|
||||
int ret = 1;
|
||||
struct dm_str_list *strl;
|
||||
|
||||
if (d && (d->flags & DEV_REGULAR))
|
||||
return d;
|
||||
|
||||
/* If the entry's wrong, remove it */
|
||||
if (stat(name, &buf) < 0) {
|
||||
if (d)
|
||||
dm_hash_remove(_cache.names, name);
|
||||
log_sys_very_verbose("stat", name);
|
||||
d = NULL;
|
||||
} else
|
||||
info_available = 1;
|
||||
|
||||
if (d && (buf.st_rdev != d->dev)) {
|
||||
dm_hash_remove(_cache.names, name);
|
||||
d = NULL;
|
||||
}
|
||||
|
||||
if (!d) {
|
||||
_insert(name, info_available ? &buf : NULL, 0, obtain_device_list_from_udev());
|
||||
d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
if (!d) {
|
||||
log_debug_devs("Device name not found in dev_cache repeat dev_cache_scan for %s", name);
|
||||
dev_cache_scan();
|
||||
d = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
dm_list_iterate_items(strl, &dev->aliases) {
|
||||
if (!strcmp(strl->str, name)) {
|
||||
dm_list_del(&strl->list);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
if (d && (d->flags & DEV_REGULAR))
|
||||
return d;
|
||||
|
||||
if (f && !(d->flags & DEV_REGULAR)) {
|
||||
ret = f->passes_filter(cmd, f, d, NULL);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
log_debug_devs("get device by name defer filter %s", dev_name(d));
|
||||
d->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (f && !(d->flags & DEV_REGULAR) && !ret)
|
||||
return NULL;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static struct device *_dev_cache_seek_devt(dev_t dev)
|
||||
{
|
||||
struct device *d = NULL;
|
||||
struct dm_hash_node *n = dm_hash_get_first(_cache.names);
|
||||
while (n) {
|
||||
d = dm_hash_get_data(_cache.names, n);
|
||||
if (d->dev == dev)
|
||||
return d;
|
||||
n = dm_hash_get_next(_cache.names, n);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO This is very inefficient. We probably want a hash table indexed by
|
||||
* major:minor for keys to speed up these lookups.
|
||||
* Check that paths for this dev still refer to the same dev_t. This is known
|
||||
* to drop invalid paths in the case where lvm deactivates an LV, which causes
|
||||
* that LV path to go away, but that LV path is not removed from dev-cache (it
|
||||
* probably should be). Later a new path to a different LV is added to
|
||||
* dev-cache, where the new LV has the same major:minor as the previously
|
||||
* deactivated LV. The new LV will find the existing struct dev, and that
|
||||
* struct dev will have dev->aliases entries that refer to the name of the old
|
||||
* deactivated LV. Those old paths are all invalid and are dropped here.
|
||||
*/
|
||||
|
||||
static void _verify_aliases(struct device *dev, const char *newname)
|
||||
{
|
||||
struct dm_str_list *strl, *strl2;
|
||||
struct stat st;
|
||||
|
||||
dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
||||
/* newname was just stat'd and added by caller */
|
||||
if (newname && !strcmp(strl->str, newname))
|
||||
continue;
|
||||
|
||||
if (stat(strl->str, &st) || (st.st_rdev != dev->dev)) {
|
||||
log_debug("Drop invalid path %s for %d:%d (new path %s).",
|
||||
strl->str, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), newname ?: "");
|
||||
dm_hash_remove(_cache.names, strl->str);
|
||||
dm_list_del(&strl->list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f)
|
||||
{
|
||||
struct device *dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
struct stat st;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* DEV_REGULAR means that is "dev" is actually a file, not a device.
|
||||
* FIXME: I don't think dev-cache is used for files any more and this
|
||||
* can be dropped?
|
||||
*/
|
||||
if (dev && (dev->flags & DEV_REGULAR))
|
||||
return dev;
|
||||
|
||||
/*
|
||||
* The requested path is invalid, remove any dev-cache
|
||||
* info for it.
|
||||
*/
|
||||
if (stat(name, &st)) {
|
||||
if (dev) {
|
||||
log_print("Device path %s is invalid for %d:%d %s.",
|
||||
name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
|
||||
|
||||
dm_hash_remove(_cache.names, name);
|
||||
|
||||
_remove_alias(dev, name);
|
||||
|
||||
/* Remove any other names in dev->aliases that are incorrect. */
|
||||
_verify_aliases(dev, NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!S_ISBLK(st.st_mode)) {
|
||||
log_debug("Not a block device %s.", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* dev-cache has incorrect info for the requested path.
|
||||
* Remove incorrect info and then add new dev-cache entry.
|
||||
*/
|
||||
if (dev && (st.st_rdev != dev->dev)) {
|
||||
log_debug("Device path %s does not match %d:%d %s.",
|
||||
name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev), dev_name(dev));
|
||||
|
||||
dm_hash_remove(_cache.names, name);
|
||||
|
||||
_remove_alias(dev, name);
|
||||
|
||||
/* Remove any other names in dev->aliases that are incorrect. */
|
||||
_verify_aliases(dev, NULL);
|
||||
|
||||
/* Add new dev-cache entry next. */
|
||||
dev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Either add a new struct dev for st_rdev and name,
|
||||
* or add name as a new alias for an existing struct dev
|
||||
* for st_rdev.
|
||||
*/
|
||||
if (!dev) {
|
||||
if (!_insert_dev(name, st.st_rdev))
|
||||
return_NULL;
|
||||
|
||||
/* Get the struct dev that was just added. */
|
||||
dev = (struct device *) dm_hash_lookup(_cache.names, name);
|
||||
|
||||
if (!dev) {
|
||||
log_error("Failed to get device %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_verify_aliases(dev, name);
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller passed a filter if they only want the dev if it
|
||||
* passes filters.
|
||||
*/
|
||||
|
||||
if (!f)
|
||||
return dev;
|
||||
|
||||
ret = f->passes_filter(cmd, f, dev, NULL);
|
||||
|
||||
/*
|
||||
* This might happen if this function is called before
|
||||
* filters can do i/o. I don't think this will happen
|
||||
* any longer and this EAGAIN case can be removed.
|
||||
*/
|
||||
if (ret == -EAGAIN) {
|
||||
log_debug_devs("dev_cache_get filter deferred %s", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
log_debug_devs("dev_cache_get filter excludes %s", dev_name(dev));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct dev_filter *f, int *filtered)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *sysfs_dir;
|
||||
struct stat info;
|
||||
struct device *d = _dev_cache_seek_devt(dev);
|
||||
struct device *d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
|
||||
int ret;
|
||||
|
||||
if (filtered)
|
||||
*filtered = 0;
|
||||
|
||||
if (d && (d->flags & DEV_REGULAR))
|
||||
return d;
|
||||
|
||||
if (!d) {
|
||||
sysfs_dir = dm_sysfs_dir();
|
||||
if (sysfs_dir && *sysfs_dir) {
|
||||
@@ -1535,11 +1584,11 @@ struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct
|
||||
log_debug_devs("Device num not found in dev_cache repeat dev_cache_scan for %d:%d",
|
||||
(int)MAJOR(dev), (int)MINOR(dev));
|
||||
dev_cache_scan();
|
||||
d = _dev_cache_seek_devt(dev);
|
||||
}
|
||||
d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
|
||||
|
||||
if (!d)
|
||||
return NULL;
|
||||
if (!d)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (d->flags & DEV_REGULAR)
|
||||
return d;
|
||||
@@ -1560,6 +1609,7 @@ struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct
|
||||
|
||||
if (filtered)
|
||||
*filtered = 1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1649,3 +1699,335 @@ bool dev_cache_has_md_with_end_superblock(struct dev_types *dt)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int _setup_devices_list(struct cmd_context *cmd)
|
||||
{
|
||||
struct dm_str_list *strl;
|
||||
struct dev_use *du;
|
||||
|
||||
/*
|
||||
* For each --devices arg, add a du to cmd->use_devices.
|
||||
* The du has devname is the devices arg value.
|
||||
*/
|
||||
|
||||
dm_list_iterate_items(strl, &cmd->deviceslist) {
|
||||
if (!(du = dm_pool_zalloc(cmd->mem, sizeof(struct dev_use))))
|
||||
return_0;
|
||||
|
||||
if (!(du->devname = dm_pool_strdup(cmd->mem, strl->str)))
|
||||
return_0;
|
||||
|
||||
dm_list_add(&cmd->use_devices, &du->list);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _setup_devices_file_dmeventd(struct cmd_context *cmd)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
/*
|
||||
* When command is run by dmeventd there is no --devicesfile
|
||||
* option that can enable/disable the use of a devices file.
|
||||
*/
|
||||
if (!find_config_tree_bool(cmd, devices_use_devicesfile_CFG, NULL)) {
|
||||
cmd->enable_devices_file = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If /etc/lvm/devices/dmeventd.devices exists, then use that.
|
||||
* The optional dmeventd.devices allows the user to control
|
||||
* which devices dmeventd will look at and use.
|
||||
* Otherwise, disable the devices file because dmeventd should
|
||||
* be able to manage LVs in any VG (i.e. LVs in a non-system
|
||||
* devices file.)
|
||||
*/
|
||||
if (dm_snprintf(path, sizeof(path), "%s/devices/dmeventd.devices", cmd->system_dir) < 0) {
|
||||
log_warn("Failed to copy devices path");
|
||||
cmd->enable_devices_file = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (stat(path, &st)) {
|
||||
/* No dmeventd.devices, so do not use a devices file. */
|
||||
cmd->enable_devices_file = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmd->enable_devices_file = 1;
|
||||
(void) dm_strncpy(cmd->devices_file_path, path, sizeof(cmd->devices_file_path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setup_devices_file(struct cmd_context *cmd)
|
||||
{
|
||||
char dirpath[PATH_MAX];
|
||||
const char *filename = NULL;
|
||||
struct stat st;
|
||||
int rv;
|
||||
|
||||
if (cmd->run_by_dmeventd)
|
||||
return _setup_devices_file_dmeventd(cmd);
|
||||
|
||||
if (cmd->devicesfile) {
|
||||
/* --devicesfile <filename> or "" has been set which overrides
|
||||
lvm.conf settings use_devicesfile and devicesfile. */
|
||||
if (!strlen(cmd->devicesfile))
|
||||
cmd->enable_devices_file = 0;
|
||||
else {
|
||||
cmd->enable_devices_file = 1;
|
||||
filename = cmd->devicesfile;
|
||||
}
|
||||
/* TODO: print a warning if --devicesfile system.devices
|
||||
while lvm.conf use_devicesfile=0. */
|
||||
} else {
|
||||
if (!find_config_tree_bool(cmd, devices_use_devicesfile_CFG, NULL))
|
||||
cmd->enable_devices_file = 0;
|
||||
else {
|
||||
cmd->enable_devices_file = 1;
|
||||
filename = find_config_tree_str(cmd, devices_devicesfile_CFG, NULL);
|
||||
if (!validate_name(filename)) {
|
||||
log_error("Invalid devices file name from config setting \"%s\".", filename);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cmd->enable_devices_file)
|
||||
return 1;
|
||||
|
||||
if (dm_snprintf(dirpath, sizeof(dirpath), "%s/devices", cmd->system_dir) < 0) {
|
||||
log_error("Failed to copy devices dir path");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stat(dirpath, &st)) {
|
||||
log_debug("Creating %s.", dirpath);
|
||||
dm_prepare_selinux_context(dirpath, S_IFDIR);
|
||||
rv = mkdir(dirpath, 0755);
|
||||
dm_prepare_selinux_context(NULL, 0);
|
||||
|
||||
if ((rv < 0) && stat(dirpath, &st)) {
|
||||
log_error("Failed to create %s %d", dirpath, errno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dm_snprintf(cmd->devices_file_path, sizeof(cmd->devices_file_path),
|
||||
"%s/devices/%s", cmd->system_dir, filename) < 0) {
|
||||
log_error("Failed to copy devices file path");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add all system devices to dev-cache, and attempt to
|
||||
* match all devices_file entries to dev-cache entries.
|
||||
*/
|
||||
int setup_devices(struct cmd_context *cmd)
|
||||
{
|
||||
int file_exists;
|
||||
int lock_mode = 0;
|
||||
|
||||
if (cmd->enable_devices_list) {
|
||||
if (!_setup_devices_list(cmd))
|
||||
return_0;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
if (!setup_devices_file(cmd))
|
||||
return_0;
|
||||
|
||||
if (!cmd->enable_devices_file)
|
||||
goto scan;
|
||||
|
||||
file_exists = devices_file_exists(cmd);
|
||||
|
||||
/*
|
||||
* Removing the devices file is another way of disabling the use of
|
||||
* a devices file, unless the command creates the devices file.
|
||||
*/
|
||||
if (!file_exists && !cmd->create_edit_devices_file) {
|
||||
log_debug("Devices file not found, ignoring.");
|
||||
cmd->enable_devices_file = 0;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't let pvcreate or vgcreate create a new system devices file
|
||||
* unless it's specified explicitly with --devicesfile. This avoids
|
||||
* a problem where a system is running with existing PVs, and is
|
||||
* not using a devices file based on the fact that the system
|
||||
* devices file doesn't exist. If the user simply uses pvcreate
|
||||
* to create a new PV, they almost certainly do not want that to
|
||||
* create a new system devices file containing the new PV and none
|
||||
* of the existing PVs that the system is already using.
|
||||
* However, if they use the vgimportdevices or lvmdevices command
|
||||
* then they are clearly intending to use the devices file, so we
|
||||
* can create it. Or, if they specify a non-system devices file
|
||||
* with pvcreate/vgcreate, then they clearly want to use a devices
|
||||
* file and we can create it (and creating a non-system devices file
|
||||
* would not cause existing PVs to disappear from the main system.)
|
||||
*
|
||||
* An exception is if pvcreate/vgcreate get to device_id_write and
|
||||
* did not see any existing VGs during label scan. In that case
|
||||
* they will create a new system devices file, since there will be
|
||||
* no VGs that the new file would hide.
|
||||
*/
|
||||
if (cmd->create_edit_devices_file && !cmd->devicesfile && !file_exists &&
|
||||
(!strncmp(cmd->name, "pvcreate", 8) || !strncmp(cmd->name, "vgcreate", 8))) {
|
||||
/* The command will decide in device_ids_write whether to create
|
||||
a new system devices file. */
|
||||
cmd->enable_devices_file = 0;
|
||||
cmd->pending_devices_file = 1;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
if (!file_exists && cmd->sysinit) {
|
||||
cmd->enable_devices_file = 0;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
if (!file_exists) {
|
||||
/*
|
||||
* pvcreate/vgcreate/vgimportdevices/lvmdevices-add create
|
||||
* a new devices file here if it doesn't exist.
|
||||
* They have the create_edit_devices_file flag set.
|
||||
* First they create/lock-ex the devices file lockfile.
|
||||
* Other commands will not use a devices file if none exists.
|
||||
*/
|
||||
lock_mode = LOCK_EX;
|
||||
|
||||
if (!lock_devices_file(cmd, lock_mode)) {
|
||||
log_error("Failed to lock the devices file to create.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The file will be created in device_ids_write() */
|
||||
if (!devices_file_exists(cmd))
|
||||
goto scan;
|
||||
} else {
|
||||
/*
|
||||
* Commands that intend to edit the devices file have
|
||||
* edit_devices_file or create_edit_devices_file set (create if
|
||||
* they can also create a new devices file) and lock it ex
|
||||
* here prior to reading. Other commands that intend to just
|
||||
* read the devices file lock sh.
|
||||
*/
|
||||
lock_mode = (cmd->create_edit_devices_file || cmd->edit_devices_file) ? LOCK_EX : LOCK_SH;
|
||||
|
||||
if (!lock_devices_file(cmd, lock_mode)) {
|
||||
log_error("Failed to lock the devices file.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the list of device ids that lvm can use.
|
||||
* Adds a struct dev_id to cmd->use_devices for each one.
|
||||
*/
|
||||
if (!device_ids_read(cmd)) {
|
||||
log_error("Failed to read the devices file.");
|
||||
unlock_devices_file(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the command is editing the devices file, it acquires
|
||||
* the ex lock above, will later call device_ids_write(), and
|
||||
* then unlock the lock after writing the file.
|
||||
* When the command is just reading the devices file, it's
|
||||
* locked sh above just before reading the file, and unlocked
|
||||
* here after reading.
|
||||
*/
|
||||
if (lock_mode == LOCK_SH)
|
||||
unlock_devices_file(cmd);
|
||||
|
||||
scan:
|
||||
/*
|
||||
* Add a 'struct device' to dev-cache for each device available on the system.
|
||||
* This will not open or read any devices, but may look at sysfs properties.
|
||||
* This list of devs comes from looking /dev entries, or from asking libudev.
|
||||
*/
|
||||
dev_cache_scan();
|
||||
|
||||
/*
|
||||
* Match entries from cmd->use_devices with device structs in dev-cache.
|
||||
*/
|
||||
device_ids_match(cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The alternative to setup_devices() when the command is interested
|
||||
* in using only one PV.
|
||||
*
|
||||
* Add one system device to dev-cache, and attempt to
|
||||
* match its dev-cache entry to a devices_file entry.
|
||||
*/
|
||||
int setup_device(struct cmd_context *cmd, const char *devname)
|
||||
{
|
||||
struct stat buf;
|
||||
struct device *dev;
|
||||
|
||||
if (cmd->enable_devices_list) {
|
||||
if (!_setup_devices_list(cmd))
|
||||
return_0;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
if (!setup_devices_file(cmd))
|
||||
return_0;
|
||||
|
||||
if (!cmd->enable_devices_file)
|
||||
goto scan;
|
||||
|
||||
if (!devices_file_exists(cmd)) {
|
||||
log_debug("Devices file not found, ignoring.");
|
||||
cmd->enable_devices_file = 0;
|
||||
goto scan;
|
||||
}
|
||||
|
||||
if (!lock_devices_file(cmd, LOCK_SH)) {
|
||||
log_error("Failed to lock the devices file to read.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!device_ids_read(cmd)) {
|
||||
log_error("Failed to read the devices file.");
|
||||
unlock_devices_file(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unlock_devices_file(cmd);
|
||||
|
||||
scan:
|
||||
if (stat(devname, &buf) < 0) {
|
||||
log_error("Cannot access device %s.", devname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISBLK(buf.st_mode)) {
|
||||
log_error("Invaild device type %s.", devname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_insert_dev(devname, buf.st_rdev))
|
||||
return_0;
|
||||
|
||||
if (!(dev = (struct device *) dm_hash_lookup(_cache.names, devname)))
|
||||
return_0;
|
||||
|
||||
/* Match this device to an entry in devices_file so it will not
|
||||
be rejected by filter-deviceid. */
|
||||
if (cmd->enable_devices_file)
|
||||
device_ids_match_dev(cmd, dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ struct dev_filter {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
int dev_cache_index_devs(void);
|
||||
struct dm_list *dev_cache_get_dev_list_for_vgid(const char *vgid);
|
||||
struct dm_list *dev_cache_get_dev_list_for_lvid(const char *lvid);
|
||||
|
||||
@@ -75,4 +74,10 @@ void dev_cache_failed_path(struct device *dev, const char *path);
|
||||
|
||||
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt);
|
||||
|
||||
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value);
|
||||
|
||||
int setup_devices_file(struct cmd_context *cmd);
|
||||
int setup_devices(struct cmd_context *cmd);
|
||||
int setup_device(struct cmd_context *cmd, const char *devname);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -81,7 +81,7 @@ typedef struct dasd_information2_t {
|
||||
int dasd_is_cdl_formatted(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
dasd_information2_t dasd_info2;
|
||||
dasd_information2_t dasd_info2 = { 0 };
|
||||
|
||||
if (!dev_open_readonly(dev))
|
||||
return_0;
|
||||
|
||||
@@ -104,7 +104,7 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
|
||||
}
|
||||
|
||||
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
|
||||
log_sys_error("ioctl BLKGETSIZE64", name);
|
||||
log_warn("WARNING: %s: ioctl BLKGETSIZE64 %s", name, strerror(errno));
|
||||
if (do_close && !dev_close_immediate(dev))
|
||||
stack;
|
||||
return 0;
|
||||
@@ -124,7 +124,7 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
|
||||
|
||||
static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
|
||||
{
|
||||
long read_ahead_long;
|
||||
long read_ahead_long = 0;
|
||||
|
||||
if (dev->read_ahead != -1) {
|
||||
*read_ahead = (uint32_t) dev->read_ahead;
|
||||
@@ -132,12 +132,13 @@ static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
|
||||
}
|
||||
|
||||
if (!dev_open_readonly_quiet(dev)) {
|
||||
log_error("Failed to open to get readahead %s", dev_name(dev));
|
||||
log_warn("WARNING: Failed to open %s to get readahead %s.",
|
||||
dev_name(dev), strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) {
|
||||
log_sys_error("ioctl BLKRAGET", dev_name(dev));
|
||||
log_warn("WARNING: %s: ioctl BLKRAGET %s.", dev_name(dev), strerror(errno));
|
||||
if (!dev_close_immediate(dev))
|
||||
stack;
|
||||
return 0;
|
||||
@@ -170,7 +171,7 @@ static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64
|
||||
test_mode() ? " (test mode - suppressed)" : "");
|
||||
|
||||
if (!test_mode() && ioctl(dev->fd, BLKDISCARD, &discard_range) < 0) {
|
||||
log_error("%s: BLKDISCARD ioctl at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
|
||||
log_warn("WARNING: %s: ioctl BLKDISCARD at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
|
||||
dev_name(dev), offset_bytes, size_bytes, strerror(errno));
|
||||
if (!dev_close_immediate(dev))
|
||||
stack;
|
||||
|
||||
@@ -55,7 +55,17 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
|
||||
static int _dev_has_imsm_magic(struct device *dev, uint64_t devsize_sectors)
|
||||
{
|
||||
char imsm_signature[IMSM_SIG_LEN];
|
||||
uint64_t off = (devsize_sectors * 512) - 1024;
|
||||
uint64_t off;
|
||||
unsigned int physical_block_size = 0;
|
||||
unsigned int logical_block_size = 0;
|
||||
|
||||
if (!dev_get_direct_block_sizes(dev, &physical_block_size, &logical_block_size))
|
||||
return_0;
|
||||
|
||||
if (logical_block_size == 4096)
|
||||
off = (devsize_sectors * 512) - 8192;
|
||||
else
|
||||
off = (devsize_sectors * 512) - 1024;
|
||||
|
||||
if (!dev_read_bytes(dev, off, IMSM_SIG_LEN, imsm_signature))
|
||||
return_0;
|
||||
@@ -156,17 +166,14 @@ static int _udev_dev_is_md_component(struct device *dev)
|
||||
if (!(ext = dev_ext_get(dev)))
|
||||
return_0;
|
||||
|
||||
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE))) {
|
||||
dev->flags |= DEV_UDEV_INFO_MISSING;
|
||||
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID);
|
||||
}
|
||||
#else
|
||||
static int _udev_dev_is_md_component(struct device *dev)
|
||||
{
|
||||
dev->flags |= DEV_UDEV_INFO_MISSING;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/device/bcache.h"
|
||||
#include "lib/label/label.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
|
||||
#ifdef BLKID_WIPING_SUPPORT
|
||||
#include <blkid.h>
|
||||
@@ -35,36 +36,16 @@
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
* dev is pmem if /sys/dev/block/<major>:<minor>/queue/dax is 1
|
||||
* An nvme device has major number 259 (BLKEXT), minor number <minor>,
|
||||
* and reading /sys/dev/block/259:<minor>/device/dev shows a character
|
||||
* device cmajor:cminor where cmajor matches the major number of the
|
||||
* nvme character device entry in /proc/devices. Checking all of that
|
||||
* is excessive and unnecessary compared to just comparing /dev/name*.
|
||||
*/
|
||||
|
||||
int dev_is_pmem(struct device *dev)
|
||||
int dev_is_nvme(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[PATH_MAX];
|
||||
int is_pmem = 0;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/queue/dax",
|
||||
dm_sysfs_dir(),
|
||||
(int) MAJOR(dev->dev),
|
||||
(int) MINOR(dev->dev)) < 0) {
|
||||
log_warn("Sysfs path for %s dax is too long.", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(fp = fopen(path, "r")))
|
||||
return 0;
|
||||
|
||||
if (fscanf(fp, "%d", &is_pmem) != 1)
|
||||
log_warn("Failed to parse DAX %s.", path);
|
||||
|
||||
if (is_pmem)
|
||||
log_debug("%s is pmem", dev_name(dev));
|
||||
|
||||
if (fclose(fp))
|
||||
log_sys_debug("fclose", path);
|
||||
|
||||
return is_pmem ? 1 : 0;
|
||||
return (dev->flags & DEV_IS_NVME) ? 1 : 0;
|
||||
}
|
||||
|
||||
int dev_is_lv(struct device *dev)
|
||||
@@ -230,7 +211,7 @@ struct dev_types *create_dev_types(const char *proc_dir,
|
||||
log_error("Expecting string in devices/types "
|
||||
"in config file");
|
||||
if (fclose(pd))
|
||||
log_sys_error("fclose", proc_devices);
|
||||
log_sys_debug("fclose", proc_devices);
|
||||
goto bad;
|
||||
}
|
||||
dev_len = strlen(cv->v.str);
|
||||
@@ -241,7 +222,7 @@ struct dev_types *create_dev_types(const char *proc_dir,
|
||||
"in devices/types in config file",
|
||||
name);
|
||||
if (fclose(pd))
|
||||
log_sys_error("fclose", proc_devices);
|
||||
log_sys_debug("fclose", proc_devices);
|
||||
goto bad;
|
||||
}
|
||||
if (!cv->v.i) {
|
||||
@@ -249,7 +230,7 @@ struct dev_types *create_dev_types(const char *proc_dir,
|
||||
"%s in devices/types in config file",
|
||||
name);
|
||||
if (fclose(pd))
|
||||
log_sys_error("fclose", proc_devices);
|
||||
log_sys_debug("fclose", proc_devices);
|
||||
goto bad;
|
||||
}
|
||||
if (dev_len <= strlen(line + i) &&
|
||||
@@ -302,6 +283,9 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
|
||||
|
||||
const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
if (dev->flags & DEV_IS_NVME)
|
||||
return "NVME";
|
||||
|
||||
if (MAJOR(dev->dev) == dt->device_mapper_major)
|
||||
return "DM";
|
||||
|
||||
@@ -348,7 +332,6 @@ int major_is_scsi_device(struct dev_types *dt, int major)
|
||||
return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static int _loop_is_with_partscan(struct device *dev)
|
||||
{
|
||||
FILE *fp;
|
||||
@@ -380,6 +363,45 @@ static int _loop_is_with_partscan(struct device *dev)
|
||||
return partscan;
|
||||
}
|
||||
|
||||
int dev_get_partition_number(struct device *dev, int *num)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char buf[8] = { 0 };
|
||||
dev_t devt = dev->dev;
|
||||
struct stat sb;
|
||||
|
||||
if (dev->part != -1) {
|
||||
*num = dev->part;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/partition",
|
||||
dm_sysfs_dir(), (int)MAJOR(devt), (int)MINOR(devt)) < 0) {
|
||||
log_error("Failed to create sysfs path for %s", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stat(path, &sb)) {
|
||||
dev->part = 0;
|
||||
*num = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!get_sysfs_value(path, buf, sizeof(buf), 0)) {
|
||||
log_error("Failed to read sysfs path for %s", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!buf[0]) {
|
||||
log_error("Failed to read sysfs partition value for %s", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev->part = atoi(buf);
|
||||
*num = dev->part;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* See linux/genhd.h and fs/partitions/msdos */
|
||||
#define PART_MAGIC 0xAA55
|
||||
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
|
||||
@@ -398,6 +420,28 @@ struct partition {
|
||||
uint32_t nr_sects;
|
||||
} __attribute__((packed));
|
||||
|
||||
static int _has_sys_partition(struct device *dev)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct stat info;
|
||||
int major = (int) MAJOR(dev->dev);
|
||||
int minor = (int) MINOR(dev->dev);
|
||||
|
||||
/* check if dev is a partition */
|
||||
if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
|
||||
dm_sysfs_dir(), major, minor) < 0) {
|
||||
log_warn("WARNING: %s: partition path is too long.", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stat(path, &info) == -1) {
|
||||
if (errno != ENOENT)
|
||||
log_sys_debug("stat", path);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _is_partitionable(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
int parts = major_max_partitions(dt, MAJOR(dev->dev));
|
||||
@@ -414,6 +458,13 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
|
||||
_loop_is_with_partscan(dev))
|
||||
return 1;
|
||||
|
||||
if (dev_is_nvme(dt, dev)) {
|
||||
/* If this dev is already a partition then it's not partitionable. */
|
||||
if (_has_sys_partition(dev))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((parts <= 1) || (MINOR(dev->dev) % parts))
|
||||
return 0;
|
||||
|
||||
@@ -551,16 +602,22 @@ int dev_is_partitioned(struct dev_types *dt, struct device *dev)
|
||||
*/
|
||||
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
{
|
||||
const char *sysfs_dir = dm_sysfs_dir();
|
||||
int major = (int) MAJOR(dev->dev);
|
||||
int minor = (int) MINOR(dev->dev);
|
||||
char path[PATH_MAX];
|
||||
char temp_path[PATH_MAX];
|
||||
char buffer[64];
|
||||
struct stat info;
|
||||
FILE *fp = NULL;
|
||||
int parts, residue, size, ret = 0;
|
||||
|
||||
/*
|
||||
* /dev/nvme devs don't use the major:minor numbering like
|
||||
* block dev types that have their own major number, so
|
||||
* the calculation based on minor number doesn't work.
|
||||
*/
|
||||
if (dev_is_nvme(dt, dev))
|
||||
goto sys_partition;
|
||||
|
||||
/*
|
||||
* Try to get the primary dev out of the
|
||||
* list of known device types first.
|
||||
@@ -576,23 +633,14 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sys_partition:
|
||||
/*
|
||||
* If we can't get the primary dev out of the list of known device
|
||||
* types, try to look at sysfs directly then. This is more complex
|
||||
* way and it also requires certain sysfs layout to be present
|
||||
* which might not be there in old kernels!
|
||||
*/
|
||||
|
||||
/* check if dev is a partition */
|
||||
if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
|
||||
sysfs_dir, major, minor) < 0) {
|
||||
log_error("dm_snprintf partition failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (stat(path, &info) == -1) {
|
||||
if (errno != ENOENT)
|
||||
log_sys_error("stat", path);
|
||||
if (!_has_sys_partition(dev)) {
|
||||
*result = dev->dev;
|
||||
ret = 1;
|
||||
goto out; /* dev is not a partition! */
|
||||
@@ -605,25 +653,31 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
* - basename ../../block/md0/md0 = md0
|
||||
* Parent's 'dev' sysfs attribute = /sys/block/md0/dev
|
||||
*/
|
||||
if ((size = readlink(dirname(path), temp_path, sizeof(temp_path) - 1)) < 0) {
|
||||
log_sys_error("readlink", path);
|
||||
if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d",
|
||||
dm_sysfs_dir(), major, minor) < 0) {
|
||||
log_warn("WARNING: %s: major:minor sysfs path is too long.", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
if ((size = readlink(path, temp_path, sizeof(temp_path) - 1)) < 0) {
|
||||
log_warn("WARNING: Readlink of %s failed.", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
temp_path[size] = '\0';
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/block/%s/dev",
|
||||
sysfs_dir, basename(dirname(temp_path))) < 0) {
|
||||
log_error("dm_snprintf dev failed");
|
||||
dm_sysfs_dir(), basename(dirname(temp_path))) < 0) {
|
||||
log_warn("WARNING: sysfs path for %s is too long.",
|
||||
basename(dirname(temp_path)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* finally, parse 'dev' attribute and create corresponding dev_t */
|
||||
if (!(fp = fopen(path, "r"))) {
|
||||
if (errno == ENOENT)
|
||||
log_error("sysfs file %s does not exist.", path);
|
||||
log_debug("sysfs file %s does not exist.", path);
|
||||
else
|
||||
log_sys_error("fopen", path);
|
||||
log_sys_debug("fopen", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -633,7 +687,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
}
|
||||
|
||||
if (sscanf(buffer, "%d:%d", &major, &minor) != 2) {
|
||||
log_error("sysfs file %s not in expected MAJ:MIN format: %s",
|
||||
log_warn("WARNING: sysfs file %s not in expected MAJ:MIN format: %s",
|
||||
path, buffer);
|
||||
goto out;
|
||||
}
|
||||
@@ -641,29 +695,29 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
ret = 2;
|
||||
out:
|
||||
if (fp && fclose(fp))
|
||||
log_sys_error("fclose", path);
|
||||
log_sys_debug("fclose", path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef BLKID_WIPING_SUPPORT
|
||||
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size)
|
||||
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
|
||||
{
|
||||
char *block_size_str = NULL;
|
||||
|
||||
if ((block_size_str = blkid_get_tag_value(NULL, "BLOCK_SIZE", dev_name(dev)))) {
|
||||
if ((block_size_str = blkid_get_tag_value(NULL, "BLOCK_SIZE", pathname))) {
|
||||
*fs_block_size = (uint32_t)atoi(block_size_str);
|
||||
free(block_size_str);
|
||||
log_debug("Found blkid BLOCK_SIZE %u for fs on %s", *fs_block_size, dev_name(dev));
|
||||
log_debug("Found blkid BLOCK_SIZE %u for fs on %s", *fs_block_size, pathname);
|
||||
return 1;
|
||||
} else {
|
||||
log_debug("No blkid BLOCK_SIZE for fs on %s", dev_name(dev));
|
||||
log_debug("No blkid BLOCK_SIZE for fs on %s", pathname);
|
||||
*fs_block_size = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size)
|
||||
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
|
||||
{
|
||||
log_debug("Disabled blkid BLOCK_SIZE for fs.");
|
||||
*fs_block_size = 0;
|
||||
@@ -703,7 +757,7 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_error("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name);
|
||||
log_warn("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name);
|
||||
return 2;
|
||||
}
|
||||
if (blkid_probe_lookup_value(probe, "SBMAGIC", &magic, &len)) {
|
||||
@@ -837,7 +891,7 @@ static int _wipe_signature(struct device *dev, const char *type, const char *nam
|
||||
int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found, int full))
|
||||
{
|
||||
int wipe;
|
||||
uint64_t offset_found;
|
||||
uint64_t offset_found = 0;
|
||||
|
||||
wipe = signature_detection_fn(dev, &offset_found, 1);
|
||||
if (wipe == -1) {
|
||||
@@ -901,9 +955,9 @@ int wipe_known_signatures(struct cmd_context *cmd, struct device *dev,
|
||||
yes, force, wiped);
|
||||
#endif
|
||||
if (blkid_wiping_enabled) {
|
||||
log_warn("allocation/use_blkid_wiping=1 configuration setting is set "
|
||||
log_warn("WARNING: allocation/use_blkid_wiping=1 configuration setting is set "
|
||||
"while LVM is not compiled with blkid wiping support.");
|
||||
log_warn("Falling back to native LVM signature detection.");
|
||||
log_warn("WARNING: Falling back to native LVM signature detection.");
|
||||
}
|
||||
return _wipe_known_signatures_with_lvm(dev, name,
|
||||
types_to_exclude,
|
||||
@@ -919,25 +973,23 @@ static int _snprintf_attr(char *buf, size_t buf_size, const char *sysfs_dir,
|
||||
if (dm_snprintf(buf, buf_size, "%s/dev/block/%d:%d/%s", sysfs_dir,
|
||||
(int)MAJOR(dev), (int)MINOR(dev),
|
||||
attribute) < 0) {
|
||||
log_warn("dm_snprintf %s failed.", attribute);
|
||||
log_warn("WARNING: sysfs path for %s attribute is too long.", attribute);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned long _dev_topology_attribute(struct dev_types *dt,
|
||||
const char *attribute,
|
||||
struct device *dev,
|
||||
unsigned long default_value)
|
||||
static int _dev_sysfs_block_attribute(struct dev_types *dt,
|
||||
const char *attribute,
|
||||
struct device *dev,
|
||||
unsigned long *value)
|
||||
{
|
||||
const char *sysfs_dir = dm_sysfs_dir();
|
||||
char path[PATH_MAX], buffer[64];
|
||||
FILE *fp;
|
||||
struct stat info;
|
||||
dev_t uninitialized_var(primary);
|
||||
unsigned long result = default_value;
|
||||
unsigned long value = 0UL;
|
||||
dev_t primary = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!attribute || !*attribute)
|
||||
goto_out;
|
||||
@@ -946,16 +998,16 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt,
|
||||
goto_out;
|
||||
|
||||
if (!_snprintf_attr(path, sizeof(path), sysfs_dir, attribute, dev->dev))
|
||||
goto_out;
|
||||
goto_out;
|
||||
|
||||
/*
|
||||
* check if the desired sysfs attribute exists
|
||||
* - if not: either the kernel doesn't have topology support
|
||||
* or the device could be a partition
|
||||
*/
|
||||
if (stat(path, &info) == -1) {
|
||||
if (!(fp = fopen(path, "r"))) {
|
||||
if (errno != ENOENT) {
|
||||
log_sys_debug("stat", path);
|
||||
log_sys_debug("fopen", path);
|
||||
goto out;
|
||||
}
|
||||
if (!dev_get_primary_dev(dt, dev, &primary))
|
||||
@@ -965,44 +1017,54 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt,
|
||||
if (!_snprintf_attr(path, sizeof(path), sysfs_dir, attribute, primary))
|
||||
goto_out;
|
||||
|
||||
if (stat(path, &info) == -1) {
|
||||
if (!(fp = fopen(path, "r"))) {
|
||||
if (errno != ENOENT)
|
||||
log_sys_debug("stat", path);
|
||||
log_sys_debug("fopen", path);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(fp = fopen(path, "r"))) {
|
||||
log_sys_debug("fopen", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), fp)) {
|
||||
log_sys_debug("fgets", path);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
if (sscanf(buffer, "%lu", &value) != 1) {
|
||||
log_warn("sysfs file %s not in expected format: %s", path, buffer);
|
||||
if (sscanf(buffer, "%lu", value) != 1) {
|
||||
log_warn("WARNING: sysfs file %s not in expected format: %s", path, buffer);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
log_very_verbose("Device %s: %s is %lu%s.",
|
||||
dev_name(dev), attribute, value, default_value ? "" : " bytes");
|
||||
|
||||
result = value >> SECTOR_SHIFT;
|
||||
|
||||
if (!result && value) {
|
||||
log_warn("WARNING: Device %s: %s is %lu and is unexpectedly less than sector.",
|
||||
dev_name(dev), attribute, value);
|
||||
result = 1;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
out_close:
|
||||
if (fclose(fp))
|
||||
log_sys_debug("fclose", path);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long _dev_topology_attribute(struct dev_types *dt,
|
||||
const char *attribute,
|
||||
struct device *dev,
|
||||
unsigned long default_value)
|
||||
{
|
||||
unsigned long result = default_value;
|
||||
unsigned long value = 0UL;
|
||||
|
||||
if (_dev_sysfs_block_attribute(dt, attribute, dev, &value)) {
|
||||
log_very_verbose("Device %s: %s is %lu%s.",
|
||||
dev_name(dev), attribute, value, default_value ? "" : " bytes");
|
||||
|
||||
result = value >> SECTOR_SHIFT;
|
||||
|
||||
if (!result && value) {
|
||||
log_warn("WARNING: Device %s: %s is %lu and is unexpectedly less than sector.",
|
||||
dev_name(dev), attribute, value);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1033,8 +1095,17 @@ unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev)
|
||||
|
||||
int dev_is_rotational(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
return (int) _dev_topology_attribute(dt, "queue/rotational", dev, 1UL);
|
||||
unsigned long value;
|
||||
return _dev_sysfs_block_attribute(dt, "queue/rotational", dev, &value) ? (int) value : 1;
|
||||
}
|
||||
|
||||
/* dev is pmem if /sys/dev/block/<major>:<minor>/queue/dax is 1 */
|
||||
int dev_is_pmem(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
unsigned long value;
|
||||
return _dev_sysfs_block_attribute(dt, "queue/dax", dev, &value) ? (int) value : 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
@@ -1071,6 +1142,11 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dev_is_pmem(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
@@ -1185,10 +1261,8 @@ int udev_dev_is_md_component(struct device *dev)
|
||||
const char *value;
|
||||
int ret = 0;
|
||||
|
||||
if (!obtain_device_list_from_udev()) {
|
||||
dev->flags |= DEV_UDEV_INFO_MISSING;
|
||||
if (!obtain_device_list_from_udev())
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(udev_device = _udev_get_dev(dev)))
|
||||
return 0;
|
||||
@@ -1215,7 +1289,6 @@ int udev_dev_is_mpath_component(struct device *dev)
|
||||
|
||||
int udev_dev_is_md_component(struct device *dev)
|
||||
{
|
||||
dev->flags |= DEV_UDEV_INFO_MISSING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev);
|
||||
int major_max_partitions(struct dev_types *dt, int major);
|
||||
int dev_is_partitioned(struct dev_types *dt, struct device *dev);
|
||||
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result);
|
||||
int dev_get_partition_number(struct device *dev, int *num);
|
||||
|
||||
/* Various device properties */
|
||||
unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev);
|
||||
@@ -93,10 +94,12 @@ unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev);
|
||||
|
||||
int dev_is_rotational(struct dev_types *dt, struct device *dev);
|
||||
|
||||
int dev_is_pmem(struct device *dev);
|
||||
int dev_is_pmem(struct dev_types *dt, struct device *dev);
|
||||
|
||||
int dev_is_nvme(struct dev_types *dt, struct device *dev);
|
||||
|
||||
int dev_is_lv(struct device *dev);
|
||||
|
||||
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size);
|
||||
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
#define DEV_BCACHE_WRITE 0x00008000 /* bcache_fd is open with RDWR */
|
||||
#define DEV_SCAN_FOUND_LABEL 0x00010000 /* label scan read dev and found label */
|
||||
#define DEV_IS_MD_COMPONENT 0x00020000 /* device is an md component */
|
||||
#define DEV_UDEV_INFO_MISSING 0x00040000 /* we have no udev info for this device */
|
||||
#define DEV_IS_NVME 0x00040000 /* set if dev is nvme */
|
||||
#define DEV_MATCHED_USE_ID 0x00080000 /* matched an entry from cmd->use_devices */
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
@@ -56,12 +57,54 @@ struct dev_ext {
|
||||
void *handle;
|
||||
};
|
||||
|
||||
#define DEV_ID_TYPE_SYS_WWID 0x0001
|
||||
#define DEV_ID_TYPE_SYS_SERIAL 0x0002
|
||||
#define DEV_ID_TYPE_MPATH_UUID 0x0003
|
||||
#define DEV_ID_TYPE_MD_UUID 0x0004
|
||||
#define DEV_ID_TYPE_LOOP_FILE 0x0005
|
||||
#define DEV_ID_TYPE_CRYPT_UUID 0x0006
|
||||
#define DEV_ID_TYPE_LVMLV_UUID 0x0007
|
||||
#define DEV_ID_TYPE_DEVNAME 0x0008
|
||||
|
||||
/*
|
||||
* A device ID of a certain type for a device.
|
||||
* A struct device may have multiple dev_id structs on dev->ids.
|
||||
* One of them will be the one that's used, pointed to by dev->id.
|
||||
*/
|
||||
|
||||
struct dev_id {
|
||||
struct dm_list list;
|
||||
struct device *dev;
|
||||
uint16_t idtype; /* DEV_ID_TYPE_ */
|
||||
char *idname; /* id string determined by idtype */
|
||||
};
|
||||
|
||||
/*
|
||||
* A device listed in devices file that lvm should use.
|
||||
* Each entry in the devices file is represented by a struct dev_use.
|
||||
* The structs are kept on cmd->use_devices.
|
||||
* idtype/idname/pvid/part are set when reading the devices file.
|
||||
* du->dev is set when a struct dev_use is matched to a struct device.
|
||||
*/
|
||||
|
||||
struct dev_use {
|
||||
struct dm_list list;
|
||||
struct device *dev;
|
||||
int part;
|
||||
uint16_t idtype;
|
||||
char *idname;
|
||||
char *devname;
|
||||
char *pvid;
|
||||
};
|
||||
|
||||
/*
|
||||
* All devices in LVM will be represented by one of these.
|
||||
* pointer comparisons are valid.
|
||||
*/
|
||||
struct device {
|
||||
struct dm_list aliases; /* struct dm_str_list */
|
||||
struct dm_list ids; /* struct dev_id, different entries for different idtypes */
|
||||
struct dev_id *id; /* points to the the ids entry being used for this dev */
|
||||
dev_t dev;
|
||||
|
||||
/* private */
|
||||
@@ -72,6 +115,7 @@ struct device {
|
||||
int read_ahead;
|
||||
int bcache_fd;
|
||||
int bcache_di;
|
||||
int part; /* partition number */
|
||||
uint32_t flags;
|
||||
uint32_t filtered_flags;
|
||||
unsigned size_seqno;
|
||||
|
||||
2324
lib/device/device_id.c
Normal file
2324
lib/device/device_id.c
Normal file
File diff suppressed because it is too large
Load Diff
55
lib/device/device_id.h
Normal file
55
lib/device/device_id.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _LVM_DEVICE_ID_H
|
||||
#define _LVM_DEVICE_ID_H
|
||||
|
||||
void free_du(struct dev_use *du);
|
||||
void free_dus(struct dm_list *list);
|
||||
void free_did(struct dev_id *did);
|
||||
void free_dids(struct dm_list *list);
|
||||
const char *idtype_to_str(uint16_t idtype);
|
||||
uint16_t idtype_from_str(const char *str);
|
||||
const char *dev_idtype_for_metadata(struct cmd_context *cmd, struct device *dev);
|
||||
const char *dev_idname_for_metadata(struct cmd_context *cmd, struct device *dev);
|
||||
int device_ids_use_devname(struct cmd_context *cmd);
|
||||
int device_ids_read(struct cmd_context *cmd);
|
||||
int device_ids_write(struct cmd_context *cmd);
|
||||
int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid,
|
||||
const char *idtype_arg, const char *id_arg);
|
||||
void device_id_pvremove(struct cmd_context *cmd, struct device *dev);
|
||||
void device_ids_match(struct cmd_context *cmd);
|
||||
int device_ids_match_dev(struct cmd_context *cmd, struct device *dev);
|
||||
void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, int *device_ids_invalid, int noupdate);
|
||||
int device_ids_version_unchanged(struct cmd_context *cmd);
|
||||
void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_list, int *search_count, int noupdate);
|
||||
const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_t idtype);
|
||||
|
||||
struct dev_use *get_du_for_dev(struct cmd_context *cmd, struct device *dev);
|
||||
struct dev_use *get_du_for_pvid(struct cmd_context *cmd, const char *pvid);
|
||||
|
||||
char *devices_file_version(void);
|
||||
int devices_file_exists(struct cmd_context *cmd);
|
||||
int devices_file_touch(struct cmd_context *cmd);
|
||||
int lock_devices_file(struct cmd_context *cmd, int mode);
|
||||
int lock_devices_file_try(struct cmd_context *cmd, int mode, int *held);
|
||||
void unlock_devices_file(struct cmd_context *cmd);
|
||||
|
||||
void devices_file_init(struct cmd_context *cmd);
|
||||
void devices_file_exit(struct cmd_context *cmd);
|
||||
|
||||
void unlink_searched_devnames(struct cmd_context *cmd);
|
||||
|
||||
#endif
|
||||
@@ -95,6 +95,8 @@ const char *get_lock_type_string(lock_type_t lock_type)
|
||||
return "dlm";
|
||||
case LOCK_TYPE_SANLOCK:
|
||||
return "sanlock";
|
||||
case LOCK_TYPE_IDM:
|
||||
return "idm";
|
||||
}
|
||||
return "invalid";
|
||||
}
|
||||
@@ -111,6 +113,8 @@ lock_type_t get_lock_type_from_string(const char *str)
|
||||
return LOCK_TYPE_DLM;
|
||||
if (!strcmp(str, "sanlock"))
|
||||
return LOCK_TYPE_SANLOCK;
|
||||
if (!strcmp(str, "idm"))
|
||||
return LOCK_TYPE_IDM;
|
||||
return LOCK_TYPE_INVALID;
|
||||
}
|
||||
|
||||
@@ -399,7 +403,7 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
void *handle __attribute__((unused)))
|
||||
{
|
||||
struct lvinfo info;
|
||||
int inkernel, snap_active = 0;
|
||||
int inkernel, snap_active = 0, partial = 0, raid_is_avail = 1;
|
||||
char uuid[64] __attribute__((aligned(8)));
|
||||
const char *access_str;
|
||||
struct lv_segment *snap_seg = NULL, *mirror_seg = NULL;
|
||||
@@ -475,7 +479,7 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
snap_active ? "active" : "INACTIVE");
|
||||
}
|
||||
snap_seg = NULL;
|
||||
} else if ((snap_seg = find_snapshot(lv))) {
|
||||
} else if (lv_is_cow(lv) && (snap_seg = find_snapshot(lv))) {
|
||||
if (inkernel &&
|
||||
(snap_active = lv_snapshot_percent(snap_seg->cow,
|
||||
&snap_percent)))
|
||||
@@ -558,11 +562,18 @@ int lvdisplay_full(struct cmd_context *cmd,
|
||||
log_print("LV VDO Pool name %s", seg_lv(seg, 0)->name);
|
||||
}
|
||||
|
||||
if (lv_is_partial(lv))
|
||||
partial = 1;
|
||||
|
||||
if (lv_is_raid(lv))
|
||||
raid_is_avail = raid_is_available(lv) ? 1 : 0;
|
||||
|
||||
if (inkernel && info.suspended)
|
||||
log_print("LV Status suspended");
|
||||
else if (activation())
|
||||
log_print("LV Status %savailable",
|
||||
inkernel ? "" : "NOT ");
|
||||
log_print("LV Status %savailable%s",
|
||||
(inkernel && raid_is_avail) ? "" : "NOT ",
|
||||
partial ? " (partial)" : "");
|
||||
|
||||
/********* FIXME lv_number
|
||||
log_print("LV # %u", lv->lv_number + 1);
|
||||
|
||||
69
lib/filters/filter-deviceid.c
Normal file
69
lib/filters/filter-deviceid.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/filters/filter.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
|
||||
static int _passes_deviceid_filter(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
|
||||
{
|
||||
dev->filtered_flags &= ~DEV_FILTERED_DEVICES_FILE;
|
||||
dev->filtered_flags &= ~DEV_FILTERED_DEVICES_LIST;
|
||||
|
||||
if (!cmd->enable_devices_file && !cmd->enable_devices_list)
|
||||
return 1;
|
||||
|
||||
if (cmd->filter_deviceid_skip)
|
||||
return 1;
|
||||
|
||||
if (dev->flags & DEV_MATCHED_USE_ID)
|
||||
return 1;
|
||||
|
||||
if (cmd->enable_devices_file)
|
||||
dev->filtered_flags |= DEV_FILTERED_DEVICES_FILE;
|
||||
else if (cmd->enable_devices_list)
|
||||
dev->filtered_flags |= DEV_FILTERED_DEVICES_LIST;
|
||||
|
||||
log_debug_devs("%s: Skipping (deviceid)", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _destroy_deviceid_filter(struct dev_filter *f)
|
||||
{
|
||||
if (f->use_count)
|
||||
log_error(INTERNAL_ERROR "Destroying deviceid filter while in use %u times.", f->use_count);
|
||||
|
||||
free(f);
|
||||
}
|
||||
|
||||
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!(f = zalloc(sizeof(struct dev_filter)))) {
|
||||
log_error("deviceid filter allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->passes_filter = _passes_deviceid_filter;
|
||||
f->destroy = _destroy_deviceid_filter;
|
||||
f->use_count = 0;
|
||||
f->name = "deviceid";
|
||||
|
||||
log_debug_devs("deviceid filter initialised.");
|
||||
|
||||
return f;
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/filters/filter.h"
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
#include <libudev.h>
|
||||
#include "lib/device/dev-ext-udev-constants.h"
|
||||
@@ -27,7 +28,6 @@
|
||||
|
||||
#define MPATH_PREFIX "mpath-"
|
||||
|
||||
|
||||
struct mpath_priv {
|
||||
struct dm_pool *mem;
|
||||
struct dev_filter f;
|
||||
@@ -35,6 +35,9 @@ struct mpath_priv {
|
||||
struct dm_hash_table *hash;
|
||||
};
|
||||
|
||||
/*
|
||||
* given "/dev/foo" return "foo"
|
||||
*/
|
||||
static const char *_get_sysfs_name(struct device *dev)
|
||||
{
|
||||
const char *name;
|
||||
@@ -53,6 +56,11 @@ static const char *_get_sysfs_name(struct device *dev)
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* given major:minor
|
||||
* readlink translates /sys/dev/block/major:minor to /sys/.../foo
|
||||
* from /sys/.../foo return "foo"
|
||||
*/
|
||||
static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno,
|
||||
char *buf, size_t buf_size)
|
||||
{
|
||||
@@ -60,7 +68,7 @@ static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno,
|
||||
char path[PATH_MAX];
|
||||
int size;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d", sysfs_dir,
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d", sysfs_dir,
|
||||
(int) MAJOR(devno), (int) MINOR(devno)) < 0) {
|
||||
log_error("Sysfs path string is too long.");
|
||||
return NULL;
|
||||
@@ -102,27 +110,28 @@ static int _get_sysfs_string(const char *path, char *buffer, int max_size)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _get_sysfs_get_major_minor(const char *sysfs_dir, const char *kname, int *major, int *minor)
|
||||
static int _get_sysfs_dm_mpath(struct dev_types *dt, const char *sysfs_dir, const char *holder_name)
|
||||
{
|
||||
char path[PATH_MAX], buffer[64];
|
||||
char path[PATH_MAX];
|
||||
char buffer[128];
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/block/%s/dev", sysfs_dir, kname) < 0) {
|
||||
if (dm_snprintf(path, sizeof(path), "%sblock/%s/dm/uuid", sysfs_dir, holder_name) < 0) {
|
||||
log_error("Sysfs path string is too long.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer[0] = '\0';
|
||||
|
||||
if (!_get_sysfs_string(path, buffer, sizeof(buffer)))
|
||||
return_0;
|
||||
|
||||
if (sscanf(buffer, "%d:%d", major, minor) != 2) {
|
||||
log_error("Failed to parse major minor from %s", buffer);
|
||||
return 0;
|
||||
}
|
||||
if (!strncmp(buffer, MPATH_PREFIX, 6))
|
||||
return 1;
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_parent_mpath(const char *dir, char *name, int max_size)
|
||||
static int _get_holder_name(const char *dir, char *name, int max_size)
|
||||
{
|
||||
struct dirent *d;
|
||||
DIR *dr;
|
||||
@@ -149,13 +158,13 @@ static int _get_parent_mpath(const char *dir, char *name, int max_size)
|
||||
}
|
||||
|
||||
if (closedir(dr))
|
||||
log_sys_error("closedir", dir);
|
||||
log_sys_debug("closedir", dir);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
static int _udev_dev_is_mpath(struct device *dev)
|
||||
static int _udev_dev_is_mpath_component(struct device *dev)
|
||||
{
|
||||
const char *value;
|
||||
struct dev_ext *ext;
|
||||
@@ -174,95 +183,148 @@ static int _udev_dev_is_mpath(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int _udev_dev_is_mpath(struct device *dev)
|
||||
static int _udev_dev_is_mpath_component(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _native_dev_is_mpath(struct dev_filter *f, struct device *dev)
|
||||
static int _native_dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
struct mpath_priv *mp = (struct mpath_priv *) f->private;
|
||||
struct dev_types *dt = mp->dt;
|
||||
const char *part_name, *name;
|
||||
struct stat info;
|
||||
char path[PATH_MAX], parent_name[PATH_MAX];
|
||||
const char *part_name;
|
||||
const char *name; /* e.g. "sda" for "/dev/sda" */
|
||||
char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */
|
||||
char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */
|
||||
char dm_dev_path[PATH_MAX]; /* e.g. "/dev/dm-1" */
|
||||
char holder_name[256]; /* e.g. "dm-1" */
|
||||
const char *sysfs_dir = dm_sysfs_dir();
|
||||
int major = MAJOR(dev->dev);
|
||||
int minor = MINOR(dev->dev);
|
||||
int dev_major = MAJOR(dev->dev);
|
||||
int dev_minor = MINOR(dev->dev);
|
||||
int dm_dev_major;
|
||||
int dm_dev_minor;
|
||||
struct stat info;
|
||||
dev_t primary_dev;
|
||||
long look;
|
||||
|
||||
/* Limit this filter only to SCSI devices */
|
||||
if (!major_is_scsi_device(dt, MAJOR(dev->dev)))
|
||||
/* Limit this filter to SCSI or NVME devices */
|
||||
if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
|
||||
return 0;
|
||||
|
||||
switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
|
||||
|
||||
case 2: /* The dev is partition. */
|
||||
part_name = dev_name(dev); /* name of original dev for log_debug msg */
|
||||
if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, parent_name, sizeof(parent_name))))
|
||||
|
||||
/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
|
||||
if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
|
||||
return_0;
|
||||
|
||||
log_debug_devs("%s: Device is a partition, using primary "
|
||||
"device %s for mpath component detection",
|
||||
part_name, name);
|
||||
break;
|
||||
|
||||
case 1: /* The dev is already a primary dev. Just continue with the dev. */
|
||||
|
||||
/* gets "foo" for "/dev/foo" */
|
||||
if (!(name = _get_sysfs_name(dev)))
|
||||
return_0;
|
||||
break;
|
||||
|
||||
default: /* 0, error. */
|
||||
log_warn("Failed to get primary device for %d:%d.", major, minor);
|
||||
log_warn("Failed to get primary device for %d:%d.", dev_major, dev_minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/block/%s/holders", sysfs_dir, name) < 0) {
|
||||
if (dm_snprintf(holders_path, sizeof(holders_path), "%sblock/%s/holders", sysfs_dir, name) < 0) {
|
||||
log_warn("Sysfs path to check mpath is too long.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* also will filter out partitions */
|
||||
if (stat(path, &info))
|
||||
if (stat(holders_path, &info))
|
||||
return 0;
|
||||
|
||||
if (!S_ISDIR(info.st_mode)) {
|
||||
log_warn("Path %s is not a directory.", path);
|
||||
log_warn("Path %s is not a directory.", holders_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_get_parent_mpath(path, parent_name, sizeof(parent_name)))
|
||||
/*
|
||||
* If holders dir contains an entry such as "dm-1", then this sets
|
||||
* holder_name to "dm-1".
|
||||
*
|
||||
* If holders dir is empty, return 0 (this is generally where
|
||||
* devs that are not mpath components return.)
|
||||
*/
|
||||
if (!_get_holder_name(holders_path, holder_name, sizeof(holder_name)))
|
||||
return 0;
|
||||
|
||||
if (!_get_sysfs_get_major_minor(sysfs_dir, parent_name, &major, &minor))
|
||||
return_0;
|
||||
|
||||
if (major != dt->device_mapper_major)
|
||||
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
|
||||
log_warn("dm device path to check mpath is too long.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Avoid repeated detection of multipath device and use first checked result */
|
||||
look = (long) dm_hash_lookup_binary(mp->hash, &minor, sizeof(minor));
|
||||
/*
|
||||
* stat "/dev/dm-1" which is the holder of the dev we're checking
|
||||
* dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
|
||||
*/
|
||||
if (stat(dm_dev_path, &info)) {
|
||||
log_debug("filter-mpath %s holder %s stat result %d",
|
||||
dev_name(dev), dm_dev_path, errno);
|
||||
return 0;
|
||||
}
|
||||
dm_dev_major = (int)MAJOR(info.st_rdev);
|
||||
dm_dev_minor = (int)MINOR(info.st_rdev);
|
||||
|
||||
if (dm_dev_major != dt->device_mapper_major) {
|
||||
log_debug_devs("filter-mpath %s holder %s %d:%d does not have dm major",
|
||||
dev_name(dev), dm_dev_path, dm_dev_major, dm_dev_minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the result of checking that "/dev/dm-1" is an mpath device
|
||||
* to avoid repeating it for each path component.
|
||||
* The minor number of "/dev/dm-1" is added to the hash table with
|
||||
* const value 2 meaning that dm minor 1 (for /dev/dm-1) is a multipath dev
|
||||
* and const value 1 meaning that dm minor 1 is not a multipath dev.
|
||||
*/
|
||||
look = (long) dm_hash_lookup_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor));
|
||||
if (look > 0) {
|
||||
log_debug_devs("%s(%u:%u): already checked as %sbeing mpath.",
|
||||
parent_name, major, minor, (look > 1) ? "" : "not ");
|
||||
log_debug_devs("filter-mpath %s holder %s %u:%u already checked as %sbeing mpath.",
|
||||
dev_name(dev), holder_name, dm_dev_major, dm_dev_minor, (look > 1) ? "" : "not ");
|
||||
return (look > 1) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (lvm_dm_prefix_check(major, minor, MPATH_PREFIX)) {
|
||||
(void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)2);
|
||||
/*
|
||||
* Returns 1 if /sys/block/<holder_name>/dm/uuid indicates that
|
||||
* <holder_name> is a dm device with dm uuid prefix mpath-.
|
||||
* When true, <holder_name> will be something like "dm-1".
|
||||
*
|
||||
* (Is a hash table worth it to avoid reading one sysfs file?)
|
||||
*/
|
||||
if (_get_sysfs_dm_mpath(dt, sysfs_dir, holder_name)) {
|
||||
log_debug_devs("filter-mpath %s holder %s %u:%u ignore mpath component",
|
||||
dev_name(dev), holder_name, dm_dev_major, dm_dev_minor);
|
||||
(void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
(void) dm_hash_insert_binary(mp->hash, &minor, sizeof(minor), (void*)1);
|
||||
(void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
|
||||
static int _dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
|
||||
{
|
||||
if (dev->ext.src == DEV_EXT_NONE)
|
||||
return _native_dev_is_mpath(f, dev);
|
||||
return _native_dev_is_mpath_component(cmd, f, dev);
|
||||
|
||||
if (dev->ext.src == DEV_EXT_UDEV)
|
||||
return _udev_dev_is_mpath(dev);
|
||||
return _udev_dev_is_mpath_component(dev);
|
||||
|
||||
log_error(INTERNAL_ERROR "Missing hook for mpath recognition "
|
||||
"using external device info source %s", dev_ext_name(dev));
|
||||
@@ -272,11 +334,11 @@ static int _dev_is_mpath(struct dev_filter *f, struct device *dev)
|
||||
|
||||
#define MSG_SKIPPING "%s: Skipping mpath component device"
|
||||
|
||||
static int _ignore_mpath(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
|
||||
static int _ignore_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
|
||||
{
|
||||
dev->filtered_flags &= ~DEV_FILTERED_MPATH_COMPONENT;
|
||||
|
||||
if (_dev_is_mpath(f, dev) == 1) {
|
||||
if (_dev_is_mpath_component(cmd, f, dev) == 1) {
|
||||
if (dev->ext.src == DEV_EXT_NONE)
|
||||
log_debug_devs(MSG_SKIPPING, dev_name(dev));
|
||||
else
|
||||
@@ -303,8 +365,8 @@ static void _destroy(struct dev_filter *f)
|
||||
struct dev_filter *mpath_filter_create(struct dev_types *dt)
|
||||
{
|
||||
const char *sysfs_dir = dm_sysfs_dir();
|
||||
struct dm_pool *mem;
|
||||
struct mpath_priv *mp;
|
||||
struct dm_pool *mem;
|
||||
struct dm_hash_table *hash;
|
||||
|
||||
if (!*sysfs_dir) {
|
||||
@@ -312,7 +374,7 @@ struct dev_filter *mpath_filter_create(struct dev_types *dt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(hash = dm_hash_create(128))) {
|
||||
if (!(hash = dm_hash_create(110))) {
|
||||
log_error("mpath hash table creation failed.");
|
||||
return NULL;
|
||||
}
|
||||
@@ -328,19 +390,13 @@ struct dev_filter *mpath_filter_create(struct dev_types *dt)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
|
||||
log_error("mpath filter allocation failed.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
mp->f.passes_filter = _ignore_mpath;
|
||||
mp->f.passes_filter = _ignore_mpath_component;
|
||||
mp->f.destroy = _destroy;
|
||||
mp->f.use_count = 0;
|
||||
mp->f.private = mp;
|
||||
mp->f.name = "mpath";
|
||||
|
||||
mp->mem = mem;
|
||||
mp->dt = dt;
|
||||
mp->mem = mem;
|
||||
mp->hash = hash;
|
||||
|
||||
log_debug_devs("mpath filter initialised.");
|
||||
|
||||
@@ -58,7 +58,7 @@ static int _init_hash(struct pfilter *pf)
|
||||
if (pf->devices)
|
||||
dm_hash_destroy(pf->devices);
|
||||
|
||||
if (!(pf->devices = dm_hash_create(128)))
|
||||
if (!(pf->devices = dm_hash_create(111)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -15,11 +15,16 @@
|
||||
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/filters/filter.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
|
||||
struct rfilter {
|
||||
struct dm_pool *mem;
|
||||
dm_bitset_t accept;
|
||||
struct dm_regex *engine;
|
||||
unsigned config_filter:1;
|
||||
unsigned config_global_filter:1;
|
||||
unsigned warned_filter:1;
|
||||
unsigned warned_global_filter:1;
|
||||
};
|
||||
|
||||
static int _extract_pattern(struct dm_pool *mem, const char *pat,
|
||||
@@ -153,6 +158,22 @@ static int _accept_p(struct cmd_context *cmd, struct dev_filter *f, struct devic
|
||||
|
||||
dev->filtered_flags &= ~DEV_FILTERED_REGEX;
|
||||
|
||||
if (cmd->enable_devices_list)
|
||||
return 1;
|
||||
|
||||
if (cmd->enable_devices_file && !cmd->filter_regex_with_devices_file) {
|
||||
/* can't warn in create_filter because enable_devices_file is set later */
|
||||
if (rf->config_filter && !rf->warned_filter) {
|
||||
log_warn("Please remove the lvm.conf filter, it is ignored with the devices file.");
|
||||
rf->warned_filter = 1;
|
||||
}
|
||||
if (rf->config_global_filter && !rf->warned_global_filter) {
|
||||
log_warn("Please remove the lvm.conf global_filter, it is ignored with the devices file.");
|
||||
rf->warned_global_filter = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(sl, &dev->aliases) {
|
||||
m = dm_regex_match(rf->engine, sl->str);
|
||||
|
||||
@@ -192,7 +213,7 @@ static void _regex_destroy(struct dev_filter *f)
|
||||
dm_pool_destroy(rf->mem);
|
||||
}
|
||||
|
||||
struct dev_filter *regex_filter_create(const struct dm_config_value *patterns)
|
||||
struct dev_filter *regex_filter_create(const struct dm_config_value *patterns, int config_filter, int config_global_filter)
|
||||
{
|
||||
struct dm_pool *mem = dm_pool_create("filter regex", 10 * 1024);
|
||||
struct rfilter *rf;
|
||||
@@ -206,6 +227,9 @@ struct dev_filter *regex_filter_create(const struct dm_config_value *patterns)
|
||||
|
||||
rf->mem = mem;
|
||||
|
||||
rf->config_filter = config_filter;
|
||||
rf->config_global_filter = config_global_filter;
|
||||
|
||||
if (!_build_matcher(rf, patterns))
|
||||
goto_bad;
|
||||
|
||||
|
||||
@@ -218,15 +218,15 @@ static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", dir,
|
||||
d->d_name) < 0) {
|
||||
log_error("sysfs path name too long: %s in %s",
|
||||
d->d_name, dir);
|
||||
log_warn("WARNING: sysfs path name too long: %s in %s.",
|
||||
d->d_name, dir);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* devices have a "dev" file */
|
||||
if (dm_snprintf(file, sizeof(file), "%s/dev", path) < 0) {
|
||||
log_error("sysfs path name too long: %s in %s",
|
||||
d->d_name, dir);
|
||||
log_warn("WARNING: sysfs path name too long: %s in %s.",
|
||||
d->d_name, dir);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ static int _read_devs(struct dev_set *ds, const char *dir, unsigned sysfs_depth)
|
||||
}
|
||||
|
||||
if (closedir(dr))
|
||||
log_sys_error("closedir", dir);
|
||||
log_sys_debug("closedir", dir);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ static int _passes_usable_filter(struct cmd_context *cmd, struct dev_filter *f,
|
||||
filter_mode_t mode = data->mode;
|
||||
int skip_lvs = data->skip_lvs;
|
||||
struct dev_usable_check_params ucp = {0};
|
||||
int is_lv = 0;
|
||||
int r = 1;
|
||||
|
||||
dev->filtered_flags &= ~DEV_FILTERED_MINSIZE;
|
||||
@@ -145,8 +146,11 @@ static int _passes_usable_filter(struct cmd_context *cmd, struct dev_filter *f,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(r = device_is_usable(dev, ucp))) {
|
||||
dev->filtered_flags |= DEV_FILTERED_UNUSABLE;
|
||||
if (!(r = device_is_usable(dev, ucp, &is_lv))) {
|
||||
if (is_lv)
|
||||
dev->filtered_flags |= DEV_FILTERED_IS_LV;
|
||||
else
|
||||
dev->filtered_flags |= DEV_FILTERED_UNUSABLE;
|
||||
log_debug_devs("%s: Skipping unusable device.", dev_name(dev));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ struct dev_filter *partitioned_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *persistent_filter_create(struct dev_types *dt, struct dev_filter *f);
|
||||
struct dev_filter *sysfs_filter_create(void);
|
||||
struct dev_filter *signature_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd);
|
||||
|
||||
struct dev_filter *internal_filter_create(void);
|
||||
int internal_filter_allow(struct dm_pool *mem, struct device *dev);
|
||||
@@ -43,7 +44,7 @@ void internal_filter_clear(void);
|
||||
* r|.*| - reject everything else
|
||||
*/
|
||||
|
||||
struct dev_filter *regex_filter_create(const struct dm_config_value *patterns);
|
||||
struct dev_filter *regex_filter_create(const struct dm_config_value *patterns, int config_filter, int config_global_filter);
|
||||
|
||||
typedef enum {
|
||||
FILTER_MODE_NO_LVMETAD,
|
||||
@@ -63,5 +64,8 @@ struct dev_filter *usable_filter_create(struct cmd_context *cmd, struct dev_type
|
||||
#define DEV_FILTERED_DEVTYPE 0x00000100
|
||||
#define DEV_FILTERED_MINSIZE 0x00000200
|
||||
#define DEV_FILTERED_UNUSABLE 0x00000400
|
||||
#define DEV_FILTERED_DEVICES_FILE 0x00000800
|
||||
#define DEV_FILTERED_DEVICES_LIST 0x00001000
|
||||
#define DEV_FILTERED_IS_LV 0x00002000
|
||||
|
||||
#endif /* _LVM_FILTER_H */
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "lib/format_text/archiver.h"
|
||||
#include "lib/format_text/format-text.h"
|
||||
#include "lib/misc/lvm-string.h"
|
||||
#include "lib/misc/lvm-signal.h"
|
||||
#include "lib/cache/lvmcache.h"
|
||||
#include "lib/mm/memlock.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
@@ -102,13 +103,13 @@ static int _archive(struct volume_group *vg, int compulsory)
|
||||
{
|
||||
char *desc;
|
||||
|
||||
if (vg_is_archived(vg))
|
||||
return 1; /* VG has been already archived */
|
||||
|
||||
/* Don't archive orphan VGs. */
|
||||
if (is_orphan_vg(vg->name))
|
||||
return 1;
|
||||
|
||||
if (vg_is_archived(vg))
|
||||
return 1; /* VG has been already archived */
|
||||
|
||||
if (!vg->cmd->archive_params->enabled || !vg->cmd->archive_params->dir) {
|
||||
vg->status |= ARCHIVED_VG;
|
||||
return 1;
|
||||
@@ -155,7 +156,13 @@ static int _archive(struct volume_group *vg, int compulsory)
|
||||
|
||||
int archive(struct volume_group *vg)
|
||||
{
|
||||
return _archive(vg, 1);
|
||||
int r;
|
||||
|
||||
sigint_allow();
|
||||
r = _archive(vg, 1);
|
||||
sigint_restore();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int archive_display(struct cmd_context *cmd, const char *vg_name)
|
||||
@@ -218,6 +225,7 @@ static int _backup(struct volume_group *vg)
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
char *desc;
|
||||
int r;
|
||||
|
||||
if (!(desc = _build_desc(vg->cmd->mem, vg->cmd->cmd_line, 0)))
|
||||
return_0;
|
||||
@@ -229,7 +237,11 @@ static int _backup(struct volume_group *vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return backup_to_file(name, desc, vg);
|
||||
sigint_allow();
|
||||
r = backup_to_file(name, desc, vg);
|
||||
sigint_restore();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int backup_locally(struct volume_group *vg)
|
||||
@@ -267,6 +279,7 @@ int backup_locally(struct volume_group *vg)
|
||||
|
||||
int backup(struct volume_group *vg)
|
||||
{
|
||||
|
||||
/* Unlock memory if possible */
|
||||
memlock_unlock(vg->cmd);
|
||||
|
||||
@@ -321,7 +334,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd,
|
||||
}
|
||||
|
||||
if (vg)
|
||||
set_pv_devices(tf, vg, NULL);
|
||||
set_pv_devices(tf, vg);
|
||||
|
||||
if (!vg)
|
||||
tf->fmt->ops->destroy_instance(tf);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "lib/metadata/segtype.h"
|
||||
#include "lib/format_text/text_export.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "libdaemon/client/config-util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
@@ -527,6 +528,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
struct physical_volume *pv;
|
||||
char buffer[PATH_MAX * 2];
|
||||
const char *name;
|
||||
const char *idtype, *idname;
|
||||
|
||||
outf(f, "physical_volumes {");
|
||||
_inc_indent(f);
|
||||
@@ -555,6 +557,13 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
dm_escape_double_quotes(buffer, pv_dev_name(pv)));
|
||||
outnl(f);
|
||||
|
||||
idtype = dev_idtype_for_metadata(vg->cmd, pv->dev);
|
||||
idname = dev_idname_for_metadata(vg->cmd, pv->dev);
|
||||
if (idtype && idname) {
|
||||
outf(f, "device_id_type = \"%s\"", idtype);
|
||||
outf(f, "device_id = \"%s\"", idname);
|
||||
}
|
||||
|
||||
if (!_print_flag_config(f, pv->status, PV_FLAGS))
|
||||
return_0;
|
||||
|
||||
@@ -871,45 +880,50 @@ bad:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _print_historical_lv(struct formatter *f, struct historical_logical_volume *hlv)
|
||||
static int _print_historical_lv_with_descendants(struct formatter *f, struct historical_logical_volume *hlv,
|
||||
char *descendants_buffer)
|
||||
{
|
||||
char buffer[40];
|
||||
char *descendants_buffer = NULL;
|
||||
int r = 0;
|
||||
|
||||
if (!id_write_format(&hlv->lvid.id[1], buffer, sizeof(buffer)))
|
||||
goto_out;
|
||||
return_0;
|
||||
|
||||
if (!_alloc_printed_indirect_descendants(&hlv->indirect_glvs, &descendants_buffer))
|
||||
goto_out;
|
||||
|
||||
outnlgo(f);
|
||||
outfgo(f, "%s {", hlv->name);
|
||||
outnl(f);
|
||||
outf(f, "%s {", hlv->name);
|
||||
_inc_indent(f);
|
||||
|
||||
outfgo(f, "id = \"%s\"", buffer);
|
||||
outf(f, "id = \"%s\"", buffer);
|
||||
|
||||
if (!_print_timestamp(f, "creation_time", hlv->timestamp, buffer, sizeof(buffer)))
|
||||
goto_out;
|
||||
return_0;
|
||||
|
||||
if (!_print_timestamp(f, "removal_time", hlv->timestamp_removed, buffer, sizeof(buffer)))
|
||||
goto_out;
|
||||
return_0;
|
||||
|
||||
if (hlv->indirect_origin) {
|
||||
if (hlv->indirect_origin->is_historical)
|
||||
outfgo(f, "origin = \"%s%s\"", HISTORICAL_LV_PREFIX, hlv->indirect_origin->historical->name);
|
||||
outf(f, "origin = \"%s%s\"", HISTORICAL_LV_PREFIX, hlv->indirect_origin->historical->name);
|
||||
else
|
||||
outfgo(f, "origin = \"%s\"", hlv->indirect_origin->live->name);
|
||||
outf(f, "origin = \"%s\"", hlv->indirect_origin->live->name);
|
||||
}
|
||||
|
||||
if (descendants_buffer)
|
||||
outfgo(f, "descendants = %s", descendants_buffer);
|
||||
outf(f, "descendants = %s", descendants_buffer);
|
||||
|
||||
_dec_indent(f);
|
||||
outfgo(f, "}");
|
||||
outf(f, "}");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _print_historical_lv(struct formatter *f, struct historical_logical_volume *hlv)
|
||||
{
|
||||
char *descendants_buffer = NULL;
|
||||
int r = 0;
|
||||
|
||||
if (_alloc_printed_indirect_descendants(&hlv->indirect_glvs, &descendants_buffer))
|
||||
r = _print_historical_lv_with_descendants(f, hlv, descendants_buffer);
|
||||
|
||||
r = 1;
|
||||
out:
|
||||
free(descendants_buffer);
|
||||
|
||||
return r;
|
||||
@@ -946,12 +960,13 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
||||
int count = 0;
|
||||
struct pv_list *pvl;
|
||||
struct physical_volume *pv;
|
||||
char buffer[32], *uuid, *name;
|
||||
char buffer[32], *name;
|
||||
char uuid[64];
|
||||
|
||||
if (!(f->mem = dm_pool_create("text pv_names", 512)))
|
||||
return_0;
|
||||
|
||||
if (!(f->pv_names = dm_hash_create(128)))
|
||||
if (!(f->pv_names = dm_hash_create(115)))
|
||||
return_0;
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
@@ -964,8 +979,7 @@ static int _build_pv_names(struct formatter *f, struct volume_group *vg)
|
||||
if (!(name = dm_pool_strdup(f->mem, buffer)))
|
||||
return_0;
|
||||
|
||||
if (!(uuid = dm_pool_zalloc(f->mem, 64)) ||
|
||||
!id_write_format(&pv->id, uuid, 64))
|
||||
if (!id_write_format(&pv->id, uuid, sizeof(uuid)))
|
||||
return_0;
|
||||
|
||||
if (!dm_hash_insert(f->pv_names, uuid, name))
|
||||
@@ -1031,62 +1045,53 @@ static int _text_vg_export(struct formatter *f,
|
||||
|
||||
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp)
|
||||
{
|
||||
struct formatter *f;
|
||||
int r;
|
||||
struct formatter f = {
|
||||
.indent = 0,
|
||||
.header = 1,
|
||||
.out_with_comment = &_out_with_comment_file,
|
||||
.nl = &_nl_file,
|
||||
.data.fp = fp,
|
||||
};
|
||||
|
||||
_init();
|
||||
|
||||
if (!(f = zalloc(sizeof(*f))))
|
||||
return_0;
|
||||
if ((r = _text_vg_export(&f, vg, desc)))
|
||||
r = !ferror(f.data.fp);
|
||||
|
||||
f->data.fp = fp;
|
||||
f->indent = 0;
|
||||
f->header = 1;
|
||||
f->out_with_comment = &_out_with_comment_file;
|
||||
f->nl = &_nl_file;
|
||||
|
||||
r = _text_vg_export(f, vg, desc);
|
||||
if (r)
|
||||
r = !ferror(f->data.fp);
|
||||
free(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Returns amount of buffer used incl. terminating NUL */
|
||||
size_t text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf, uint32_t *buf_size)
|
||||
{
|
||||
struct formatter *f;
|
||||
size_t r = 0;
|
||||
size_t r;
|
||||
struct formatter f = {
|
||||
.indent = 0,
|
||||
.header = 0,
|
||||
.out_with_comment = &_out_with_comment_raw,
|
||||
.nl = &_nl_raw,
|
||||
.data.buf.size = 65536, /* Initial metadata limit */
|
||||
};
|
||||
|
||||
_init();
|
||||
|
||||
if (!(f = zalloc(sizeof(*f))))
|
||||
return_0;
|
||||
|
||||
f->data.buf.size = 65536; /* Initial metadata limit */
|
||||
if (!(f->data.buf.start = zalloc(f->data.buf.size))) {
|
||||
if (!(f.data.buf.start = zalloc(f.data.buf.size))) {
|
||||
log_error("text_export buffer allocation failed");
|
||||
goto out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
f->indent = 0;
|
||||
f->header = 0;
|
||||
f->out_with_comment = &_out_with_comment_raw;
|
||||
f->nl = &_nl_raw;
|
||||
|
||||
if (!_text_vg_export(f, vg, desc)) {
|
||||
free(f->data.buf.start);
|
||||
goto_out;
|
||||
if (!_text_vg_export(&f, vg, desc)) {
|
||||
free(f.data.buf.start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = f->data.buf.used + 1;
|
||||
*buf = f->data.buf.start;
|
||||
r = f.data.buf.used + 1;
|
||||
*buf = f.data.buf.start;
|
||||
|
||||
if (buf_size)
|
||||
*buf_size = f->data.buf.size;
|
||||
*buf_size = f.data.buf.size;
|
||||
|
||||
out:
|
||||
free(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ static const struct flag _vg_flags[] = {
|
||||
{LVM_READ, "READ", STATUS_FLAG},
|
||||
{LVM_WRITE, "WRITE", STATUS_FLAG},
|
||||
{LVM_WRITE_LOCKED, "WRITE_LOCKED", COMPATIBLE_FLAG},
|
||||
{NOAUTOACTIVATE, "NOAUTOACTIVATE", COMPATIBLE_FLAG},
|
||||
{CLUSTERED, "CLUSTERED", STATUS_FLAG},
|
||||
{SHARED, "SHARED", STATUS_FLAG},
|
||||
{PARTIAL_VG, NULL, 0},
|
||||
@@ -70,8 +71,10 @@ static const struct flag _lv_flags[] = {
|
||||
{LV_REMOVE_AFTER_RESHAPE, "REMOVE_AFTER_RESHAPE", SEGTYPE_FLAG},
|
||||
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
|
||||
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
|
||||
{LV_NOAUTOACTIVATE, "NOAUTOACTIVATE", COMPATIBLE_FLAG},
|
||||
{LV_ERROR_WHEN_FULL, "ERROR_WHEN_FULL", COMPATIBLE_FLAG},
|
||||
{LV_METADATA_FORMAT, "METADATA_FORMAT", SEGTYPE_FLAG},
|
||||
{LV_CROP_METADATA, "CROP_METADATA", SEGTYPE_FLAG},
|
||||
{LV_CACHE_VOL, "CACHE_VOL", COMPATIBLE_FLAG},
|
||||
{LV_CACHE_USES_CACHEVOL, "CACHE_USES_CACHEVOL", SEGTYPE_FLAG},
|
||||
{LV_NOSCAN, NULL, 0},
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "lib/mm/xlate.h"
|
||||
#include "lib/label/label.h"
|
||||
#include "lib/cache/lvmcache.h"
|
||||
#include "libdaemon/client/config-util.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
@@ -63,8 +64,7 @@ void free_text_fidtc(struct volume_group *vg)
|
||||
|
||||
fidtc->preserve = 0;
|
||||
|
||||
if (fidtc->write_buf)
|
||||
free(fidtc->write_buf);
|
||||
free(fidtc->write_buf);
|
||||
fidtc->write_buf = NULL;
|
||||
fidtc->write_buf_size = 0;
|
||||
fidtc->new_metadata_size = 0;
|
||||
@@ -580,6 +580,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
struct metadata_area *mda)
|
||||
{
|
||||
char desc[2048];
|
||||
struct dm_config_tree *cft;
|
||||
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
|
||||
struct text_fid_context *fidtc = (struct text_fid_context *) fid->private;
|
||||
struct raw_locn *rlocn_old;
|
||||
@@ -660,14 +661,29 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
|
||||
(void) dm_snprintf(desc, sizeof(desc), "Write[%u] from %s.", vg->write_count, vg->cmd->cmd_line);
|
||||
|
||||
new_size = text_vg_export_raw(vg, desc, &write_buf, &write_buf_size);
|
||||
if (!new_size || !write_buf) {
|
||||
log_error("VG %s metadata writing failed", vg->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fidtc->write_buf = write_buf;
|
||||
fidtc->write_buf_size = write_buf_size;
|
||||
fidtc->new_metadata_size = new_size;
|
||||
}
|
||||
|
||||
if (!new_size || !write_buf) {
|
||||
log_error("VG %s metadata writing failed", vg->name);
|
||||
goto out;
|
||||
/* Immediatelly reuse existing buffer for parsing metadata back.
|
||||
* Such VG is then used for as precommitted VG and later committed VG.
|
||||
*
|
||||
* 'Lazy' creation of such VG might improve performance, but we
|
||||
* lose important validation that written metadata can be parsed. */
|
||||
if (!(cft = config_tree_from_string_without_dup_node_check(write_buf))) {
|
||||
log_error("Error parsing metadata for VG %s.", vg->name);
|
||||
goto out;
|
||||
}
|
||||
release_vg(vg->vg_precommitted);
|
||||
vg->vg_precommitted = import_vg_from_config_tree(vg->cmd, vg->fid, cft);
|
||||
dm_config_destroy(cft);
|
||||
if (!vg->vg_precommitted)
|
||||
goto_out;
|
||||
}
|
||||
|
||||
log_debug_metadata("VG %s seqno %u metadata write to %s mda_start %llu mda_size %llu mda_last %llu",
|
||||
@@ -1630,7 +1646,9 @@ int read_metadata_location_summary(const struct format_type *fmt,
|
||||
vgsummary->mda_size = rlocn->size;
|
||||
|
||||
/* Keep track of largest metadata size we find. */
|
||||
lvmcache_save_metadata_size(rlocn->size);
|
||||
lvmcache_save_metadata_size_bytes(rlocn->size);
|
||||
/* Keep track of the most full metadata area. */
|
||||
lvmcache_save_metadata_size_percent(rlocn->size, mdah->size);
|
||||
|
||||
lvmcache_lookup_mda(vgsummary);
|
||||
|
||||
@@ -2018,9 +2036,7 @@ static void _text_destroy(struct format_type *fmt)
|
||||
if (fmt->orphan_vg)
|
||||
free_orphan_vg(fmt->orphan_vg);
|
||||
|
||||
if (fmt->private)
|
||||
free(fmt->private);
|
||||
|
||||
free(fmt->private);
|
||||
free(fmt);
|
||||
}
|
||||
|
||||
@@ -2209,7 +2225,7 @@ static int _create_vg_text_instance(struct format_instance *fid,
|
||||
vg_name = fic->context.vg_ref.vg_name;
|
||||
vg_id = fic->context.vg_ref.vg_id;
|
||||
|
||||
if (!(fid->metadata_areas_index = dm_hash_create(128))) {
|
||||
if (!(fid->metadata_areas_index = dm_hash_create(116))) {
|
||||
log_error("Couldn't create metadata index for format "
|
||||
"instance of VG %s.", vg_name);
|
||||
return 0;
|
||||
|
||||
@@ -186,6 +186,8 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
|
||||
goto_out;
|
||||
|
||||
(*vsn)->read_desc(vg->vgmem, cft, when, desc);
|
||||
vg->committed_cft = cft; /* Reuse CFT for recreation of committed VG */
|
||||
cft = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -198,7 +200,8 @@ struct volume_group *text_read_metadata(struct format_instance *fid,
|
||||
*use_previous_vg = 0;
|
||||
|
||||
out:
|
||||
config_destroy(cft);
|
||||
if (cft)
|
||||
config_destroy(cft);
|
||||
return vg;
|
||||
}
|
||||
|
||||
@@ -231,7 +234,7 @@ static struct volume_group *_import_vg_from_config_tree(struct cmd_context *cmd,
|
||||
if (!(vg = (*vsn)->read_vg(cmd, fid->fmt, fid, cft)))
|
||||
stack;
|
||||
else {
|
||||
set_pv_devices(fid, vg, NULL);
|
||||
set_pv_devices(fid, vg);
|
||||
|
||||
if ((vg_missing = vg_missing_pv_count(vg)))
|
||||
log_verbose("There are %d physical volumes missing.", vg_missing);
|
||||
|
||||
@@ -128,7 +128,7 @@ static int _read_id(struct id *id, const struct dm_config_node *cn, const char *
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _read_flag_config(const struct dm_config_node *n, uint64_t *status, int type)
|
||||
static int _read_flag_config(const struct dm_config_node *n, uint64_t *status, enum pv_vg_lv_e type)
|
||||
{
|
||||
const struct dm_config_value *cv;
|
||||
*status = 0;
|
||||
@@ -188,7 +188,7 @@ static int _read_pv(struct cmd_context *cmd,
|
||||
struct physical_volume *pv;
|
||||
struct pv_list *pvl;
|
||||
const struct dm_config_value *cv;
|
||||
const char *device_hint;
|
||||
const char *str;
|
||||
uint64_t size, ba_start;
|
||||
|
||||
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
|
||||
@@ -233,11 +233,21 @@ static int _read_pv(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dm_config_get_str(pvn, "device", &device_hint)) {
|
||||
if (!(pv->device_hint = dm_pool_strdup(mem, device_hint)))
|
||||
if (dm_config_get_str(pvn, "device", &str)) {
|
||||
if (!(pv->device_hint = dm_pool_strdup(mem, str)))
|
||||
log_error("Failed to allocate memory for device hint in read_pv.");
|
||||
}
|
||||
|
||||
if (dm_config_get_str(pvn, "device_id", &str)) {
|
||||
if (!(pv->device_id = dm_pool_strdup(mem, str)))
|
||||
log_error("Failed to allocate memory for device_id in read_pv.");
|
||||
}
|
||||
|
||||
if (dm_config_get_str(pvn, "device_id_type", &str)) {
|
||||
if (!(pv->device_id_type = dm_pool_strdup(mem, str)))
|
||||
log_error("Failed to allocate memory for device_id_type in read_pv.");
|
||||
}
|
||||
|
||||
if (!_read_uint64(pvn, "pe_start", &pv->pe_start)) {
|
||||
log_error("Couldn't read extent start value (pe_start) "
|
||||
"for physical volume.");
|
||||
@@ -306,7 +316,7 @@ static int _read_pvsummary(struct cmd_context *cmd,
|
||||
{
|
||||
struct physical_volume *pv;
|
||||
struct pv_list *pvl;
|
||||
const char *device_hint;
|
||||
const char *str;
|
||||
|
||||
if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl))) ||
|
||||
!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv))))
|
||||
@@ -326,9 +336,19 @@ static int _read_pvsummary(struct cmd_context *cmd,
|
||||
!_read_uint64(pvn, "dev_size", &pv->size))
|
||||
log_warn("Couldn't read dev size for physical volume.");
|
||||
|
||||
if (dm_config_get_str(pvn, "device", &device_hint)) {
|
||||
if (!(pv->device_hint = dm_pool_strdup(mem, device_hint)))
|
||||
log_error("Failed to allocate memory for device hint in read_pv.");
|
||||
if (dm_config_get_str(pvn, "device", &str)) {
|
||||
if (!(pv->device_hint = dm_pool_strdup(mem, str)))
|
||||
log_error("Failed to allocate memory for device hint in read_pv_sum.");
|
||||
}
|
||||
|
||||
if (dm_config_get_str(pvn, "device_id", &str)) {
|
||||
if (!(pv->device_id = dm_pool_strdup(mem, str)))
|
||||
log_error("Failed to allocate memory for device_id in read_pv_sum.");
|
||||
}
|
||||
|
||||
if (dm_config_get_str(pvn, "device_id_type", &str)) {
|
||||
if (!(pv->device_id_type = dm_pool_strdup(mem, str)))
|
||||
log_error("Failed to allocate memory for device_id_type in read_pv_sum.");
|
||||
}
|
||||
|
||||
dm_list_add(&vgsummary->pvsummaries, &pvl->list);
|
||||
@@ -1054,7 +1074,7 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
|
||||
* The pv hash memorises the pv section names -> pv
|
||||
* structures.
|
||||
*/
|
||||
if (!(pv_hash = dm_hash_create(64))) {
|
||||
if (!(pv_hash = dm_hash_create(59))) {
|
||||
log_error("Couldn't create pv hash table.");
|
||||
goto bad;
|
||||
}
|
||||
@@ -1063,7 +1083,7 @@ static struct volume_group *_read_vg(struct cmd_context *cmd,
|
||||
* The lv hash memorises the lv section names -> lv
|
||||
* structures.
|
||||
*/
|
||||
if (!(lv_hash = dm_hash_create(1024))) {
|
||||
if (!(lv_hash = dm_hash_create(1023))) {
|
||||
log_error("Couldn't create lv hash table.");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@@ -20,9 +20,7 @@
|
||||
#define outhint(args...) do {if (!out_hint(args)) return_0;} while (0)
|
||||
#define outfc(args...) do {if (!out_text_with_comment(args)) return_0;} while (0)
|
||||
#define outf(args...) do {if (!out_text(args)) return_0;} while (0)
|
||||
#define outfgo(args...) do {if (!out_text(args)) goto_out;} while (0)
|
||||
#define outnl(f) do {if (!out_newline(f)) return_0;} while (0)
|
||||
#define outnlgo(f) do {if (!out_newline(f)) goto_out;} while (0)
|
||||
|
||||
struct formatter;
|
||||
struct lv_segment;
|
||||
|
||||
@@ -379,7 +379,7 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
|
||||
struct label_header *lh = (struct label_header *) label_buf;
|
||||
struct pv_header *pvhdr;
|
||||
struct pv_header_extension *pvhdr_ext;
|
||||
struct metadata_area *mda;
|
||||
struct metadata_area *mda = NULL;
|
||||
struct metadata_area *mda1 = NULL;
|
||||
struct metadata_area *mda2 = NULL;
|
||||
struct disk_locn *dlocn_xl;
|
||||
|
||||
@@ -240,9 +240,8 @@ static int _target_present(struct cmd_context *cmd,
|
||||
|
||||
if (!_integrity_checked) {
|
||||
_integrity_checked = 1;
|
||||
_integrity_present = target_present(cmd, TARGET_NAME_INTEGRITY, 1);
|
||||
|
||||
if (!target_version(TARGET_NAME_INTEGRITY, &maj, &min, &patchlevel))
|
||||
if (!(_integrity_present = target_present_version(cmd, TARGET_NAME_INTEGRITY, 1,
|
||||
&maj, &min, &patchlevel)))
|
||||
return 0;
|
||||
|
||||
if (maj < 1 || min < 6) {
|
||||
@@ -295,7 +294,7 @@ static int _integrity_add_target_line(struct dev_manager *dm,
|
||||
|
||||
if (!seg->integrity_data_sectors) {
|
||||
log_error("_integrity_add_target_line zero size");
|
||||
return_0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dm_tree_node_add_integrity_target(node, seg->integrity_data_sectors,
|
||||
|
||||
@@ -145,6 +145,7 @@
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/label/hints.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
#include "lib/device/device_id.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -166,8 +167,10 @@ static const char *_newhints_file = DEFAULT_RUN_DIR "/newhints";
|
||||
* than they were built with. Increase the minor number
|
||||
* when adding features that older lvm versions can just
|
||||
* ignore while continuing to use the other content.
|
||||
*
|
||||
* MAJOR 2: add devices_file
|
||||
*/
|
||||
#define HINTS_VERSION_MAJOR 1
|
||||
#define HINTS_VERSION_MAJOR 2
|
||||
#define HINTS_VERSION_MINOR 1
|
||||
|
||||
#define HINT_LINE_LEN (PATH_MAX + NAME_LEN + ID_LEN + 64)
|
||||
@@ -445,7 +448,7 @@ static int _dev_in_hint_hash(struct cmd_context *cmd, struct device *dev)
|
||||
return 0;
|
||||
|
||||
if (!dev_get_size(dev, &devsize) || !devsize)
|
||||
return_0;
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -712,8 +715,9 @@ static int _read_hint_file(struct cmd_context *cmd, struct dm_list *hints, int *
|
||||
break;
|
||||
}
|
||||
|
||||
if (hv_major > HINTS_VERSION_MAJOR) {
|
||||
log_debug("ignore hints with newer major version %d.%d", hv_major, hv_minor);
|
||||
if (hv_major != HINTS_VERSION_MAJOR) {
|
||||
log_debug("ignore hints with version %d.%d current %d.%d",
|
||||
hv_major, hv_minor, HINTS_VERSION_MAJOR, HINTS_VERSION_MINOR);
|
||||
*needs_refresh = 1;
|
||||
break;
|
||||
}
|
||||
@@ -758,6 +762,25 @@ static int _read_hint_file(struct cmd_context *cmd, struct dm_list *hints, int *
|
||||
continue;
|
||||
}
|
||||
|
||||
keylen = strlen("devices_file:");
|
||||
if (!strncmp(_hint_line, "devices_file:", keylen)) {
|
||||
const char *df_hint = _hint_line + keylen;
|
||||
const char *df_config = find_config_tree_str(cmd, devices_devicesfile_CFG, NULL);
|
||||
/* when a devices file is not used, hints should have devices_file:. */
|
||||
if (!cmd->enable_devices_file || !df_hint || !df_config) {
|
||||
if (df_hint[0] != '.') {
|
||||
log_debug("ignore hints with different devices_file: not enabled vs %s", df_hint);
|
||||
*needs_refresh = 1;
|
||||
break;
|
||||
}
|
||||
} else if (strcmp(df_hint, df_config)) {
|
||||
log_debug("ignore hints with different devices_file: %s vs %s", df_hint, df_config);
|
||||
*needs_refresh = 1;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
keylen = strlen("devs_hash:");
|
||||
if (!strncmp(_hint_line, "devs_hash:", keylen)) {
|
||||
if (sscanf(_hint_line + keylen, "%u %u", &read_hash, &read_count) != 2) {
|
||||
@@ -827,8 +850,12 @@ static int _read_hint_file(struct cmd_context *cmd, struct dm_list *hints, int *
|
||||
if (!(iter = dev_iter_create(NULL, 0)))
|
||||
return 0;
|
||||
while ((dev = dev_iter_get(cmd, iter))) {
|
||||
if (cmd->enable_devices_file && !get_du_for_dev(cmd, dev))
|
||||
continue;
|
||||
|
||||
if (!_dev_in_hint_hash(cmd, dev))
|
||||
continue;
|
||||
|
||||
(void) dm_strncpy(devpath, dev_name(dev), sizeof(devpath));
|
||||
calc_hash = calc_crc(calc_hash, (const uint8_t *)devpath, strlen(devpath));
|
||||
calc_count++;
|
||||
@@ -887,6 +914,7 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
|
||||
struct device *dev;
|
||||
const char *vgname;
|
||||
char *filter_str = NULL;
|
||||
const char *config_devices_file = NULL;
|
||||
uint32_t hash = INITIAL_CRC;
|
||||
uint32_t count = 0;
|
||||
time_t t;
|
||||
@@ -947,6 +975,19 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
|
||||
|
||||
fprintf(fp, "scan_lvs:%d\n", cmd->scan_lvs);
|
||||
|
||||
/*
|
||||
* Only associate hints with the default/system devices file.
|
||||
* If no default/system devices file is used, "." is set.
|
||||
* If we are using a devices file other than the config setting
|
||||
* (from --devicesfile), then we should not be using hints and
|
||||
* shouldn't get here.
|
||||
*/
|
||||
config_devices_file = find_config_tree_str(cmd, devices_devicesfile_CFG, NULL);
|
||||
if (cmd->enable_devices_file && !cmd->devicesfile && config_devices_file)
|
||||
fprintf(fp, "devices_file:%s\n", config_devices_file);
|
||||
else
|
||||
fprintf(fp, "devices_file:.\n");
|
||||
|
||||
/*
|
||||
* iterate through all devs and write a line for each
|
||||
* dev flagged DEV_SCAN_FOUND_LABEL
|
||||
@@ -964,6 +1005,9 @@ int write_hint_file(struct cmd_context *cmd, int newhints)
|
||||
* 2. add PVs to the hint file
|
||||
*/
|
||||
while ((dev = dev_iter_get(cmd, iter))) {
|
||||
if (cmd->enable_devices_file && !get_du_for_dev(cmd, dev))
|
||||
continue;
|
||||
|
||||
if (!_dev_in_hint_hash(cmd, dev)) {
|
||||
if (dev->flags & DEV_SCAN_FOUND_LABEL) {
|
||||
/* should never happen */
|
||||
@@ -1244,12 +1288,14 @@ check:
|
||||
*/
|
||||
|
||||
int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
struct dm_list *devs_in, struct dm_list *devs_out)
|
||||
struct dm_list *devs_in, struct dm_list *devs_out, char **vgname_out)
|
||||
{
|
||||
struct dm_list hints_list;
|
||||
int needs_refresh = 0;
|
||||
char *vgname = NULL;
|
||||
|
||||
*vgname_out = NULL;
|
||||
|
||||
dm_list_init(&hints_list);
|
||||
|
||||
/* Decide below if the caller should create new hints. */
|
||||
@@ -1328,7 +1374,7 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
}
|
||||
|
||||
/*
|
||||
* couln't read file for some reason, not normal, just skip using hints
|
||||
* couldn't read file for some reason, not normal, just skip using hints
|
||||
*/
|
||||
if (!_read_hint_file(cmd, &hints_list, &needs_refresh)) {
|
||||
log_debug("get_hints: read fail");
|
||||
@@ -1353,7 +1399,6 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
/* create new hints after scan */
|
||||
*newhints = NEWHINTS_REFRESH;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1385,12 +1430,12 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
|
||||
_apply_hints(cmd, &hints_list, vgname, devs_in, devs_out);
|
||||
|
||||
log_debug("get_hints: applied using %d other %d",
|
||||
dm_list_size(devs_out), dm_list_size(devs_in));
|
||||
log_debug("get_hints: applied using %d other %d vgname %s",
|
||||
dm_list_size(devs_out), dm_list_size(devs_in), vgname ?: "");
|
||||
|
||||
dm_list_splice(hints_out, &hints_list);
|
||||
|
||||
free(vgname);
|
||||
*vgname_out = vgname;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
struct hint {
|
||||
struct dm_list list;
|
||||
char name[PATH_MAX];
|
||||
char pvid[ID_LEN + 1];
|
||||
char vgname[NAME_LEN];
|
||||
dev_t devt;
|
||||
char name[PATH_MAX] __attribute__((aligned(8)));
|
||||
char vgname[NAME_LEN] __attribute__((aligned(8)));
|
||||
char pvid[ID_LEN + 1] __attribute__((aligned(8)));
|
||||
unsigned chosen:1; /* this hint's dev was chosen for scanning */
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ void clear_hint_file(struct cmd_context *cmd);
|
||||
void invalidate_hints(struct cmd_context *cmd);
|
||||
|
||||
int get_hints(struct cmd_context *cmd, struct dm_list *hints, int *newhints,
|
||||
struct dm_list *devs_in, struct dm_list *devs_out);
|
||||
struct dm_list *devs_in, struct dm_list *devs_out, char **vgname_out);
|
||||
|
||||
int validate_hints(struct cmd_context *cmd, struct dm_list *hints);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "lib/label/hints.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/format_text/layout.h"
|
||||
#include "lib/device/device_id.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -581,7 +582,8 @@ retry_open:
|
||||
|
||||
if (di == -1) {
|
||||
log_error("Failed to set bcache fd.");
|
||||
close(fd);
|
||||
if (close(fd))
|
||||
log_sys_debug("close", name);
|
||||
dev->bcache_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
@@ -805,16 +807,6 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This will search the system's /dev for new path names and
|
||||
* could help us reopen the device if it finds a new preferred
|
||||
* path name for this dev's major:minor. It does that by
|
||||
* inserting a new preferred path name on dev->aliases. open
|
||||
* uses the first name from that list.
|
||||
*/
|
||||
log_debug_devs("Scanning refreshing device paths.");
|
||||
dev_cache_scan();
|
||||
|
||||
/* Put devs that failed to open back on the original list to retry. */
|
||||
dm_list_splice(devs, &reopen_devs);
|
||||
goto scan_more;
|
||||
@@ -936,6 +928,12 @@ static void _prepare_open_file_limit(struct cmd_context *cmd, unsigned int num_d
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently the only caller is pvck which probably doesn't need
|
||||
* deferred filters checked after the read... it wants to know if
|
||||
* anything has the pvid, even a dev that might be filtered.
|
||||
*/
|
||||
|
||||
int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev_out)
|
||||
{
|
||||
char buf[LABEL_SIZE] __attribute__((aligned(8)));
|
||||
@@ -948,7 +946,20 @@ int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev
|
||||
|
||||
dm_list_init(&devs);
|
||||
|
||||
dev_cache_scan();
|
||||
/*
|
||||
* Creates a list of available devices, does not open or read any,
|
||||
* and does not filter them.
|
||||
*/
|
||||
if (!setup_devices(cmd)) {
|
||||
log_error("Failed to set up devices.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterating over all available devices with cmd->filter filters
|
||||
* devices; those returned from dev_iter_get are the devs that
|
||||
* pass filters, and are those we can use.
|
||||
*/
|
||||
|
||||
if (!(iter = dev_iter_create(cmd->filter, 0))) {
|
||||
log_error("Scanning failed to get devices.");
|
||||
@@ -1021,7 +1032,9 @@ int label_scan(struct cmd_context *cmd)
|
||||
struct dev_iter *iter;
|
||||
struct device_list *devl, *devl2;
|
||||
struct device *dev;
|
||||
char *vgname_hint = NULL;
|
||||
uint64_t max_metadata_size_bytes;
|
||||
int device_ids_invalid = 0;
|
||||
int using_hints;
|
||||
int create_hints = 0; /* NEWHINTS_NONE */
|
||||
|
||||
@@ -1038,12 +1051,17 @@ int label_scan(struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
/*
|
||||
* dev_cache_scan() creates a list of devices on the system
|
||||
* (saved in in dev-cache) which we can iterate through to
|
||||
* search for LVM devs. The dev cache list either comes from
|
||||
* looking at dev nodes under /dev, or from udev.
|
||||
* Creates a list of available devices, does not open or read any,
|
||||
* and does not filter them. The list of all available devices
|
||||
* is kept in "dev-cache", and comes from /dev entries or libudev.
|
||||
* The list of devs found here needs to be filtered to get the
|
||||
* list of devs we can use. The dev_iter calls using cmd->filter
|
||||
* are what filters the devs.
|
||||
*/
|
||||
dev_cache_scan();
|
||||
if (!setup_devices(cmd)) {
|
||||
log_error("Failed to set up devices.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we know that there will be md components with an end
|
||||
@@ -1080,7 +1098,7 @@ int label_scan(struct cmd_context *cmd)
|
||||
* so this will usually do nothing.
|
||||
*/
|
||||
label_scan_invalidate(dev);
|
||||
};
|
||||
}
|
||||
dev_iter_destroy(iter);
|
||||
|
||||
/*
|
||||
@@ -1120,21 +1138,54 @@ int label_scan(struct cmd_context *cmd)
|
||||
* by using hints which tell us which devices are PVs, which
|
||||
* are the only devices we actually need to scan. Without
|
||||
* hints we need to scan all devs to find which are PVs.
|
||||
*
|
||||
* TODO: if the command is using hints and a single vgname
|
||||
*/
|
||||
if (!get_hints(cmd, &hints_list, &create_hints, &all_devs, &scan_devs, &vgname_hint)) {
|
||||
dm_list_splice(&scan_devs, &all_devs);
|
||||
dm_list_init(&hints_list);
|
||||
using_hints = 0;
|
||||
} else
|
||||
using_hints = 1;
|
||||
|
||||
/*
|
||||
* If the command is using hints and a single vgname
|
||||
* arg, we can also take the vg lock here, prior to scanning.
|
||||
* This means we would not need to rescan the PVs in the VG
|
||||
* in vg_read (skip lvmcache_label_rescan_vg) after the
|
||||
* vg lock is usually taken. (Some commands are already
|
||||
* able to avoid rescan in vg_read, but locking early would
|
||||
* apply to more cases.)
|
||||
*
|
||||
* TODO: we don't know exactly which vg lock mode (read or write)
|
||||
* the command will use in vg_read() for the normal lock_vol(),
|
||||
* but we could make a fairly accurate guess of READ/WRITE based
|
||||
* on looking at the command name. If we guess wrong we can
|
||||
* just unlock_vg and lock_vol again with the correct mode in
|
||||
* vg_read().
|
||||
*/
|
||||
if (!get_hints(cmd, &hints_list, &create_hints, &all_devs, &scan_devs)) {
|
||||
dm_list_splice(&scan_devs, &all_devs);
|
||||
dm_list_init(&hints_list);
|
||||
using_hints = 0;
|
||||
} else
|
||||
using_hints = 1;
|
||||
if (vgname_hint) {
|
||||
uint32_t lck_type = LCK_VG_WRITE;
|
||||
|
||||
log_debug("Early lock vg");
|
||||
|
||||
/* FIXME: borrowing this lockd flag which should be
|
||||
quite close to what we want, based on the command name.
|
||||
Need to do proper mode selection here, and then check
|
||||
in case the later lock_vol in vg_read wants different. */
|
||||
if (cmd->lockd_vg_default_sh)
|
||||
lck_type = LCK_VG_READ;
|
||||
|
||||
if (!lock_vol(cmd, vgname_hint, lck_type, NULL)) {
|
||||
log_warn("Could not pre-lock VG %s.", vgname_hint);
|
||||
/* not an error since this is just an optimization */
|
||||
} else {
|
||||
/* Save some state indicating that the vg lock
|
||||
is already held so that the normal lock_vol()
|
||||
will know. */
|
||||
cmd->early_lock_vg_mode = lck_type;
|
||||
}
|
||||
|
||||
free(vgname_hint);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the total number of devices exceeds the soft open file
|
||||
@@ -1170,7 +1221,7 @@ int label_scan(struct cmd_context *cmd)
|
||||
* If the largest metadata is within 1MB of the bcache size, then start
|
||||
* warning.
|
||||
*/
|
||||
max_metadata_size_bytes = lvmcache_max_metadata_size();
|
||||
max_metadata_size_bytes = lvmcache_max_metadata_size_bytes();
|
||||
|
||||
if (max_metadata_size_bytes + (1024 * 1024) > _current_bcache_size_bytes) {
|
||||
/* we want bcache to be 1MB larger than the max metadata seen */
|
||||
@@ -1185,6 +1236,14 @@ int label_scan(struct cmd_context *cmd)
|
||||
(unsigned long long)want_size_kb);
|
||||
}
|
||||
|
||||
/*
|
||||
* If vg metadata is using a large percentage of a metadata area, then
|
||||
* create /run/lvm/scan_lock_global to tell future lvm commands to
|
||||
* begin doing lock_global() prior to scanning to avoid problems due to
|
||||
* metadata wrapping between label_scan and vg_read.
|
||||
*/
|
||||
set_scan_lock_global(cmd);
|
||||
|
||||
dm_list_init(&cmd->hints);
|
||||
|
||||
/*
|
||||
@@ -1196,9 +1255,14 @@ int label_scan(struct cmd_context *cmd)
|
||||
if (!validate_hints(cmd, &hints_list)) {
|
||||
log_debug("Will scan %d remaining devices", dm_list_size(&all_devs));
|
||||
_scan_list(cmd, cmd->filter, &all_devs, 0, NULL);
|
||||
/* scan_devs are the devs that have been scanned */
|
||||
dm_list_splice(&scan_devs, &all_devs);
|
||||
free_hints(&hints_list);
|
||||
using_hints = 0;
|
||||
create_hints = 0;
|
||||
/* invalid hints means a new dev probably appeared and
|
||||
we should search for any missing pvids again. */
|
||||
unlink_searched_devnames(cmd);
|
||||
} else {
|
||||
/* The hints may be used by another device iteration. */
|
||||
dm_list_splice(&cmd->hints, &hints_list);
|
||||
@@ -1206,32 +1270,10 @@ int label_scan(struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
/*
|
||||
* Stronger exclusion of md components that might have been
|
||||
* misidentified as PVs due to having an end-of-device md superblock.
|
||||
* If we're not using hints, and are not already doing a full md check
|
||||
* on devs being scanned, then if udev info is missing for a PV, scan
|
||||
* the end of the PV to verify it's not an md component. The full
|
||||
* dev_is_md_component call will do new reads at the end of the dev.
|
||||
* Check if the devices_file content is up to date and
|
||||
* if not update it.
|
||||
*/
|
||||
if (cmd->md_component_detection && !cmd->use_full_md_check && !using_hints &&
|
||||
!strcmp(cmd->md_component_checks, "auto")) {
|
||||
int once = 0;
|
||||
dm_list_iterate_items(devl, &scan_devs) {
|
||||
if (!(devl->dev->flags & DEV_SCAN_FOUND_LABEL))
|
||||
continue;
|
||||
if (!(devl->dev->flags & DEV_UDEV_INFO_MISSING))
|
||||
continue;
|
||||
if (!once++)
|
||||
log_debug_devs("Scanning end of PVs with no udev info for MD components");
|
||||
|
||||
if (dev_is_md_component(devl->dev, NULL, 1)) {
|
||||
log_debug_devs("Scan dropping PV from MD component %s", dev_name(devl->dev));
|
||||
devl->dev->flags &= ~DEV_SCAN_FOUND_LABEL;
|
||||
lvmcache_del_dev(devl->dev);
|
||||
lvmcache_del_dev_from_duplicates(devl->dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
device_ids_validate(cmd, &scan_devs, &device_ids_invalid, 0);
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &all_devs) {
|
||||
dm_list_del(&devl->list);
|
||||
@@ -1243,6 +1285,23 @@ int label_scan(struct cmd_context *cmd)
|
||||
free(devl);
|
||||
}
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &filtered_devs) {
|
||||
dm_list_del(&devl->list);
|
||||
free(devl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for md components that might have been missed by filter-md
|
||||
* during the scan. With the label scanning complete we have metadata
|
||||
* available that can sometimes offer a clue that a dev is actually an
|
||||
* md component (device name hint, pv size vs dev size). In some of
|
||||
* those cases we may want to do a full md check on a dev that has been
|
||||
* scanned. This is done before hints are written so that any devs
|
||||
* dropped due to being md components will not be included in a new
|
||||
* hint file.
|
||||
*/
|
||||
lvmcache_extra_md_component_checks(cmd);
|
||||
|
||||
/*
|
||||
* If hints were not available/usable, then we scanned all devs,
|
||||
* and we now know which are PVs. Save this list of PVs we've
|
||||
@@ -1250,7 +1309,7 @@ int label_scan(struct cmd_context *cmd)
|
||||
* (create_hints variable has NEWHINTS_X value which indicates
|
||||
* the reason for creating the new hints.)
|
||||
*/
|
||||
if (create_hints)
|
||||
if (create_hints && !device_ids_invalid)
|
||||
write_hint_file(cmd, create_hints);
|
||||
|
||||
return 1;
|
||||
@@ -1260,7 +1319,7 @@ int label_scan(struct cmd_context *cmd)
|
||||
* Read the header of the disk and if it's a PV
|
||||
* save the pvid in dev->pvid.
|
||||
*/
|
||||
int label_read_pvid(struct device *dev)
|
||||
int label_read_pvid(struct device *dev, int *has_pvid)
|
||||
{
|
||||
char buf[4096] __attribute__((aligned(8)));
|
||||
struct label_header *lh;
|
||||
@@ -1279,14 +1338,17 @@ int label_read_pvid(struct device *dev)
|
||||
*/
|
||||
if (!dev_read_bytes(dev, 0, 4096, buf)) {
|
||||
label_scan_invalidate(dev);
|
||||
return 0;
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (has_pvid)
|
||||
*has_pvid = 0;
|
||||
|
||||
lh = (struct label_header *)(buf + 512);
|
||||
if (memcmp(lh->id, LABEL_ID, sizeof(lh->id))) {
|
||||
/* Not an lvm deice */
|
||||
label_scan_invalidate(dev);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1296,9 +1358,12 @@ int label_read_pvid(struct device *dev)
|
||||
if (memcmp(lh->type, LVM2_LABEL, sizeof(lh->type))) {
|
||||
/* Not an lvm deice */
|
||||
label_scan_invalidate(dev);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (has_pvid)
|
||||
*has_pvid = 1;
|
||||
|
||||
pvh = (struct pv_header *)(buf + 512 + 32);
|
||||
memcpy(dev->pvid, pvh->pv_uuid, ID_LEN);
|
||||
return 1;
|
||||
@@ -1408,12 +1473,12 @@ void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv
|
||||
struct device *dev;
|
||||
dev_t devt;
|
||||
|
||||
if (!lv_info(cmd, lv, 0, &lvinfo, 0, 0))
|
||||
return;
|
||||
|
||||
devt = MKDEV(lvinfo.major, lvinfo.minor);
|
||||
if ((dev = dev_cache_get_by_devt(cmd, devt, NULL, NULL)))
|
||||
label_scan_invalidate(dev);
|
||||
if (lv_info(cmd, lv, 0, &lvinfo, 0, 0) && lvinfo.exists) {
|
||||
/* FIXME: Still unclear what is it supposed to find */
|
||||
devt = MKDEV(lvinfo.major, lvinfo.minor);
|
||||
if ((dev = dev_cache_get_by_devt(cmd, devt, NULL, NULL)))
|
||||
label_scan_invalidate(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1430,6 +1495,7 @@ void label_scan_drop(struct cmd_context *cmd)
|
||||
return;
|
||||
|
||||
while ((dev = dev_iter_get(cmd, iter))) {
|
||||
cmd->filter->wipe(cmd, cmd->filter, dev, NULL);
|
||||
if (_in_bcache(dev))
|
||||
_scan_dev_close(dev);
|
||||
}
|
||||
@@ -1575,7 +1641,8 @@ int label_scan_reopen_rw(struct device *dev)
|
||||
if (!bcache_change_fd(dev->bcache_di, fd)) {
|
||||
log_error("Failed to change to rw fd %s di %d fd %d.",
|
||||
dev_name(dev), dev->bcache_di, fd);
|
||||
close(fd);
|
||||
if (close(fd))
|
||||
log_sys_debug("close", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1638,7 +1705,7 @@ bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data)
|
||||
_scan_dev_close(dev);
|
||||
|
||||
dev->flags |= DEV_BCACHE_WRITE;
|
||||
label_scan_open(dev);
|
||||
(void) label_scan_open(dev); /* checked later */
|
||||
}
|
||||
|
||||
if (dev->bcache_di < 0) {
|
||||
|
||||
@@ -112,13 +112,12 @@ void label_scan_invalidate(struct device *dev);
|
||||
void label_scan_invalidate_lv(struct cmd_context *cmd, struct logical_volume *lv);
|
||||
void label_scan_drop(struct cmd_context *cmd);
|
||||
void label_scan_destroy(struct cmd_context *cmd);
|
||||
void label_scan_confirm(struct device *dev);
|
||||
int label_scan_setup_bcache(void);
|
||||
int label_scan_open(struct device *dev);
|
||||
int label_scan_open_excl(struct device *dev);
|
||||
int label_scan_open_rw(struct device *dev);
|
||||
int label_scan_reopen_rw(struct device *dev);
|
||||
int label_read_pvid(struct device *dev);
|
||||
int label_read_pvid(struct device *dev, int *has_pvid);
|
||||
|
||||
int label_scan_for_pvid(struct cmd_context *cmd, char *pvid, struct device **dev_out);
|
||||
|
||||
|
||||
@@ -203,6 +203,11 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
|
||||
if (is_orphan_vg(vol))
|
||||
return 1;
|
||||
|
||||
if (!is_global && cmd->early_lock_vg_mode && (lck_type != LCK_UNLOCK)) {
|
||||
log_debug("VG was locked early.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_blocking_supported)
|
||||
flags |= LCK_NONBLOCK;
|
||||
|
||||
@@ -354,10 +359,8 @@ static int _lockf_global(struct cmd_context *cmd, const char *mode, int convert,
|
||||
if (!strcmp(mode, "ex")) {
|
||||
flags |= LCK_WRITE;
|
||||
|
||||
if (cmd->lockf_global_ex) {
|
||||
log_warn("global flock already held ex");
|
||||
if (cmd->lockf_global_ex)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = lock_vol(cmd, VG_GLOBAL, flags, NULL);
|
||||
if (ret)
|
||||
|
||||
@@ -56,8 +56,11 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
|
||||
|
||||
#define unlock_vg(cmd, vg, vol) \
|
||||
do { \
|
||||
if (is_real_vg(vol) && !sync_local_dev_names(cmd)) \
|
||||
stack; \
|
||||
if (is_real_vg(vol)) { \
|
||||
if (!sync_local_dev_names(cmd)) \
|
||||
stack; \
|
||||
vg_backup_if_needed(vg); \
|
||||
} \
|
||||
if (!lock_vol(cmd, vol, LCK_VG_UNLOCK, NULL)) \
|
||||
stack; \
|
||||
} while (0)
|
||||
|
||||
@@ -25,6 +25,11 @@ static int _use_lvmlockd = 0; /* is 1 if command is configured to use lv
|
||||
static int _lvmlockd_connected = 0; /* is 1 if command is connected to lvmlockd */
|
||||
static int _lvmlockd_init_failed = 0; /* used to suppress further warnings */
|
||||
|
||||
struct lvmlockd_pvs {
|
||||
char **path;
|
||||
int num;
|
||||
};
|
||||
|
||||
void lvmlockd_set_socket(const char *sock)
|
||||
{
|
||||
_lvmlockd_socket = sock;
|
||||
@@ -178,18 +183,34 @@ static int _lockd_result(daemon_reply reply, int *result, uint32_t *lockd_flags)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static daemon_reply _lockd_send(const char *req_name, ...)
|
||||
static daemon_reply _lockd_send_with_pvs(const char *req_name,
|
||||
const struct lvmlockd_pvs *lock_pvs, ...)
|
||||
{
|
||||
va_list ap;
|
||||
daemon_reply repl;
|
||||
daemon_request req;
|
||||
int i;
|
||||
char key[32];
|
||||
const char *val;
|
||||
va_list ap;
|
||||
|
||||
req = daemon_request_make(req_name);
|
||||
|
||||
va_start(ap, req_name);
|
||||
va_start(ap, lock_pvs);
|
||||
daemon_request_extend_v(req, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Pass PV list */
|
||||
if (lock_pvs && lock_pvs->num) {
|
||||
daemon_request_extend(req, "path_num = " FMTd64,
|
||||
(int64_t)(lock_pvs)->num, NULL);
|
||||
|
||||
for (i = 0; i < lock_pvs->num; i++) {
|
||||
snprintf(key, sizeof(key), "path[%d] = %%s", i);
|
||||
val = lock_pvs->path[i] ? lock_pvs->path[i] : "none";
|
||||
daemon_request_extend(req, key, val, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
repl = daemon_send(_lvmlockd, req);
|
||||
|
||||
daemon_request_destroy(req);
|
||||
@@ -197,6 +218,166 @@ static daemon_reply _lockd_send(const char *req_name, ...)
|
||||
return repl;
|
||||
}
|
||||
|
||||
#define _lockd_send(req_name, args...) \
|
||||
_lockd_send_with_pvs(req_name, NULL, ##args)
|
||||
|
||||
static int _lockd_retrive_vg_pv_num(struct volume_group *vg)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
int num = 0;
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs)
|
||||
num++;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static void _lockd_retrive_vg_pv_list(struct volume_group *vg,
|
||||
struct lvmlockd_pvs *lock_pvs)
|
||||
{
|
||||
struct pv_list *pvl;
|
||||
int pv_num, i;
|
||||
|
||||
memset(lock_pvs, 0x0, sizeof(*lock_pvs));
|
||||
|
||||
pv_num = _lockd_retrive_vg_pv_num(vg);
|
||||
if (!pv_num) {
|
||||
log_error("Fail to any PVs for VG %s", vg->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate buffer for PV list */
|
||||
lock_pvs->path = zalloc(sizeof(*lock_pvs->path) * pv_num);
|
||||
if (!lock_pvs->path) {
|
||||
log_error("Fail to allocate PV list for VG %s", vg->name);
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv));
|
||||
if (!lock_pvs->path[i]) {
|
||||
log_error("Fail to allocate PV path for VG %s", vg->name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
log_debug("VG %s find PV device %s", vg->name, lock_pvs->path[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
lock_pvs->num = pv_num;
|
||||
return;
|
||||
|
||||
fail:
|
||||
for (i = 0; i < pv_num; i++) {
|
||||
if (!lock_pvs->path[i])
|
||||
continue;
|
||||
free(lock_pvs->path[i]);
|
||||
}
|
||||
free(lock_pvs->path);
|
||||
return;
|
||||
}
|
||||
|
||||
static int _lockd_retrive_lv_pv_num(struct volume_group *vg,
|
||||
const char *lv_name)
|
||||
{
|
||||
struct logical_volume *lv = find_lv(vg, lv_name);
|
||||
struct pv_list *pvl;
|
||||
int num;
|
||||
|
||||
if (!lv)
|
||||
return 0;
|
||||
|
||||
num = 0;
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (lv_is_on_pv(lv, pvl->pv))
|
||||
num++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static void _lockd_retrive_lv_pv_list(struct volume_group *vg,
|
||||
const char *lv_name,
|
||||
struct lvmlockd_pvs *lock_pvs)
|
||||
{
|
||||
struct logical_volume *lv = find_lv(vg, lv_name);
|
||||
struct pv_list *pvl;
|
||||
int pv_num, i = 0;
|
||||
|
||||
memset(lock_pvs, 0x0, sizeof(*lock_pvs));
|
||||
|
||||
/* Cannot find any existed LV? */
|
||||
if (!lv)
|
||||
return;
|
||||
|
||||
pv_num = _lockd_retrive_lv_pv_num(vg, lv_name);
|
||||
if (!pv_num) {
|
||||
/*
|
||||
* Fixup for 'lvcreate --type error -L1 -n $lv1 $vg', in this
|
||||
* case, the drive path list is empty since it doesn't establish
|
||||
* the structure 'pvseg->lvseg->lv->name'.
|
||||
*
|
||||
* So create drive path list with all drives in the VG.
|
||||
*/
|
||||
log_error("Fail to find any PVs for %s/%s, try to find PVs from VG instead",
|
||||
vg->name, lv_name);
|
||||
_lockd_retrive_vg_pv_list(vg, lock_pvs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate buffer for PV list */
|
||||
lock_pvs->path = malloc(sizeof(*lock_pvs->path) * pv_num);
|
||||
if (!lock_pvs->path) {
|
||||
log_error("Fail to allocate PV list for %s/%s", vg->name, lv_name);
|
||||
return;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (lv_is_on_pv(lv, pvl->pv)) {
|
||||
lock_pvs->path[i] = strdup(pv_dev_name(pvl->pv));
|
||||
if (!lock_pvs->path[i]) {
|
||||
log_error("Fail to allocate PV path for LV %s/%s",
|
||||
vg->name, lv_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
log_debug("Find PV device %s for LV %s/%s",
|
||||
lock_pvs->path[i], vg->name, lv_name);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
lock_pvs->num = pv_num;
|
||||
return;
|
||||
|
||||
fail:
|
||||
for (i = 0; i < pv_num; i++) {
|
||||
if (!lock_pvs->path[i])
|
||||
continue;
|
||||
free(lock_pvs->path[i]);
|
||||
lock_pvs->path[i] = NULL;
|
||||
}
|
||||
free(lock_pvs->path);
|
||||
lock_pvs->path = NULL;
|
||||
lock_pvs->num = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static void _lockd_free_pv_list(struct lvmlockd_pvs *lock_pvs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < lock_pvs->num; i++) {
|
||||
free(lock_pvs->path[i]);
|
||||
lock_pvs->path[i] = NULL;
|
||||
}
|
||||
|
||||
free(lock_pvs->path);
|
||||
lock_pvs->path = NULL;
|
||||
lock_pvs->num = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* result/lockd_flags are values returned from lvmlockd.
|
||||
*
|
||||
@@ -227,6 +408,7 @@ static int _lockd_request(struct cmd_context *cmd,
|
||||
const char *lv_lock_args,
|
||||
const char *mode,
|
||||
const char *opts,
|
||||
const struct lvmlockd_pvs *lock_pvs,
|
||||
int *result,
|
||||
uint32_t *lockd_flags)
|
||||
{
|
||||
@@ -251,7 +433,8 @@ static int _lockd_request(struct cmd_context *cmd,
|
||||
cmd_name = "none";
|
||||
|
||||
if (vg_name && lv_name) {
|
||||
reply = _lockd_send(req_name,
|
||||
reply = _lockd_send_with_pvs(req_name,
|
||||
lock_pvs,
|
||||
"cmd = %s", cmd_name,
|
||||
"pid = " FMTd64, (int64_t) pid,
|
||||
"mode = %s", mode,
|
||||
@@ -271,7 +454,8 @@ static int _lockd_request(struct cmd_context *cmd,
|
||||
req_name, mode, vg_name, lv_name, *result, *lockd_flags);
|
||||
|
||||
} else if (vg_name) {
|
||||
reply = _lockd_send(req_name,
|
||||
reply = _lockd_send_with_pvs(req_name,
|
||||
lock_pvs,
|
||||
"cmd = %s", cmd_name,
|
||||
"pid = " FMTd64, (int64_t) pid,
|
||||
"mode = %s", mode,
|
||||
@@ -288,7 +472,8 @@ static int _lockd_request(struct cmd_context *cmd,
|
||||
req_name, mode, vg_name, *result, *lockd_flags);
|
||||
|
||||
} else {
|
||||
reply = _lockd_send(req_name,
|
||||
reply = _lockd_send_with_pvs(req_name,
|
||||
lock_pvs,
|
||||
"cmd = %s", cmd_name,
|
||||
"pid = " FMTd64, (int64_t) pid,
|
||||
"mode = %s", mode,
|
||||
@@ -382,6 +567,7 @@ static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
|
||||
{
|
||||
struct device *dev;
|
||||
char path[PATH_MAX];
|
||||
char *name;
|
||||
uint64_t old_size_bytes;
|
||||
uint64_t new_size_bytes;
|
||||
uint32_t extend_bytes;
|
||||
@@ -423,8 +609,10 @@ static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
|
||||
|
||||
new_size_bytes = lv->size * SECTOR_SIZE;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/mapper/%s-%s", lv->vg->cmd->dev_dir,
|
||||
lv->vg->name, lv->name) < 0) {
|
||||
if (!(name = dm_build_dm_name(lv->vg->cmd->mem, lv->vg->name, lv->name, NULL)))
|
||||
return_0;
|
||||
|
||||
if (dm_snprintf(path, sizeof(path), "%s/%s", dm_dir(), name) < 0) {
|
||||
log_error("Extend sanlock LV %s name too long - extended size not zeroed.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
@@ -550,7 +738,8 @@ static int _deactivate_sanlock_lv(struct cmd_context *cmd, struct volume_group *
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _init_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
static int _init_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
const char *lock_type)
|
||||
{
|
||||
daemon_reply reply;
|
||||
const char *reply_str;
|
||||
@@ -566,7 +755,7 @@ static int _init_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
reply = _lockd_send("init_vg",
|
||||
"pid = " FMTd64, (int64_t) getpid(),
|
||||
"vg_name = %s", vg->name,
|
||||
"vg_lock_type = %s", "dlm",
|
||||
"vg_lock_type = %s", lock_type,
|
||||
NULL);
|
||||
|
||||
if (!_lockd_result(reply, &result, NULL)) {
|
||||
@@ -586,10 +775,12 @@ static int _init_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
log_error("VG %s init failed: invalid parameters for dlm", vg->name);
|
||||
break;
|
||||
case -EMANAGER:
|
||||
log_error("VG %s init failed: lock manager dlm is not running", vg->name);
|
||||
log_error("VG %s init failed: lock manager %s is not running",
|
||||
vg->name, lock_type);
|
||||
break;
|
||||
case -EPROTONOSUPPORT:
|
||||
log_error("VG %s init failed: lock manager dlm is not supported by lvmlockd", vg->name);
|
||||
log_error("VG %s init failed: lock manager %s is not supported by lvmlockd",
|
||||
vg->name, lock_type);
|
||||
break;
|
||||
case -EEXIST:
|
||||
log_error("VG %s init failed: a lockspace with the same name exists", vg->name);
|
||||
@@ -613,7 +804,7 @@ static int _init_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
goto out;
|
||||
}
|
||||
|
||||
vg->lock_type = "dlm";
|
||||
vg->lock_type = lock_type;
|
||||
vg->lock_args = vg_lock_args;
|
||||
|
||||
if (!vg_write(vg) || !vg_commit(vg)) {
|
||||
@@ -628,6 +819,16 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _init_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
return _init_vg(cmd, vg, "dlm");
|
||||
}
|
||||
|
||||
static int _init_vg_idm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
return _init_vg(cmd, vg, "idm");
|
||||
}
|
||||
|
||||
static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, int lv_lock_count)
|
||||
{
|
||||
daemon_reply reply;
|
||||
@@ -791,7 +992,7 @@ out:
|
||||
|
||||
/* called after vg_remove on disk */
|
||||
|
||||
static int _free_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
static int _free_vg(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
daemon_reply reply;
|
||||
uint32_t lockd_flags = 0;
|
||||
@@ -817,16 +1018,27 @@ static int _free_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
log_error("_free_vg_dlm lvmlockd result %d", result);
|
||||
log_error("%s: lock type %s lvmlockd result %d",
|
||||
__func__, vg->lock_type, result);
|
||||
|
||||
daemon_reply_destroy(reply);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _free_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
return _free_vg(cmd, vg);
|
||||
}
|
||||
|
||||
static int _free_vg_idm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
return _free_vg(cmd, vg);
|
||||
}
|
||||
|
||||
/* called before vg_remove on disk */
|
||||
|
||||
static int _busy_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
static int _busy_vg(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
daemon_reply reply;
|
||||
uint32_t lockd_flags = 0;
|
||||
@@ -861,13 +1073,24 @@ static int _busy_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
log_error("_busy_vg_dlm lvmlockd result %d", result);
|
||||
log_error("%s: lock type %s lvmlockd result %d", __func__,
|
||||
vg->lock_type, result);
|
||||
|
||||
out:
|
||||
daemon_reply_destroy(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _busy_vg_dlm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
return _busy_vg(cmd, vg);
|
||||
}
|
||||
|
||||
static int _busy_vg_idm(struct cmd_context *cmd, struct volume_group *vg)
|
||||
{
|
||||
return _busy_vg(cmd, vg);
|
||||
}
|
||||
|
||||
/* called before vg_remove on disk */
|
||||
|
||||
static int _free_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg)
|
||||
@@ -973,6 +1196,8 @@ int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return _init_vg_dlm(cmd, vg);
|
||||
case LOCK_TYPE_SANLOCK:
|
||||
return _init_vg_sanlock(cmd, vg, lv_lock_count);
|
||||
case LOCK_TYPE_IDM:
|
||||
return _init_vg_idm(cmd, vg);
|
||||
default:
|
||||
log_error("Unknown lock_type.");
|
||||
return 0;
|
||||
@@ -1014,7 +1239,8 @@ int lockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg,
|
||||
* When removing (not changing), each LV is locked
|
||||
* when it is removed, they do not need checking here.
|
||||
*/
|
||||
if (lock_type_num == LOCK_TYPE_DLM || lock_type_num == LOCK_TYPE_SANLOCK) {
|
||||
if (lock_type_num == LOCK_TYPE_DLM || lock_type_num == LOCK_TYPE_SANLOCK ||
|
||||
lock_type_num == LOCK_TYPE_IDM) {
|
||||
if (changing && !_lockd_all_lvs(cmd, vg)) {
|
||||
log_error("Cannot change VG %s with active LVs", vg->name);
|
||||
return 0;
|
||||
@@ -1038,6 +1264,9 @@ int lockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg,
|
||||
case LOCK_TYPE_SANLOCK:
|
||||
/* returning an error will prevent vg_remove() */
|
||||
return _free_vg_sanlock(cmd, vg);
|
||||
case LOCK_TYPE_IDM:
|
||||
/* returning an error will prevent vg_remove() */
|
||||
return _busy_vg_idm(cmd, vg);
|
||||
default:
|
||||
log_error("Unknown lock_type.");
|
||||
return 0;
|
||||
@@ -1056,6 +1285,9 @@ void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg)
|
||||
case LOCK_TYPE_DLM:
|
||||
_free_vg_dlm(cmd, vg);
|
||||
break;
|
||||
case LOCK_TYPE_IDM:
|
||||
_free_vg_idm(cmd, vg);
|
||||
break;
|
||||
default:
|
||||
log_error("Unknown lock_type.");
|
||||
}
|
||||
@@ -1087,6 +1319,7 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_i
|
||||
int host_id = 0;
|
||||
int result;
|
||||
int ret;
|
||||
struct lvmlockd_pvs lock_pvs;
|
||||
|
||||
memset(uuid, 0, sizeof(uuid));
|
||||
|
||||
@@ -1122,7 +1355,15 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_i
|
||||
host_id = find_config_tree_int(cmd, local_host_id_CFG, NULL);
|
||||
}
|
||||
|
||||
reply = _lockd_send("start_vg",
|
||||
/*
|
||||
* Create the VG's PV list when start the VG, the PV list
|
||||
* is passed to lvmlockd, and the the PVs path will be used
|
||||
* to send SCSI commands for idm locking scheme.
|
||||
*/
|
||||
if (!strcmp(vg->lock_type, "idm")) {
|
||||
_lockd_retrive_vg_pv_list(vg, &lock_pvs);
|
||||
reply = _lockd_send_with_pvs("start_vg",
|
||||
&lock_pvs,
|
||||
"pid = " FMTd64, (int64_t) getpid(),
|
||||
"vg_name = %s", vg->name,
|
||||
"vg_lock_type = %s", vg->lock_type,
|
||||
@@ -1132,6 +1373,20 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int start_i
|
||||
"host_id = " FMTd64, (int64_t) host_id,
|
||||
"opts = %s", start_init ? "start_init" : "none",
|
||||
NULL);
|
||||
_lockd_free_pv_list(&lock_pvs);
|
||||
} else {
|
||||
reply = _lockd_send_with_pvs("start_vg",
|
||||
NULL,
|
||||
"pid = " FMTd64, (int64_t) getpid(),
|
||||
"vg_name = %s", vg->name,
|
||||
"vg_lock_type = %s", vg->lock_type,
|
||||
"vg_lock_args = %s", vg->lock_args ?: "none",
|
||||
"vg_uuid = %s", uuid[0] ? uuid : "none",
|
||||
"version = " FMTd64, (int64_t) vg->seqno,
|
||||
"host_id = " FMTd64, (int64_t) host_id,
|
||||
"opts = %s", start_init ? "start_init" : "none",
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (!_lockd_result(reply, &result, &lockd_flags)) {
|
||||
ret = 0;
|
||||
@@ -1286,7 +1541,7 @@ int lockd_start_wait(struct cmd_context *cmd)
|
||||
* can provide in the lock-gl call.
|
||||
*
|
||||
* lockd_gl() and lockd_gl_create() differ in the specific cases where
|
||||
* ENOLS (no lockspace found) is overriden. In the vgcreate case, the
|
||||
* ENOLS (no lockspace found) is overridden. In the vgcreate case, the
|
||||
* override cases are related to sanlock bootstrap, and the lock_type of
|
||||
* the vg being created is needed.
|
||||
*
|
||||
@@ -1359,7 +1614,7 @@ int lockd_global_create(struct cmd_context *cmd, const char *def_mode, const cha
|
||||
req:
|
||||
if (!_lockd_request(cmd, "lock_gl",
|
||||
NULL, vg_lock_type, NULL, NULL, NULL, NULL, mode, NULL,
|
||||
&result, &lockd_flags)) {
|
||||
NULL, &result, &lockd_flags)) {
|
||||
/* No result from lvmlockd, it is probably not running. */
|
||||
log_error("Global lock failed: check that lvmlockd is running.");
|
||||
return 0;
|
||||
@@ -1595,7 +1850,7 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode)
|
||||
|
||||
if (!_lockd_request(cmd, "lock_gl",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, mode, opts,
|
||||
&result, &lockd_flags)) {
|
||||
NULL, &result, &lockd_flags)) {
|
||||
/* No result from lvmlockd, it is probably not running. */
|
||||
|
||||
/* We don't care if an unlock fails. */
|
||||
@@ -1863,7 +2118,7 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
|
||||
|
||||
if (!_lockd_request(cmd, "lock_vg",
|
||||
vg_name, NULL, NULL, NULL, NULL, NULL, mode, NULL,
|
||||
&result, &lockd_flags)) {
|
||||
NULL, &result, &lockd_flags)) {
|
||||
/*
|
||||
* No result from lvmlockd, it is probably not running.
|
||||
* Decide if it is ok to continue without a lock in
|
||||
@@ -2123,6 +2378,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
|
||||
uint32_t lockd_flags;
|
||||
int refreshed = 0;
|
||||
int result;
|
||||
struct lvmlockd_pvs lock_pvs;
|
||||
|
||||
/*
|
||||
* Verify that when --readonly is used, no LVs should be activated or used.
|
||||
@@ -2188,13 +2444,28 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
|
||||
retry:
|
||||
log_debug("lockd LV %s/%s mode %s uuid %s", vg->name, lv_name, mode, lv_uuid);
|
||||
|
||||
if (!_lockd_request(cmd, "lock_lv",
|
||||
vg->name, vg->lock_type, vg->lock_args,
|
||||
lv_name, lv_uuid, lock_args, mode, opts,
|
||||
&result, &lockd_flags)) {
|
||||
/* No result from lvmlockd, it is probably not running. */
|
||||
log_error("Locking failed for LV %s/%s", vg->name, lv_name);
|
||||
return 0;
|
||||
/* Pass PV list for IDM lock type */
|
||||
if (!strcmp(vg->lock_type, "idm")) {
|
||||
_lockd_retrive_lv_pv_list(vg, lv_name, &lock_pvs);
|
||||
if (!_lockd_request(cmd, "lock_lv",
|
||||
vg->name, vg->lock_type, vg->lock_args,
|
||||
lv_name, lv_uuid, lock_args, mode, opts,
|
||||
&lock_pvs, &result, &lockd_flags)) {
|
||||
_lockd_free_pv_list(&lock_pvs);
|
||||
/* No result from lvmlockd, it is probably not running. */
|
||||
log_error("Locking failed for LV %s/%s", vg->name, lv_name);
|
||||
return 0;
|
||||
}
|
||||
_lockd_free_pv_list(&lock_pvs);
|
||||
} else {
|
||||
if (!_lockd_request(cmd, "lock_lv",
|
||||
vg->name, vg->lock_type, vg->lock_args,
|
||||
lv_name, lv_uuid, lock_args, mode, opts,
|
||||
NULL, &result, &lockd_flags)) {
|
||||
/* No result from lvmlockd, it is probably not running. */
|
||||
log_error("Locking failed for LV %s/%s", vg->name, lv_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* The lv was not active/locked. */
|
||||
@@ -2676,6 +2947,7 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
|
||||
return 1;
|
||||
case LOCK_TYPE_SANLOCK:
|
||||
case LOCK_TYPE_DLM:
|
||||
case LOCK_TYPE_IDM:
|
||||
break;
|
||||
default:
|
||||
log_error("lockd_init_lv: unknown lock_type.");
|
||||
@@ -2818,6 +3090,8 @@ int lockd_init_lv(struct cmd_context *cmd, struct volume_group *vg, struct logic
|
||||
lv->lock_args = "pending";
|
||||
else if (!strcmp(vg->lock_type, "dlm"))
|
||||
lv->lock_args = "dlm";
|
||||
else if (!strcmp(vg->lock_type, "idm"))
|
||||
lv->lock_args = "idm";
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2833,6 +3107,7 @@ int lockd_free_lv(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return 1;
|
||||
case LOCK_TYPE_DLM:
|
||||
case LOCK_TYPE_SANLOCK:
|
||||
case LOCK_TYPE_IDM:
|
||||
if (!lock_args)
|
||||
return 1;
|
||||
return _free_lv(cmd, vg, lv_name, lv_id, lock_args);
|
||||
@@ -3004,6 +3279,10 @@ const char *lockd_running_lock_type(struct cmd_context *cmd, int *found_multiple
|
||||
log_debug("lvmlockd found dlm");
|
||||
lock_type = "dlm";
|
||||
break;
|
||||
case LOCK_TYPE_IDM:
|
||||
log_debug("lvmlockd found idm");
|
||||
lock_type = "idm";
|
||||
break;
|
||||
default:
|
||||
log_error("Failed to find a running lock manager.");
|
||||
break;
|
||||
|
||||
@@ -472,7 +472,7 @@ static void _set_time_prefix(char *prefix, int buflen)
|
||||
if (!len)
|
||||
goto fail;
|
||||
|
||||
len = dm_snprintf(prefix + len, buflen - len, ".%ld ", ts.tv_nsec/1000);
|
||||
len = dm_snprintf(prefix + len, buflen - len, ".%06ld ", ts.tv_nsec/1000);
|
||||
if (len < 0)
|
||||
goto fail;
|
||||
|
||||
@@ -576,7 +576,7 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
|
||||
|
||||
if (log_once) {
|
||||
if (!_duplicated)
|
||||
_duplicated = dm_hash_create(128);
|
||||
_duplicated = dm_hash_create(117);
|
||||
if (_duplicated) {
|
||||
if (dm_hash_lookup(_duplicated, message))
|
||||
level = _LOG_NOTICE;
|
||||
|
||||
@@ -247,6 +247,13 @@ static int _process_poll_init(const struct cmd_context *cmd, const char *poll_ty
|
||||
goto out_req;
|
||||
}
|
||||
|
||||
if (parms->devicesfile[0] &&
|
||||
!(daemon_request_extend(req, LVMPD_PARM_DEVICESFILE " = %s",
|
||||
parms->devicesfile, NULL))) {
|
||||
log_error("Failed to create %s request." , poll_type);
|
||||
goto out_req;
|
||||
}
|
||||
|
||||
rep = daemon_send(_lvmpolld, req);
|
||||
|
||||
if (rep.error) {
|
||||
|
||||
@@ -60,6 +60,7 @@ struct daemon_parms {
|
||||
const char *progress_title;
|
||||
uint64_t lv_type;
|
||||
struct poll_functions *poll_fns;
|
||||
char devicesfile[128];
|
||||
};
|
||||
|
||||
int poll_daemon(struct cmd_context *cmd, unsigned background,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user