mirror of
git://sourceware.org/git/lvm2.git
synced 2025-04-07 14:50:46 +03:00
Compare commits
304 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
11b64b0c0c | ||
|
6838881956 | ||
|
5d16beee57 | ||
|
26e86f9da9 | ||
|
b8b0fcfa10 | ||
|
6679438437 | ||
|
1bf3961bbe | ||
|
dcf37af2ca | ||
|
ebbdaccd9c | ||
|
fafc0f76c5 | ||
|
491c6652ae | ||
|
ea73594f07 | ||
|
9ed7528d1f | ||
|
7becd29494 | ||
|
3687f7fee3 | ||
|
74c178f7bf | ||
|
82789f6134 | ||
|
30fdd6b9b4 | ||
|
63088e1f82 | ||
|
579054452b | ||
|
253ef42362 | ||
|
54831ecabd | ||
|
a4951801fa | ||
|
d0c9bcf6d7 | ||
|
43a755d568 | ||
|
12419e3b67 | ||
|
0d17105292 | ||
|
1d94dd075d | ||
|
872e085030 | ||
|
959f775985 | ||
|
0c970d8ec7 | ||
|
8d41afbc1f | ||
|
b4ebf69739 | ||
|
8c696e463f | ||
|
91c29c318f | ||
|
d556d77363 | ||
|
649d17d221 | ||
|
b4a9897bd8 | ||
|
523d796b15 | ||
|
d9832565ec | ||
|
6565ce22b7 | ||
|
53ccbdab1b | ||
|
c065b407cb | ||
|
22b628924f | ||
|
06baec439e | ||
|
92493361f3 | ||
|
5efa388206 | ||
|
fe1cf7174f | ||
|
6e5e7b3193 | ||
|
a6264f6a44 | ||
|
b2f8e744de | ||
|
01e4764c40 | ||
|
c9ee8d8a06 | ||
|
154befd4b8 | ||
|
951fd6358b | ||
|
8efbffe086 | ||
|
cff93e4d5c | ||
|
227d3ca507 | ||
|
cc843151b4 | ||
|
7dd2f101c7 | ||
|
381b45b5a9 | ||
|
8273a6e2e1 | ||
|
c59a8e2d56 | ||
|
a1e449dea2 | ||
|
3a6e221c56 | ||
|
d80d346f4e | ||
|
54ade3a6bb | ||
|
1dcd9fbe08 | ||
|
a853649565 | ||
|
a512bf3c62 | ||
|
9197880050 | ||
|
16bc80c389 | ||
|
4fa6c76181 | ||
|
b4c9f29eb3 | ||
|
8d855ff23a | ||
|
ba9c4368f4 | ||
|
1f728f370f | ||
|
80ee9e45cb | ||
|
297808c269 | ||
|
dfb4ed13f6 | ||
|
be25429ea7 | ||
|
36bdffb6a4 | ||
|
6f9e247285 | ||
|
be0b2ea01a | ||
|
d5ac344465 | ||
|
4789abbcd2 | ||
|
a29d0c014a | ||
|
7d0acdbcb0 | ||
|
5430eec2b9 | ||
|
d83f40d25a | ||
|
c40bd459df | ||
|
d016158ff9 | ||
|
874a8ab4d0 | ||
|
0fe1613c9b | ||
|
56398a2180 | ||
|
bb458e9528 | ||
|
2fae69cc4b | ||
|
0d4418fe6c | ||
|
bb66753a14 | ||
|
c1bc0c9726 | ||
|
685e704373 | ||
|
4be1c7b6ca | ||
|
36be0778f8 | ||
|
6ad474385b | ||
|
b02e6cd4a9 | ||
|
bb0bbc6d74 | ||
|
8417a6a578 | ||
|
79c022133b | ||
|
e3f0af8f1f | ||
|
5359737c29 | ||
|
b13b55884a | ||
|
da19ef49b1 | ||
|
03b78fa666 | ||
|
a87cc133e2 | ||
|
07f23d4b81 | ||
|
8bdc234348 | ||
|
05f1e78f3e | ||
|
9f425a62fc | ||
|
1e91c16112 | ||
|
12efeb6d51 | ||
|
5fd50ae192 | ||
|
5a6d318b29 | ||
|
924221765e | ||
|
a6b2ce6299 | ||
|
464c30e6c3 | ||
|
5e127fb8e9 | ||
|
f66c76e5ea | ||
|
3a700dd2f2 | ||
|
bacd9f394d | ||
|
cb0c43898a | ||
|
ff1f1188c3 | ||
|
9cc6b15dd9 | ||
|
e737c54d8a | ||
|
1d13b391f8 | ||
|
15b3cf1104 | ||
|
4ff8c706db | ||
|
0c3c08b95f | ||
|
063984afde | ||
|
623e98e16c | ||
|
f0a707f6b4 | ||
|
bea43e4faa | ||
|
c326796a89 | ||
|
fd341c818d | ||
|
00a3664a5c | ||
|
625a38c855 | ||
|
04cacff3b9 | ||
|
852f3c20bb | ||
|
8a67936e7e | ||
|
13fcb7e428 | ||
|
736db4247c | ||
|
0bb06eb99b | ||
|
5b92ce741f | ||
|
c0b725d6e6 | ||
|
75a39003b0 | ||
|
e9640e5178 | ||
|
e410715154 | ||
|
d6934ea31d | ||
|
a1017024f1 | ||
|
e7ae3fbd10 | ||
|
8425c1b468 | ||
|
7f12b5d0dc | ||
|
550ce921fa | ||
|
d913d776d1 | ||
|
a9fcc3ab0c | ||
|
a187f02ed5 | ||
|
74a2325261 | ||
|
be1b83a76f | ||
|
87a4e7bb68 | ||
|
7858c25427 | ||
|
425ae9aaf0 | ||
|
2a34723511 | ||
|
ed9468153e | ||
|
09e508cd43 | ||
|
a6408163dd | ||
|
c68af364e7 | ||
|
d5cc65f683 | ||
|
082d475ea9 | ||
|
29bb84f17b | ||
|
48d7511808 | ||
|
ffeee23537 | ||
|
46a48f1320 | ||
|
2c63b12bd3 | ||
|
36ae51c3cb | ||
|
1e21b0a6f2 | ||
|
12f1472972 | ||
|
1719f1169f | ||
|
d32ee0b7ab | ||
|
42a43c37de | ||
|
583e5f952e | ||
|
fd91edfd15 | ||
|
51030c57a1 | ||
|
1e21a93ead | ||
|
cae445443e | ||
|
f582c7be1d | ||
|
09d896810b | ||
|
07b595d0f3 | ||
|
9fe73c8d95 | ||
|
27f0ca79cc | ||
|
5f71cebcbe | ||
|
e907c3cf9a | ||
|
b32c0bb9c5 | ||
|
dd09127608 | ||
|
76b1776367 | ||
|
ebb90fd2c6 | ||
|
7d7b5db230 | ||
|
c2cf9a4cae | ||
|
84aa248f07 | ||
|
6c2debf917 | ||
|
6de7c51dce | ||
|
9f81fccd65 | ||
|
ffbf3a8ca2 | ||
|
8247752ce1 | ||
|
8cbd417e7a | ||
|
a4bf6667f8 | ||
|
b47612cd8b | ||
|
9ad2980996 | ||
|
ecf2cbec7f | ||
|
e95bc8f8c9 | ||
|
970463fc46 | ||
|
d582ee591e | ||
|
14673b2746 | ||
|
8fb58826c0 | ||
|
d7ffd98257 | ||
|
86574ce07a | ||
|
f392dab286 | ||
|
9414dcae3a | ||
|
0d3b87d19f | ||
|
4ef211a187 | ||
|
1576273273 | ||
|
e86a75b4fe | ||
|
036e88eb85 | ||
|
5f53ecda36 | ||
|
5ef958704c | ||
|
e1117164a4 | ||
|
8a9bc6eed8 | ||
|
3e641578d8 | ||
|
6326d00937 | ||
|
928b8e9c6e | ||
|
cb87e184bc | ||
|
d952358636 | ||
|
736d23ad26 | ||
|
32ab91e528 | ||
|
85014fcd6d | ||
|
32cfcfd151 | ||
|
3c365e6c5c | ||
|
4a18f89736 | ||
|
2b82e882ed | ||
|
d8726b07c3 | ||
|
ee97c5c633 | ||
|
f08d1caf47 | ||
|
acd7cfbc08 | ||
|
6c5e8ee18b | ||
|
017c668fd0 | ||
|
ccde015712 | ||
|
9beea2db69 | ||
|
275c9666b6 | ||
|
d791f160a8 | ||
|
75907f0e80 | ||
|
45344262cc | ||
|
c695c7a252 | ||
|
94da2c9792 | ||
|
ce8e6c8c63 | ||
|
60cd279f96 | ||
|
25638f6a87 | ||
|
47c4f737c9 | ||
|
a6e918cd48 | ||
|
c77f2697ee | ||
|
9259892627 | ||
|
2c06950888 | ||
|
5893ca17da | ||
|
e8e4324d68 | ||
|
502543ffed | ||
|
03a3863804 | ||
|
ebadd3ccc6 | ||
|
c4d4bddfce | ||
|
efe5af819a | ||
|
ca5d258376 | ||
|
4c31e6d56a | ||
|
51a684ef0f | ||
|
dfc132a514 | ||
|
473e93fbff | ||
|
270f9306bc | ||
|
7b9bdcb4d4 | ||
|
c2f41c1a59 | ||
|
cbfc31ee2b | ||
|
dcac774f09 | ||
|
e4b5f8a485 | ||
|
c3ed3f28a2 | ||
|
158d3243b6 | ||
|
44a04b71f8 | ||
|
a2ca20dad9 | ||
|
1d8a4c4817 | ||
|
b5249fa3c2 | ||
|
a210e9d768 | ||
|
0fc7266353 | ||
|
2a1a7a863d | ||
|
f7df63748a | ||
|
987256aaa8 | ||
|
d53c71a4f2 | ||
|
dfa74465e9 | ||
|
cf6cbfb7f7 | ||
|
352b1b1817 | ||
|
03782806eb | ||
|
e42ceccc6d |
@ -172,7 +172,7 @@ help:
|
||||
@echo " lcov-dated Generate lcov with timedate suffix."
|
||||
@echo " lcov-reset Reset lcov counters"
|
||||
@echo " man Build man pages."
|
||||
@echo " print-VARIABLE Resolve make variable."
|
||||
@echo " print-VARIABLE Resolve make variable."
|
||||
@echo " rpm Build rpm."
|
||||
@echo " run-unit-test Run unit tests."
|
||||
@echo " tags Generate c/etags."
|
||||
@ -194,7 +194,8 @@ ifneq ("$(GENHTML)", "")
|
||||
lcov:
|
||||
$(RM) -rf $(LCOV_REPORTS_DIR)
|
||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||
$(LCOV) --capture --directory $(top_builddir) --ignore-errors source \
|
||||
-find . -name '*.gc[dn][ao]' ! -newer make.tmpl -delete
|
||||
-$(LCOV) --capture --directory $(top_builddir) --ignore-errors source,negative,gcov \
|
||||
--output-file $(LCOV_REPORTS_DIR)/out.info
|
||||
-test ! -s $(LCOV_REPORTS_DIR)/out.info || \
|
||||
$(GENHTML) -o $(LCOV_REPORTS_DIR) --ignore-errors source \
|
||||
|
@ -1 +1 @@
|
||||
1.02.202 (2024-11-04)
|
||||
1.02.206-git (2025-02-27)
|
||||
|
47
WHATS_NEW
47
WHATS_NEW
@ -1,3 +1,50 @@
|
||||
Version 2.03.32 -
|
||||
==================
|
||||
Lvconvert vdopool conversion propperly validates acceptable LVs.
|
||||
Accept thin pool data LV as cachable LV.
|
||||
Allow using zram block devices (likely for testing).
|
||||
Fix lvresize when resizing COW snapshots already covering origin.
|
||||
Fix lvmdbusd read of executed lvm commands output.
|
||||
Fix construction of DM UUID for cachevol _cdata and _cmeta devices.
|
||||
|
||||
Version 2.03.31 - 27th February 2025
|
||||
====================================
|
||||
Reduce 'mandoc -T lint' reported issues for man pages.
|
||||
Restore support for LVM_SUPPRESS_FD_WARNINGS (2.03.24).
|
||||
Fix uncache and split cache restoring original state of volume.
|
||||
Extend use of lockopt skip to more scenarios.
|
||||
Enhance error path resolving in polling code.
|
||||
Disallow shared activation of LV with CoW snapshot.
|
||||
Fix lvmlockd use in lvremove of CoW snapshot, VDO pool, and uncache.
|
||||
Improve mirror split with opened temporary volumes.
|
||||
Improve pvmove finish with opened temporary volumes.
|
||||
Fix backup limit for devices file, handle over 10,000 files.
|
||||
Ignore reported optimal_io_size not divisible by 4096.
|
||||
Fix busy-loop in config reading when read returned 0.
|
||||
Fix DM cache preserving logic (2.03.28).
|
||||
Improve use of lvmlockd for usecases involving thin volumes and pools.
|
||||
|
||||
Version 2.03.30 - 14th January 2025
|
||||
===================================
|
||||
Lvresize reports origin vdo volume cannot be resized.
|
||||
Support setting reserved_memory|stack of --config cmdline.
|
||||
Fix support for disabling memory locking (2.03.27).
|
||||
Do not extend an LV if FS resize unsupported and '--fs resize' used.
|
||||
Prevent leftover temporary device when converting in use volume to a pool.
|
||||
lvconvert detects early volume in use when converting it to a pool.
|
||||
Handle NVMe with quirk changed WWID not matching WWID in devices file.
|
||||
|
||||
Version 2.03.29 - 09th December 2024
|
||||
====================================
|
||||
Configure --enable/disable-sd-notify to control lvmlockd build with sd-notify.
|
||||
Allow test mode when lvmlockd is built without dlm support.
|
||||
Add a note about RAID + integrity synchronization to lvmraid(7) man page.
|
||||
Add a function for running lvconvert --repair on RAID LVs to lvmdbusd.
|
||||
Improve option section of man pages for listing commands ({pv,lv,vg}{s,display}).
|
||||
Fix renaming of raid sub LVs when converting a volume to raid (2.03.28).
|
||||
Fix segfault/VG write error for raid LV lvextend -i|--stripes -I|--stripesize.
|
||||
Revert ignore -i|--stripes, -I|--stripesize for lvextend on raid0 LV (2.03.27).
|
||||
|
||||
Version 2.03.28 - 04th November 2024
|
||||
====================================
|
||||
Use radix_tree to lookup for UUID within committed metadata.
|
||||
|
19
WHATS_NEW_DM
19
WHATS_NEW_DM
@ -1,3 +1,20 @@
|
||||
Version 1.02.206 -
|
||||
===================
|
||||
Add support for using regex in selection criteria for string lists.
|
||||
Fix string list selection when using [<item> || <item> ...].
|
||||
|
||||
Version 1.02.205 - 27th February 2025
|
||||
=====================================
|
||||
Restore missing symbol dm_tree_node_size_changed@Base (1.02.175).
|
||||
Restore missing symbol dm_bitset_parse_list@@DM_1_02_138 (1.02.175).
|
||||
|
||||
Version 1.02.204 - 14th January 2025
|
||||
====================================
|
||||
Create /dev/disk/by-diskseq/<DISKSEQ> symlink for public DM devices.
|
||||
|
||||
Version 1.02.203 - 09th December 2024
|
||||
=====================================
|
||||
|
||||
Version 1.02.202 - 04th November 2024
|
||||
=====================================
|
||||
Introduce dm_config_parse_only_section to stop parsing after section.
|
||||
@ -263,7 +280,7 @@ Version 1.02.136 - 5th November 2016
|
||||
Still produce output when dmsetup dependency tree building finds dev missing.
|
||||
Check and report pthread_sigmask() failure in dmeventd.
|
||||
Check mem alloc fail in _canonicalize_field_ids().
|
||||
Use unsigned math when checking more then 31 legs of raid.
|
||||
Use unsigned math when checking more than 31 legs of raid.
|
||||
Fix 'dmstats delete' with dmsetup older than v1.02.129
|
||||
Fix stats walk segfault with dmsetup older than v1.02.129
|
||||
|
||||
|
48
aclocal.m4
vendored
48
aclocal.m4
vendored
@ -1,6 +1,6 @@
|
||||
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.17 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@ -422,7 +422,7 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
|
||||
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
|
||||
])dnl PKG_HAVE_DEFINE_WITH_MODULES
|
||||
|
||||
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1999-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@ -456,9 +456,12 @@ AC_DEFUN([AM_PATH_PYTHON],
|
||||
dnl Find a Python interpreter. Python versions prior to 2.0 are not
|
||||
dnl supported. (2.0 was released on October 16, 2000).
|
||||
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
|
||||
[python python2 python3 dnl
|
||||
[python python3 dnl
|
||||
python3.20 python3.19 python3.18 python3.17 python3.16 dnl
|
||||
python3.15 python3.14 python3.13 python3.12 python3.11 python3.10 dnl
|
||||
python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl
|
||||
python3.2 python3.1 python3.0 dnl
|
||||
python2 dnl
|
||||
python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl
|
||||
python2.0])
|
||||
|
||||
@ -653,15 +656,29 @@ try:
|
||||
if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
|
||||
can_use_sysconfig = 0
|
||||
except ImportError:
|
||||
pass"
|
||||
pass" # end of am_python_setup_sysconfig
|
||||
|
||||
# More repeated code, for figuring out the installation scheme to use.
|
||||
am_python_setup_scheme="if hasattr(sysconfig, 'get_default_scheme'):
|
||||
scheme = sysconfig.get_default_scheme()
|
||||
else:
|
||||
scheme = sysconfig._get_default_scheme()
|
||||
if scheme == 'posix_local':
|
||||
if '$am_py_prefix' == '/usr':
|
||||
scheme = 'deb_system' # should only happen during Debian package builds
|
||||
else:
|
||||
# Debian's default scheme installs to /usr/local/ but we want to
|
||||
# follow the prefix, as we always have.
|
||||
# See bugs#54412, #64837, et al.
|
||||
scheme = 'posix_prefix'" # end of am_python_setup_scheme
|
||||
|
||||
dnl emacs-page Set up 4 directories:
|
||||
|
||||
dnl 1. pythondir: where to install python scripts. This is the
|
||||
dnl site-packages directory, not the python standard library
|
||||
dnl directory like in previous automake betas. This behavior
|
||||
dnl directory as in early automake betas. This behavior
|
||||
dnl is more consistent with lispdir.m4 for example.
|
||||
dnl Query distutils for this directory.
|
||||
dnl Query sysconfig or distutils (per above) for this directory.
|
||||
dnl
|
||||
AC_CACHE_CHECK([for $am_display_PYTHON script directory (pythondir)],
|
||||
[am_cv_python_pythondir],
|
||||
@ -673,7 +690,11 @@ except ImportError:
|
||||
am_cv_python_pythondir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
|
||||
try:
|
||||
$am_python_setup_scheme
|
||||
sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'})
|
||||
except:
|
||||
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
|
||||
else:
|
||||
from distutils import sysconfig
|
||||
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
|
||||
@ -703,7 +724,8 @@ sys.stdout.write(sitedir)"`
|
||||
|
||||
dnl 3. pyexecdir: directory for installing python extension modules
|
||||
dnl (shared libraries).
|
||||
dnl Query distutils for this directory.
|
||||
dnl Query sysconfig or distutils for this directory.
|
||||
dnl Much of this is the same as for prefix setup above.
|
||||
dnl
|
||||
AC_CACHE_CHECK([for $am_display_PYTHON extension module directory (pyexecdir)],
|
||||
[am_cv_python_pyexecdir],
|
||||
@ -715,7 +737,11 @@ sys.stdout.write(sitedir)"`
|
||||
am_cv_python_pyexecdir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
|
||||
try:
|
||||
$am_python_setup_scheme
|
||||
sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'})
|
||||
except:
|
||||
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
|
||||
else:
|
||||
from distutils import sysconfig
|
||||
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix')
|
||||
@ -766,7 +792,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
|
||||
sys.exit(sys.hexversion < minverhex)"
|
||||
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
|
||||
|
||||
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -279,7 +279,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const u
|
||||
pc->len = i;
|
||||
|
||||
if (!_insert(rt, &pc->child, kb + i, ke, rv)) {
|
||||
free(pc2);
|
||||
free(pc->child.value.ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -293,6 +293,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const u
|
||||
if (pc->len == 1) {
|
||||
n4->values[0] = pc->child;
|
||||
free(pc);
|
||||
v->value.ptr = NULL;
|
||||
} else {
|
||||
memmove(pc->prefix, pc->prefix + 1, pc->len - 1);
|
||||
pc->len--;
|
||||
|
@ -193,12 +193,12 @@ bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, size_t prefix_len)
|
||||
{
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
const uint8_t *kb = prefix;
|
||||
const uint8_t *ke = kb + prefix_len;
|
||||
struct node **pn;
|
||||
unsigned count;
|
||||
unsigned count = 0;
|
||||
|
||||
pn = _lookup(&rt->root, kb, ke);
|
||||
|
||||
@ -280,7 +280,7 @@ static void _dump(FILE *out, struct node *n, unsigned indent)
|
||||
fprintf(out, " ");
|
||||
|
||||
if (n->has_value) {
|
||||
fprintf(out, "value: %llu\n", n->value.n);
|
||||
fprintf(out, "value: %lu\n", (unsigned long) n->value.n);
|
||||
} else {
|
||||
fprintf(out, "key: '%c' [0x%02x] %u\n",
|
||||
isprint(n->key) ? n->key : ' ', n->key, indent);
|
||||
|
@ -586,7 +586,7 @@ allocation {
|
||||
|
||||
# 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.
|
||||
# This is slightly less than 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
|
||||
|
298
configure
vendored
298
configure
vendored
@ -678,6 +678,7 @@ SILENT_RULES
|
||||
SHARED_LINK
|
||||
SELINUX_STATIC_LIBS
|
||||
SELINUX_PC
|
||||
SD_NOTIFY_SUPPORT
|
||||
SBINDIR
|
||||
RT_LIBS
|
||||
PYTHON3DIR
|
||||
@ -787,6 +788,8 @@ LIBSYSTEMD_LIBS
|
||||
LIBSYSTEMD_CFLAGS
|
||||
UDEV_LIBS
|
||||
UDEV_CFLAGS
|
||||
LIBNVME_LIBS
|
||||
LIBNVME_CFLAGS
|
||||
BLKID_LIBS
|
||||
BLKID_CFLAGS
|
||||
SYSTEMD_RUN_CMD
|
||||
@ -912,6 +915,7 @@ enable_silent_rules
|
||||
enable_static_link
|
||||
enable_shared
|
||||
with_blkid
|
||||
with_libnvme
|
||||
with_systemd
|
||||
with_udev
|
||||
with_user
|
||||
@ -971,8 +975,10 @@ enable_use_lvmpolld
|
||||
with_lvmpolld_pidfile
|
||||
enable_systemd_journal
|
||||
enable_app_machineid
|
||||
enable_sd_notify
|
||||
with_systemd_run
|
||||
enable_blkid_wiping
|
||||
enable_nvme_wwid
|
||||
enable_udev_sync
|
||||
enable_udev_rules
|
||||
enable_udev_rule_exec_detection
|
||||
@ -1045,6 +1051,8 @@ LIBSEAGATEILM_CFLAGS
|
||||
LIBSEAGATEILM_LIBS
|
||||
BLKID_CFLAGS
|
||||
BLKID_LIBS
|
||||
LIBNVME_CFLAGS
|
||||
LIBNVME_LIBS
|
||||
UDEV_CFLAGS
|
||||
UDEV_LIBS
|
||||
LIBSYSTEMD_CFLAGS
|
||||
@ -1713,8 +1721,10 @@ Optional Features:
|
||||
--disable-systemd-journal
|
||||
disable LVM systemd journaling
|
||||
--disable-app-machineid disable LVM system ID using app-specific machine-id
|
||||
--disable-sd-notify disable LVM sd_notify
|
||||
--disable-blkid_wiping disable libblkid detection of signatures when wiping
|
||||
and use native code instead
|
||||
--disable-nvme-wwid do not use libnvme to detect alternate WWIDs
|
||||
--enable-udev_sync enable synchronization with udev processing
|
||||
--enable-udev_rules install rule files needed for udev synchronization
|
||||
--enable-udev-rule-exec-detection
|
||||
@ -1741,6 +1751,7 @@ Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
||||
--without-blkid do not build with blkid library
|
||||
--without-libnvme do not build with libnvme library
|
||||
--without-systemd do not build with systemd library
|
||||
--without-udev do not build with udev library
|
||||
--with-user=USER set the owner of installed files [USER=]
|
||||
@ -1880,6 +1891,10 @@ Some influential environment variables:
|
||||
BLKID_CFLAGS
|
||||
C compiler flags for BLKID, overriding pkg-config
|
||||
BLKID_LIBS linker flags for BLKID, overriding pkg-config
|
||||
LIBNVME_CFLAGS
|
||||
C compiler flags for LIBNVME, overriding pkg-config
|
||||
LIBNVME_LIBS
|
||||
linker flags for LIBNVME, overriding pkg-config
|
||||
UDEV_CFLAGS C compiler flags for UDEV, overriding pkg-config
|
||||
UDEV_LIBS linker flags for UDEV, overriding pkg-config
|
||||
LIBSYSTEMD_CFLAGS
|
||||
@ -9128,6 +9143,16 @@ esac
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-libnvme was given.
|
||||
if test ${with_libnvme+y}
|
||||
then :
|
||||
withval=$with_libnvme;
|
||||
else case e in #(
|
||||
e) with_libnvme="yes" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-systemd was given.
|
||||
if test ${with_systemd+y}
|
||||
then :
|
||||
@ -12724,9 +12749,18 @@ SYSTEMD_MIN_VERSION=0
|
||||
NOTIFYDBUS_SUPPORT="no"
|
||||
SYSTEMD_JOURNAL_SUPPORT="no"
|
||||
APP_MACHINEID_SUPPORT="no"
|
||||
SD_NOTIFY_SUPPORT="no"
|
||||
if test "$with_systemd" = "yes"
|
||||
then :
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 218\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "systemd >= 218") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
SYSTEMD_MIN_VERSION=218 SD_NOTIFY_SUPPORT="maybe"
|
||||
fi
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"systemd >= 221\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "systemd >= 221") 2>&5
|
||||
ac_status=$?
|
||||
@ -12814,6 +12848,41 @@ printf "%s\n" "#define APP_MACHINEID_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
if test "$SD_NOTIFY_SUPPORT" != "no"
|
||||
then :
|
||||
ac_fn_c_check_header_compile "$LINENO" "systemd/sd-daemon.h" "ac_cv_header_systemd_sd_daemon_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_systemd_sd_daemon_h" = xyes
|
||||
then :
|
||||
SD_NOTIFY_SUPPORT="yes"
|
||||
else case e in #(
|
||||
e) SD_NOTIFY_SUPPORT="no" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
fi
|
||||
# Check whether --enable-sd-notify was given.
|
||||
if test ${enable_sd_notify+y}
|
||||
then :
|
||||
enableval=$enable_sd_notify; if test "$enableval" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"
|
||||
then :
|
||||
as_fn_error $? "--enable-sd-notify requires systemd/sd-daemon.h. (--with-systemd=$with_systemd)" "$LINENO" 5
|
||||
fi
|
||||
SD_NOTIFY_SUPPORT=$enableval
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable to sd_notify" >&5
|
||||
printf %s "checking whether to enable to sd_notify... " >&6; }
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SD_NOTIFY_SUPPORT" >&5
|
||||
printf "%s\n" "$SD_NOTIFY_SUPPORT" >&6; }
|
||||
|
||||
if test "$SD_NOTIFY_SUPPORT" = "yes"
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define SD_NOTIFY_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
|
||||
# Check whether --with-systemd-run was given.
|
||||
@ -13129,6 +13198,181 @@ printf "%s\n" "$BLKID_WIPING" >&6; }
|
||||
printf "%s\n" "#define DEFAULT_USE_BLKID_WIPING $DEFAULT_USE_BLKID_WIPING" >>confdefs.h
|
||||
|
||||
|
||||
################################################################################
|
||||
# Check whether --enable-nvme-wwid was given.
|
||||
if test ${enable_nvme_wwid+y}
|
||||
then :
|
||||
enableval=$enable_nvme_wwid; NVME_WWID=$enableval
|
||||
else case e in #(
|
||||
e) if test "$with_libnvme" = "yes"
|
||||
then :
|
||||
NVME_WWID="maybe"
|
||||
else case e in #(
|
||||
e) NVME_WWID="no" ;;
|
||||
esac
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
# ATM NVME_WWID is the only user of libnvme, so skip checking for libnvme when disabled
|
||||
if test "$NVME_WWID" = "no"
|
||||
then :
|
||||
with_libnvme="no"
|
||||
fi
|
||||
|
||||
if test "$with_libnvme" = "yes"
|
||||
then :
|
||||
|
||||
|
||||
pkg_failed=no
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libnvme >= 1.4" >&5
|
||||
printf %s "checking for libnvme >= 1.4... " >&6; }
|
||||
|
||||
if test -n "$LIBNVME_CFLAGS"; then
|
||||
pkg_cv_LIBNVME_CFLAGS="$LIBNVME_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnvme >= 1.4\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libnvme >= 1.4") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LIBNVME_CFLAGS=`$PKG_CONFIG --cflags "libnvme >= 1.4" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$LIBNVME_LIBS"; then
|
||||
pkg_cv_LIBNVME_LIBS="$LIBNVME_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnvme >= 1.4\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libnvme >= 1.4") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_LIBNVME_LIBS=`$PKG_CONFIG --libs "libnvme >= 1.4" 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
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "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
|
||||
LIBNVME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnvme >= 1.4" 2>&1`
|
||||
else
|
||||
LIBNVME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnvme >= 1.4" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$LIBNVME_PKG_ERRORS" >&5
|
||||
|
||||
if test "$NVME_WWID" = "yes"
|
||||
then :
|
||||
NVME_WWID="error"
|
||||
else case e in #(
|
||||
e) NVME_WWID="no" ;;
|
||||
esac
|
||||
fi
|
||||
elif test $pkg_failed = untried; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
if test "$NVME_WWID" = "yes"
|
||||
then :
|
||||
NVME_WWID="error"
|
||||
else case e in #(
|
||||
e) NVME_WWID="no" ;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
LIBNVME_CFLAGS=$pkg_cv_LIBNVME_CFLAGS
|
||||
LIBNVME_LIBS=$pkg_cv_LIBNVME_LIBS
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for NVME_NIDT_CSI in libnvme.h" >&5
|
||||
printf %s "checking for NVME_NIDT_CSI in libnvme.h... " >&6; }
|
||||
if test ${ac_cv_have_libnvme_csi+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else case e in #(
|
||||
e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <libnvme.h>
|
||||
const int a = NVME_NIDT_CSI;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"
|
||||
then :
|
||||
ac_cv_have_libnvme_csi="yes"
|
||||
else case e in #(
|
||||
e) ac_cv_have_libnvme_csi="no" ;;
|
||||
esac
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
|
||||
esac
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_libnvme_csi" >&5
|
||||
printf "%s\n" "$ac_cv_have_libnvme_csi" >&6; }
|
||||
|
||||
if test "$NVME_WWID" != "no"
|
||||
then :
|
||||
|
||||
if test $ac_cv_have_libnvme_csi = yes
|
||||
then :
|
||||
NVME_WWID="yes"
|
||||
|
||||
printf "%s\n" "#define NVME_SUPPORT 1" >>confdefs.h
|
||||
|
||||
else case e in #(
|
||||
e) NVME_WWID="error" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
else case e in #(
|
||||
e) if test "$NVME_WWID" = "yes"
|
||||
then :
|
||||
NVME_WWID="error"
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test "$NVME_WWID" = "error"
|
||||
then :
|
||||
as_fn_error $? "--enable-nvme-wwid requires libnvme library >= 1.1. (--with-libnvme=$with_libnvme)" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use libnvme for alternate WWIDs" >&5
|
||||
printf %s "checking whether to use libnvme for alternate WWIDs... " >&6; }
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NVME_WWID" >&5
|
||||
printf "%s\n" "$NVME_WWID" >&6; }
|
||||
|
||||
################################################################################
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable synchronization with udev processing" >&5
|
||||
printf %s "checking whether to enable synchronization with udev processing... " >&6; }
|
||||
@ -13427,7 +13671,11 @@ printf "%s\n" "$BUILD_LVMDBUSD" >&6; }
|
||||
# Check whether --enable-notify-dbus was given.
|
||||
if test ${enable_notify_dbus+y}
|
||||
then :
|
||||
enableval=$enable_notify_dbus; NOTIFYDBUS_SUPPORT=$enableval
|
||||
enableval=$enable_notify_dbus; if test "enableval" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"
|
||||
then :
|
||||
as_fn_error $? "--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)" "$LINENO" 5
|
||||
fi
|
||||
NOTIFYDBUS_SUPPORT=$enableval
|
||||
fi
|
||||
|
||||
|
||||
@ -13444,13 +13692,9 @@ fi
|
||||
|
||||
if test "$NOTIFYDBUS_SUPPORT" = "yes"
|
||||
then :
|
||||
if test "$SYSTEMD_MIN_VERSION" -lt 221
|
||||
then :
|
||||
as_fn_error $? "--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)" "$LINENO" 5
|
||||
fi
|
||||
|
||||
printf "%s\n" "#define NOTIFYDBUS_SUPPORT 1" >>confdefs.h
|
||||
|
||||
]
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build notifydbus" >&5
|
||||
@ -13459,10 +13703,10 @@ printf %s "checking whether to build notifydbus... " >&6; }
|
||||
printf "%s\n" "$NOTIFYDBUS_SUPPORT" >&6; }
|
||||
|
||||
################################################################################
|
||||
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"
|
||||
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" ||
|
||||
test "$APP_MACHINEID_SUPPORT" = "yes" || test "$SD_NOTIFY_SUPPORT" = "yes"
|
||||
then :
|
||||
|
||||
|
||||
pkg_failed=no
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5
|
||||
printf %s "checking for libsystemd... " >&6; }
|
||||
@ -13553,7 +13797,6 @@ else
|
||||
printf "%s\n" "yes" >&6; }
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@ -13880,7 +14123,21 @@ try:
|
||||
if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
|
||||
can_use_sysconfig = 0
|
||||
except ImportError:
|
||||
pass"
|
||||
pass" # end of am_python_setup_sysconfig
|
||||
|
||||
# More repeated code, for figuring out the installation scheme to use.
|
||||
am_python_setup_scheme="if hasattr(sysconfig, 'get_default_scheme'):
|
||||
scheme = sysconfig.get_default_scheme()
|
||||
else:
|
||||
scheme = sysconfig._get_default_scheme()
|
||||
if scheme == 'posix_local':
|
||||
if '$am_py_prefix' == '/usr':
|
||||
scheme = 'deb_system' # should only happen during Debian package builds
|
||||
else:
|
||||
# Debian's default scheme installs to /usr/local/ but we want to
|
||||
# follow the prefix, as we always have.
|
||||
# See bugs#54412, #64837, et al.
|
||||
scheme = 'posix_prefix'" # end of am_python_setup_scheme
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory (pythondir)" >&5
|
||||
@ -13897,7 +14154,11 @@ else case e in #(
|
||||
am_cv_python_pythondir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
|
||||
try:
|
||||
$am_python_setup_scheme
|
||||
sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'})
|
||||
except:
|
||||
sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
|
||||
else:
|
||||
from distutils import sysconfig
|
||||
sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
|
||||
@ -13927,7 +14188,7 @@ printf "%s\n" "$am_cv_python_pythondir" >&6; }
|
||||
pkgpythondir=\${pythondir}/$PACKAGE
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory (pyexecdir)" >&5
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory (pyexecdir)" >&5
|
||||
printf %s "checking for $am_display_PYTHON extension module directory (pyexecdir)... " >&6; }
|
||||
if test ${am_cv_python_pyexecdir+y}
|
||||
then :
|
||||
@ -13941,7 +14202,11 @@ else case e in #(
|
||||
am_cv_python_pyexecdir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
|
||||
try:
|
||||
$am_python_setup_scheme
|
||||
sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'})
|
||||
except:
|
||||
sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'})
|
||||
else:
|
||||
from distutils import sysconfig
|
||||
sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix')
|
||||
@ -16564,6 +16829,7 @@ AIO_LIBS=${AIO_LIBS:--laio}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
@ -17961,3 +18227,9 @@ then :
|
||||
printf "%s\n" "$as_me: WARNING: Building D-Bus support without D-Bus notifications!" >&2;}
|
||||
fi
|
||||
|
||||
if test "$BUILD_LVMLOCKD" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"
|
||||
then :
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Building lvmlockd without sd-notify support may block!" >&5
|
||||
printf "%s\n" "$as_me: WARNING: Building lvmlockd without sd-notify support may block!" >&2;}
|
||||
fi
|
||||
|
||||
|
71
configure.ac
71
configure.ac
@ -217,6 +217,8 @@ test "$exec_prefix" = "NONE" && exec_prefix='${prefix}'
|
||||
|
||||
AC_ARG_WITH(blkid, [AS_HELP_STRING([--without-blkid], [do not build with blkid library])],
|
||||
[], with_blkid="yes")
|
||||
AC_ARG_WITH(libnvme, [AS_HELP_STRING([--without-libnvme], [do not build with libnvme library])],
|
||||
[], with_libnvme="yes")
|
||||
AC_ARG_WITH(systemd, [AS_HELP_STRING([--without-systemd], [do not build with systemd library])],
|
||||
[], with_systemd="yes")
|
||||
AC_ARG_WITH(udev, [AS_HELP_STRING([--without-udev], [do not build with udev library])],
|
||||
@ -1046,7 +1048,9 @@ SYSTEMD_MIN_VERSION=0
|
||||
NOTIFYDBUS_SUPPORT="no"
|
||||
SYSTEMD_JOURNAL_SUPPORT="no"
|
||||
APP_MACHINEID_SUPPORT="no"
|
||||
SD_NOTIFY_SUPPORT="no"
|
||||
AS_IF([test "$with_systemd" = "yes"],
|
||||
PKG_CHECK_EXISTS(systemd >= 218, [SYSTEMD_MIN_VERSION=218 SD_NOTIFY_SUPPORT="maybe"])
|
||||
PKG_CHECK_EXISTS(systemd >= 221, [SYSTEMD_MIN_VERSION=221 NOTIFYDBUS_SUPPORT="maybe" SYSTEMD_JOURNAL_SUPPORT="maybe"])
|
||||
PKG_CHECK_EXISTS(systemd >= 234, [SYSTEMD_MIN_VERSION=234 APP_MACHINEID_SUPPORT="maybe"]))
|
||||
|
||||
@ -1082,6 +1086,22 @@ AC_MSG_RESULT([$APP_MACHINEID_SUPPORT])
|
||||
AS_IF([test "$APP_MACHINEID_SUPPORT" = "yes"],
|
||||
AC_DEFINE([APP_MACHINEID_SUPPORT], 1, [Define to 1 to include code that uses libsystemd machine-id apis.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Build with sd_notify when the header file sd-daemon.h is present
|
||||
AS_IF([test "$SD_NOTIFY_SUPPORT" != "no"],
|
||||
AC_CHECK_HEADER([systemd/sd-daemon.h], [SD_NOTIFY_SUPPORT="yes"], [SD_NOTIFY_SUPPORT="no"]))
|
||||
AC_ARG_ENABLE(sd-notify,
|
||||
AS_HELP_STRING([--disable-sd-notify],
|
||||
[disable LVM sd_notify]),
|
||||
AS_IF([test "$enableval" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"],
|
||||
AC_MSG_ERROR([--enable-sd-notify requires systemd/sd-daemon.h. (--with-systemd=$with_systemd)]))
|
||||
SD_NOTIFY_SUPPORT=$enableval, [])
|
||||
AC_MSG_CHECKING([whether to enable to sd_notify])
|
||||
AC_MSG_RESULT([$SD_NOTIFY_SUPPORT])
|
||||
|
||||
AS_IF([test "$SD_NOTIFY_SUPPORT" = "yes"],
|
||||
AC_DEFINE([SD_NOTIFY_SUPPORT], 1, [Define to 1 to include code that uses sd_notify.]))
|
||||
|
||||
################################################################################
|
||||
dnl -- Support override for systemd-run path if they need to (NixOS builds)
|
||||
AC_ARG_WITH(systemd-run,
|
||||
@ -1139,6 +1159,38 @@ AC_MSG_RESULT([$BLKID_WIPING])
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_USE_BLKID_WIPING, [$DEFAULT_USE_BLKID_WIPING],
|
||||
[Use blkid wiping by default.])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable nvme alternate WWID via libnvme
|
||||
AC_ARG_ENABLE(nvme-wwid,
|
||||
AS_HELP_STRING([--disable-nvme-wwid],
|
||||
[do not use libnvme to detect alternate WWIDs]),
|
||||
NVME_WWID=$enableval,
|
||||
[AS_IF([test "$with_libnvme" = "yes"], [NVME_WWID="maybe"], [NVME_WWID="no"])])
|
||||
|
||||
# ATM NVME_WWID is the only user of libnvme, so skip checking for libnvme when disabled
|
||||
AS_IF([test "$NVME_WWID" = "no"], [with_libnvme="no"])
|
||||
|
||||
AS_IF([test "$with_libnvme" = "yes"], [
|
||||
PKG_CHECK_MODULES([LIBNVME], [libnvme >= 1.4], [
|
||||
AC_CACHE_CHECK([for NVME_NIDT_CSI in libnvme.h],
|
||||
[ac_cv_have_libnvme_csi],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <libnvme.h>
|
||||
const int a = NVME_NIDT_CSI;
|
||||
])], [ac_cv_have_libnvme_csi="yes"], [ac_cv_have_libnvme_csi="no"])])
|
||||
|
||||
AS_IF([test "$NVME_WWID" != "no"], [
|
||||
AC_IF_YES(ac_cv_have_libnvme_csi, [NVME_WWID="yes"
|
||||
AC_DEFINE(NVME_SUPPORT, 1, [Use libnvme for WWID.])],
|
||||
[NVME_WWID="error"])])
|
||||
], [AS_IF([test "$NVME_WWID" = "yes"], [NVME_WWID="error"], [NVME_WWID="no"])])
|
||||
], [AS_IF([test "$NVME_WWID" = "yes"], [NVME_WWID="error"])])
|
||||
|
||||
AS_IF([test "$NVME_WWID" = "error"],
|
||||
[AC_MSG_ERROR([--enable-nvme-wwid requires libnvme library >= 1.1. (--with-libnvme=$with_libnvme)])])
|
||||
|
||||
AC_MSG_CHECKING([whether to use libnvme for alternate WWIDs])
|
||||
AC_MSG_RESULT([$NVME_WWID])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable udev synchronization
|
||||
AC_MSG_CHECKING([whether to enable synchronization with udev processing])
|
||||
@ -1231,14 +1283,15 @@ AC_MSG_RESULT([$BUILD_LVMDBUSD])
|
||||
dnl -- Build notifydbus
|
||||
AC_ARG_ENABLE(notify-dbus,
|
||||
[AS_HELP_STRING([--enable-notify-dbus], [enable LVM notification using dbus])],
|
||||
[NOTIFYDBUS_SUPPORT=$enableval])
|
||||
[AS_IF([test "enableval" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
|
||||
[AC_MSG_ERROR([--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)])])
|
||||
NOTIFYDBUS_SUPPORT=$enableval])
|
||||
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "maybe"],
|
||||
[AS_IF([test "$BUILD_LVMDBUSD" = "yes"], [NOTIFYDBUS_SUPPORT="yes"], [NOTIFYDBUS_SUPPORT="no"])])
|
||||
[AS_IF([test "$BUILD_LVMDBUSD" = "yes"],
|
||||
[NOTIFYDBUS_SUPPORT="yes"], [NOTIFYDBUS_SUPPORT="no"])])
|
||||
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes"],
|
||||
[AS_IF([test "$SYSTEMD_MIN_VERSION" -lt 221],
|
||||
[AC_MSG_ERROR([--enable-notify-dbus requires systemd >= 221. (--with-systemd=$with_systemd)])])
|
||||
AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])])
|
||||
|
||||
AC_MSG_CHECKING([whether to build notifydbus])
|
||||
@ -1246,9 +1299,9 @@ AC_MSG_RESULT([$NOTIFYDBUS_SUPPORT])
|
||||
|
||||
################################################################################
|
||||
dnl -- Look for libsystemd libraries if needed
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"], [
|
||||
PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])
|
||||
])
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" ||
|
||||
test "$APP_MACHINEID_SUPPORT" = "yes" || test "$SD_NOTIFY_SUPPORT" = "yes"],
|
||||
[PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable Python dbus library
|
||||
@ -1938,6 +1991,7 @@ AC_SUBST(PYTHON3)
|
||||
AC_SUBST(PYTHON3DIR)
|
||||
AC_SUBST(RT_LIBS)
|
||||
AC_SUBST(SBINDIR)
|
||||
AC_SUBST(SD_NOTIFY_SUPPORT)
|
||||
AC_SUBST(SELINUX_LIBS)
|
||||
AC_SUBST(SELINUX_PC)
|
||||
AC_SUBST(SELINUX_STATIC_LIBS)
|
||||
@ -2075,3 +2129,6 @@ AS_IF([test "$ODIRECT" != "yes"],
|
||||
|
||||
AS_IF([test "$BUILD_LVMDBUSD" = "yes" && test "$NOTIFYDBUS_SUPPORT" = "no"],
|
||||
[AC_MSG_WARN([Building D-Bus support without D-Bus notifications!])])
|
||||
|
||||
AS_IF([test "$BUILD_LVMLOCKD" = "yes" && test "$SD_NOTIFY_SUPPORT" = "no"],
|
||||
[AC_MSG_WARN([Building lvmlockd without sd-notify support may block!])])
|
||||
|
@ -30,6 +30,8 @@
|
||||
|
||||
struct lv_segment;
|
||||
struct logical_volume;
|
||||
struct cmd_context;
|
||||
struct profile;
|
||||
|
||||
struct lv_segment *first_seg(const struct logical_volume *lv)
|
||||
{
|
||||
@ -57,7 +59,7 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
||||
*/
|
||||
|
||||
/* simple_memccpy() from glibc */
|
||||
void *memccpy(void *dest, const void *src, int c, size_t n)
|
||||
void *memccpy(void *dest, const void *src, int c, unsigned long n)
|
||||
{
|
||||
const char *s = src;
|
||||
char *d = dest;
|
||||
@ -90,9 +92,14 @@ void model_FD_ZERO(void *fdset)
|
||||
/* Resent Coverity reports quite weird errors... */
|
||||
int *__errno_location(void)
|
||||
{
|
||||
static int _i = 0;
|
||||
return &_i;
|
||||
}
|
||||
|
||||
const unsigned short **__ctype_b_loc (void)
|
||||
{
|
||||
static const unsigned short *_a[1] = { 0 };
|
||||
return _a;
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#ifndef _LVM_CLOG_COMPAT_H
|
||||
#define _LVM_CLOG_COMPAT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* The intermachine communication structure version are:
|
||||
* 0: Unused
|
||||
@ -19,6 +21,8 @@
|
||||
*/
|
||||
#define CLOG_TFR_VERSION 5
|
||||
|
||||
struct clog_request;
|
||||
|
||||
int clog_request_to_network(struct clog_request *rq);
|
||||
int clog_request_from_network(void *data, size_t data_len);
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
#ifndef _LVM_CLOG_LOCAL_H
|
||||
#define _LVM_CLOG_LOCAL_H
|
||||
|
||||
struct dm_ulog_request;
|
||||
|
||||
int init_local(void);
|
||||
void cleanup_local(void);
|
||||
|
||||
|
@ -268,7 +268,7 @@ static void _free_dso_data(struct dso_data *data)
|
||||
|
||||
static struct dso_data *_alloc_dso_data(struct message_data *data)
|
||||
{
|
||||
struct dso_data *ret = (typeof(ret)) zalloc(sizeof(*ret));
|
||||
struct dso_data *ret = (__typeof__(ret)) zalloc(sizeof(*ret));
|
||||
|
||||
if (!ret)
|
||||
return_NULL;
|
||||
|
@ -15,6 +15,8 @@
|
||||
#ifndef __DMEVENTD_DOT_H__
|
||||
#define __DMEVENTD_DOT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* FIXME This stuff must be configurable. */
|
||||
|
||||
#define DM_EVENT_FIFO_CLIENT DEFAULT_DM_RUN_DIR "/dmeventd-client"
|
||||
|
@ -29,20 +29,23 @@
|
||||
*/
|
||||
|
||||
enum dm_event_mask {
|
||||
DM_EVENT_SETTINGS_MASK = 0x0000FF,
|
||||
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
|
||||
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
|
||||
DM_EVENT_SETTINGS_MASK = 0x0000FF,
|
||||
|
||||
DM_EVENT_ERROR_MASK = 0x00FF00,
|
||||
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
|
||||
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
|
||||
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
|
||||
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
|
||||
DM_EVENT_ERROR_MASK = 0x00FF00,
|
||||
|
||||
DM_EVENT_STATUS_MASK = 0xFF0000,
|
||||
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
|
||||
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occurred */
|
||||
|
||||
DM_EVENT_ERROR_AND_TIMEOUT_MASK = 0x02FF00,
|
||||
|
||||
DM_EVENT_STATUS_MASK = 0xFF0000,
|
||||
|
||||
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
|
||||
};
|
||||
|
||||
@ -70,10 +73,10 @@ int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
|
||||
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path);
|
||||
|
||||
/*
|
||||
* Identify the device to monitor by exactly one of device_name, uuid or
|
||||
* Identify the device to monitor by exactly one of dev_name, uuid or
|
||||
* device number. String arguments are duplicated, see above.
|
||||
*/
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name);
|
||||
|
||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
#ifndef _DMEVENTD_LVMWRAP_H
|
||||
#define _DMEVENTD_LVMWRAP_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct dm_pool;
|
||||
|
||||
int dmeventd_lvm2_init(void);
|
||||
|
@ -112,7 +112,7 @@ static int _remove_failed_devices(const char *cmd_lvconvert, const char *device)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
struct dso_state *state = *user;
|
||||
|
@ -114,7 +114,7 @@ out:
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
struct dso_state *state = *user;
|
||||
|
@ -163,7 +163,7 @@ static void _umount(const char *device, int major, int minor)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
struct dso_state *state = *user;
|
||||
|
@ -155,7 +155,7 @@ static int _wait_for_pid(struct dso_state *state)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask,
|
||||
void **user)
|
||||
{
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
@ -179,7 +179,7 @@ void process_event(struct dm_task *dmt,
|
||||
return;
|
||||
}
|
||||
|
||||
if (event & DM_EVENT_DEVICE_ERROR) {
|
||||
if (evmask & DM_EVENT_DEVICE_ERROR) {
|
||||
/* Error -> no need to check and do instant resize */
|
||||
state->data_percent = state->metadata_percent = 0;
|
||||
if (_use_policy(dmt, state))
|
||||
|
@ -146,7 +146,7 @@ static int _wait_for_pid(struct dso_state *state)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
@ -169,7 +169,7 @@ void process_event(struct dm_task *dmt,
|
||||
return;
|
||||
}
|
||||
|
||||
if (event & DM_EVENT_DEVICE_ERROR) {
|
||||
if (evmask & DM_EVENT_DEVICE_ERROR) {
|
||||
#if VDO_DEBUG
|
||||
log_debug("VDO event error.");
|
||||
#endif
|
||||
|
@ -160,6 +160,8 @@ def call_lvm(command, debug=False, line_cb=None,
|
||||
|
||||
# Check to see if process has terminated, None when running
|
||||
if process.poll() is not None:
|
||||
stdout_text += read_decoded(process.stdout)
|
||||
stderr_text += read_decoded(process.stderr)
|
||||
break
|
||||
except IOError as ioe:
|
||||
log_debug("call_lvm:" + str(ioe))
|
||||
@ -552,6 +554,14 @@ def lv_vdo_deduplication(lv_path, enable, dedup_options):
|
||||
return call(cmd)
|
||||
|
||||
|
||||
def lv_raid_repair(lv_path, new_pvs, repair_options):
|
||||
cmd = ['lvconvert', '-y', '--repair']
|
||||
cmd.append(lv_path)
|
||||
cmd.extend(new_pvs)
|
||||
cmd.extend(options_to_cli_args(repair_options))
|
||||
return call(cmd)
|
||||
|
||||
|
||||
def supports_json():
|
||||
cmd = ['help']
|
||||
rc, out, err = call(cmd)
|
||||
|
@ -795,6 +795,39 @@ class Lv(LvCommon):
|
||||
cache_options), cb, cbe)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
@staticmethod
|
||||
def _repair_raid_lv(lv_uuid, lv_name, new_pvs, repair_options):
|
||||
# Make sure we have a dbus object representing it
|
||||
pv_dests = []
|
||||
dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
|
||||
|
||||
# If we have PVs, verify them
|
||||
if len(new_pvs):
|
||||
for pv in new_pvs:
|
||||
pv_dbus_obj = cfg.om.get_object_by_path(pv)
|
||||
if not pv_dbus_obj:
|
||||
raise dbus.exceptions.DBusException(
|
||||
LV_INTERFACE,
|
||||
'PV Destination (%s) not found' % pv)
|
||||
|
||||
pv_dests.append(pv_dbus_obj.lvm_id)
|
||||
|
||||
LvCommon.handle_execute(*cmdhandler.lv_raid_repair(
|
||||
dbo.lvm_id, pv_dests, repair_options))
|
||||
return "/"
|
||||
|
||||
@dbus.service.method(
|
||||
dbus_interface=LV_INTERFACE,
|
||||
in_signature='aoia{sv}',
|
||||
out_signature='o',
|
||||
async_callbacks=('cb', 'cbe'))
|
||||
def RepairRaidLv(self, new_pvs, tmo, repair_options, cb, cbe):
|
||||
r = RequestEntry(
|
||||
tmo, Lv._repair_raid_lv,
|
||||
(self.Uuid, self.lvm_id, new_pvs,
|
||||
repair_options), cb, cbe, return_tuple=False)
|
||||
cfg.worker_q.put(r)
|
||||
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@utils.dbus_property(VDO_POOL_INTERFACE, 'OperatingMode', 's')
|
||||
|
@ -50,8 +50,7 @@ INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||
|
||||
ifneq (,$(firstword $(LIBSYSTEMD_LIBS)))
|
||||
DEFS += -DUSE_SD_NOTIFY
|
||||
ifeq ("@SD_NOTIFY_SUPPORT@", "yes")
|
||||
CFLAGS += $(LIBSYSTEMD_CFLAGS)
|
||||
LIBS += $(LIBSYSTEMD_LIBS)
|
||||
endif
|
||||
|
@ -97,8 +97,9 @@ static void save_client_info(char *line)
|
||||
uint32_t client_id = 0;
|
||||
char name[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
|
||||
&pid, &fd, &pi, &client_id, name);
|
||||
(void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%"
|
||||
DM_TO_STRING(MAX_NAME) "s",
|
||||
&pid, &fd, &pi, &client_id, name);
|
||||
|
||||
clients[num_clients].client_id = client_id;
|
||||
clients[num_clients].pid = pid;
|
||||
@ -129,8 +130,11 @@ static void format_info_ls(char *line)
|
||||
char lock_args[MAX_ARGS+1] = { 0 };
|
||||
char lock_type[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s",
|
||||
ls_name, vg_name, vg_uuid, lock_args, lock_type);
|
||||
(void) sscanf(line, "info=ls ls_name=%" DM_TO_STRING(MAX_NAME) "s vg_name=%"
|
||||
DM_TO_STRING(MAX_NAME) "s vg_uuid=%" DM_TO_STRING(MAX_NAME)
|
||||
"s vg_args=%" DM_TO_STRING(MAX_NAME) "s lm_type=%"
|
||||
DM_TO_STRING(MAX_NAME) "s",
|
||||
ls_name, vg_name, vg_uuid, lock_args, lock_type);
|
||||
|
||||
if (!first_ls)
|
||||
printf("\n");
|
||||
@ -150,8 +154,11 @@ static void format_info_ls_action(char *line)
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
|
||||
(void) sscanf(line, "info=ls_action client_id=%u %s %s op=%s",
|
||||
&client_id, flags, version, op);
|
||||
(void) sscanf(line, "info=ls_action client_id=%u %"
|
||||
DM_TO_STRING(MAX_NAME) "s %"
|
||||
DM_TO_STRING(MAX_NAME) "s op=%"
|
||||
DM_TO_STRING(MAX_NAME) "s",
|
||||
&client_id, flags, version, op);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
@ -166,8 +173,10 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
|
||||
char sh_count[MAX_NAME+1] = { 0 };
|
||||
uint32_t ver = 0;
|
||||
|
||||
(void) sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
|
||||
r_name, r_type, mode, sh_count, &ver);
|
||||
(void) sscanf(line, "info=r name=%" DM_TO_STRING(MAX_NAME)
|
||||
"s type=%3s mode=%3s %"
|
||||
DM_TO_STRING(MAX_NAME) "s version=%u",
|
||||
r_name, r_type, mode, sh_count, &ver);
|
||||
|
||||
strcpy(r_name_out, r_name);
|
||||
strcpy(r_type_out, r_type);
|
||||
@ -204,8 +213,9 @@ static void format_info_lk(char *line, char *r_name, char *r_type)
|
||||
return;
|
||||
}
|
||||
|
||||
(void) sscanf(line, "info=lk mode=%s version=%u %s client_id=%u",
|
||||
mode, &ver, flags, &client_id);
|
||||
(void) sscanf(line, "info=lk mode=%3s version=%u %"
|
||||
DM_TO_STRING(MAX_NAME) "s client_id=%u",
|
||||
mode, &ver, flags, &client_id);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
@ -240,8 +250,11 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
return;
|
||||
}
|
||||
|
||||
(void) sscanf(line, "info=r_action client_id=%u %s %s op=%s rt=%s mode=%s %s %s %s",
|
||||
&client_id, flags, version, op, rt, mode, lm, result, lm_rv);
|
||||
(void) sscanf(line, "info=r_action client_id=%u %" DM_TO_STRING(MAX_NAME)
|
||||
"s %" DM_TO_STRING(MAX_NAME) "s op=%" DM_TO_STRING(MAX_NAME)
|
||||
"s rt=%3s mode=%3s %" DM_TO_STRING(MAX_NAME) "s %"
|
||||
DM_TO_STRING(MAX_NAME) "s %" DM_TO_STRING(MAX_NAME) "s",
|
||||
&client_id, flags, version, op, rt, mode, lm, result, lm_rv);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "libdaemon/client/daemon-io.h"
|
||||
#include "daemon-server.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "lvm-version.h"
|
||||
#include "daemons/lvmlockd/lvmlockd-client.h"
|
||||
#include "device_mapper/misc/dm-ioctl.h"
|
||||
@ -31,7 +31,7 @@
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#ifdef USE_SD_NOTIFY
|
||||
#ifdef SD_NOTIFY_SUPPORT
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
|
||||
@ -416,6 +416,7 @@ struct lockspace *alloc_lockspace(void)
|
||||
|
||||
INIT_LIST_HEAD(&ls->actions);
|
||||
INIT_LIST_HEAD(&ls->resources);
|
||||
INIT_LIST_HEAD(&ls->dispose);
|
||||
pthread_mutex_init(&ls->mutex, NULL);
|
||||
pthread_cond_init(&ls->cond, NULL);
|
||||
return ls;
|
||||
@ -754,7 +755,7 @@ static const char *rt_str(int x)
|
||||
case LD_RT_LV:
|
||||
return "lv";
|
||||
default:
|
||||
return ".";
|
||||
return "";
|
||||
};
|
||||
}
|
||||
|
||||
@ -999,7 +1000,7 @@ static int read_adopt_file(struct list_head *vg_lockd)
|
||||
memset(vg_uuid, 0, sizeof(vg_uuid));
|
||||
memset(mode, 0, sizeof(mode));
|
||||
|
||||
if (sscanf(adopt_line, "LV: %64s %64s %s %7s %u",
|
||||
if (sscanf(adopt_line, "LV: %64s %64s %64s %7s %u",
|
||||
vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) {
|
||||
free_resource(r);
|
||||
goto fail;
|
||||
@ -1046,7 +1047,7 @@ fail:
|
||||
|
||||
static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
|
||||
{
|
||||
int rv;
|
||||
int rv = -1;
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM)
|
||||
rv = lm_prepare_lockspace_dlm(ls);
|
||||
@ -1054,8 +1055,6 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
|
||||
rv = lm_prepare_lockspace_sanlock(ls);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_prepare_lockspace_idm(ls);
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (act)
|
||||
act->lm_rv = rv;
|
||||
@ -1064,7 +1063,7 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
|
||||
|
||||
static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_only, int adopt_ok, int nodelay)
|
||||
{
|
||||
int rv;
|
||||
int rv = -1;
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM)
|
||||
rv = lm_add_lockspace_dlm(ls, adopt_only, adopt_ok);
|
||||
@ -1072,8 +1071,6 @@ static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_
|
||||
rv = lm_add_lockspace_sanlock(ls, adopt_only, adopt_ok, nodelay);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_add_lockspace_idm(ls, adopt_only, adopt_ok);
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (act)
|
||||
act->lm_rv = rv;
|
||||
@ -1082,7 +1079,7 @@ static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_
|
||||
|
||||
static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_vg)
|
||||
{
|
||||
int rv;
|
||||
int rv = -1;
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM)
|
||||
rv = lm_rem_lockspace_dlm(ls, free_vg);
|
||||
@ -1090,18 +1087,30 @@ static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_v
|
||||
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;
|
||||
|
||||
if (act)
|
||||
act->lm_rv = rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int lm_add_resource(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
int rv = -1;
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM)
|
||||
rv = lm_add_resource_dlm(ls, r, 0);
|
||||
else if (ls->lm_type == LD_LM_SANLOCK)
|
||||
rv = lm_add_resource_sanlock(ls, r);
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_add_resource_idm(ls, r);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct action *act,
|
||||
struct val_blk *vb_out, int *retry, int adopt_only, int adopt_ok)
|
||||
{
|
||||
int rv;
|
||||
int rv = -1;
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM)
|
||||
rv = lm_lock_dlm(ls, r, mode, vb_out, adopt_only, adopt_ok);
|
||||
@ -1110,8 +1119,6 @@ static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct ac
|
||||
else if (ls->lm_type == LD_LM_IDM)
|
||||
rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid,
|
||||
&act->pvs, adopt_only, adopt_ok);
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (act)
|
||||
act->lm_rv = rv;
|
||||
@ -1121,7 +1128,7 @@ static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct ac
|
||||
static int lm_convert(struct lockspace *ls, struct resource *r,
|
||||
int mode, struct action *act, uint32_t r_version)
|
||||
{
|
||||
int rv;
|
||||
int rv = -1;
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM)
|
||||
rv = lm_convert_dlm(ls, r, mode, r_version);
|
||||
@ -1129,8 +1136,6 @@ static int lm_convert(struct lockspace *ls, struct resource *r,
|
||||
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;
|
||||
|
||||
if (act)
|
||||
act->lm_rv = rv;
|
||||
@ -1140,7 +1145,7 @@ static int lm_convert(struct lockspace *ls, struct resource *r,
|
||||
static int lm_unlock(struct lockspace *ls, struct resource *r, struct action *act,
|
||||
uint32_t r_version, uint32_t lmu_flags)
|
||||
{
|
||||
int rv;
|
||||
int rv = -1;
|
||||
|
||||
if (ls->lm_type == LD_LM_DLM)
|
||||
rv = lm_unlock_dlm(ls, r, r_version, lmu_flags);
|
||||
@ -1148,8 +1153,6 @@ static int lm_unlock(struct lockspace *ls, struct resource *r, struct action *ac
|
||||
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;
|
||||
|
||||
if (act)
|
||||
act->lm_rv = rv;
|
||||
@ -1678,20 +1681,32 @@ static int res_unlock(struct lockspace *ls, struct resource *r,
|
||||
{
|
||||
struct lock *lk;
|
||||
uint32_t r_version;
|
||||
int found_transient = 0;
|
||||
int found_persistent = 0;
|
||||
int rv;
|
||||
|
||||
if (act->flags & LD_AF_PERSISTENT) {
|
||||
lk = find_lock_persistent(r);
|
||||
if (lk)
|
||||
goto do_unlock;
|
||||
if (find_lock_client(r, act->client_id))
|
||||
found_transient = 1;
|
||||
} else {
|
||||
lk = find_lock_client(r, act->client_id);
|
||||
if (lk)
|
||||
goto do_unlock;
|
||||
if (find_lock_persistent(r))
|
||||
found_persistent = 1;
|
||||
}
|
||||
|
||||
if (act->op != LD_OP_CLOSE)
|
||||
log_debug("%s:%s res_unlock cl %u no locks", ls->name, r->name, act->client_id);
|
||||
if (act->op != LD_OP_CLOSE) {
|
||||
if (found_transient)
|
||||
log_debug("%s:%s res_unlock cl %u ENOENT (found transient)", ls->name, r->name, act->client_id);
|
||||
else if (found_persistent)
|
||||
log_debug("%s:%s res_unlock cl %u ENOENT (found persistent)", ls->name, r->name, act->client_id);
|
||||
else
|
||||
log_debug("%s:%s res_unlock cl %u ENOENT (no lock)", ls->name, r->name, act->client_id);
|
||||
}
|
||||
return -ENOENT;
|
||||
|
||||
do_unlock:
|
||||
@ -1888,6 +1903,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
|
||||
{
|
||||
struct action *act, *safe, *act_close;
|
||||
struct lock *lk;
|
||||
uint32_t unlock_by_client_id = 0;
|
||||
int lm_retry;
|
||||
int rv;
|
||||
|
||||
@ -1921,6 +1937,9 @@ static void res_process(struct lockspace *ls, struct resource *r,
|
||||
if (rv == -ENOENT && (act->flags & LD_AF_UNLOCK_CANCEL))
|
||||
rv = res_cancel(ls, r, act);
|
||||
|
||||
if (!rv && r->mode == LD_LK_UN)
|
||||
unlock_by_client_id = act->client_id;
|
||||
|
||||
/*
|
||||
* possible unlock results:
|
||||
* 0: unlock succeeded
|
||||
@ -1944,22 +1963,6 @@ static void res_process(struct lockspace *ls, struct resource *r,
|
||||
res_cancel(ls, r, act_close);
|
||||
}
|
||||
|
||||
/*
|
||||
* handle freeing a lock for an lv that has been removed
|
||||
*/
|
||||
|
||||
list_for_each_entry_safe(act, safe, &r->actions, list) {
|
||||
if (act->op == LD_OP_FREE && act->rt == LD_RT_LV) {
|
||||
log_debug("%s:%s free_lv", ls->name, r->name);
|
||||
rv = free_lv(ls, r);
|
||||
act->result = rv;
|
||||
list_del(&act->list);
|
||||
add_client_result(act);
|
||||
goto r_free;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* handle enable/disable
|
||||
*/
|
||||
@ -2103,6 +2106,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
|
||||
* be held for reading. If the T lock was sh, it would
|
||||
* be converted to P ex. If the T/P modes matched, the
|
||||
* lock could just be changed from T to P.
|
||||
* Update: T->P is known to happen sometimes with LV locks.
|
||||
*/
|
||||
|
||||
list_for_each_entry_safe(act, safe, &r->actions, list) {
|
||||
@ -2121,6 +2125,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
|
||||
list_del(&act->list);
|
||||
add_client_result(act);
|
||||
} else {
|
||||
log_debug("res_process %s change transient to persistent", r->name);
|
||||
r->last_client_id = act->client_id;
|
||||
lk->flags |= LD_LF_PERSISTENT;
|
||||
lk->client_id = 0;
|
||||
@ -2237,18 +2242,44 @@ static void res_process(struct lockspace *ls, struct resource *r,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In general, if the resource struct has no locks, no actions, and is
|
||||
* unlocked, then it can be freed. (This is only needed for LV
|
||||
* resources since LVs can be removed.) However, for lvremove (and
|
||||
* vgremove, sometimes lvconvert), the command will send a free_lv op
|
||||
* after unlocking. The free_lv op also needs the resource struct.
|
||||
* So, rather than freeing it here, move the resource struct to the
|
||||
* ls->dispose list. A free_lv op will find r on the dispose list, do
|
||||
* free_lv, then free_resource. If the command closes its connection
|
||||
* without doing free_lv (e.g. normal deactivation), then the structs
|
||||
* that the client moved to the dispose list will all be freed when
|
||||
* processing the OP_CLOSE for the client.
|
||||
*/
|
||||
if ((r->type == LD_RT_LV) && (r->mode == LD_LK_UN) &&
|
||||
list_empty(&r->locks) && list_empty(&r->actions)) {
|
||||
|
||||
/* An implicit unlock of a transient lock. */
|
||||
if (!unlock_by_client_id)
|
||||
goto r_free;
|
||||
|
||||
log_debug("%s:%s will dispose for %u", ls->name, r->name, unlock_by_client_id);
|
||||
list_del(&r->list);
|
||||
r->dispose_client_id = unlock_by_client_id;
|
||||
list_add(&r->list, &ls->dispose);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
r_free:
|
||||
/* For the EUNATCH case it may be possible there are queued actions? */
|
||||
list_for_each_entry_safe(act, safe, &r->actions, list) {
|
||||
log_error("%s:%s res_process r_free cancel %s client %d",
|
||||
log_error("%s:%s res_process r_free cancel %s client %u",
|
||||
ls->name, r->name, op_str(act->op), act->client_id);
|
||||
act->result = -ECANCELED;
|
||||
list_del(&act->list);
|
||||
add_client_result(act);
|
||||
}
|
||||
log_debug("%s:%s res_process free", ls->name, r->name);
|
||||
log_debug("%s:%s res_process free_resource", ls->name, r->name);
|
||||
lm_rem_resource(ls, r);
|
||||
list_del(&r->list);
|
||||
free_resource(r);
|
||||
@ -2283,7 +2314,7 @@ static int for_each_lock(struct lockspace *ls, int locks_do)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
|
||||
static void clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
|
||||
{
|
||||
struct resource *r, *r_safe;
|
||||
struct lock *lk, *lk_safe;
|
||||
@ -2293,6 +2324,13 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
|
||||
int lk_count = 0;
|
||||
int rv;
|
||||
|
||||
list_for_each_entry_safe(r, r_safe, &ls->dispose, list) {
|
||||
log_debug("%s:%s clear_locks dispose free_resource", ls->name, r->name);
|
||||
list_del(&r->list);
|
||||
lm_rem_resource(ls, r);
|
||||
free_resource(r);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(r, r_safe, &ls->resources, list) {
|
||||
lk_version = 0;
|
||||
|
||||
@ -2308,7 +2346,7 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
|
||||
if (lk->flags & LD_LF_PERSISTENT && !drop_vg)
|
||||
log_error("%s:%s clear lock persistent", ls->name, r->name);
|
||||
else
|
||||
log_debug("%s:%s clear lock mode %s client %d", ls->name, r->name, mode_str(lk->mode), lk->client_id);
|
||||
log_debug("%s:%s clear lock mode %s client %u", ls->name, r->name, mode_str(lk->mode), lk->client_id);
|
||||
|
||||
if (lk->version > lk_version)
|
||||
lk_version = lk->version;
|
||||
@ -2344,20 +2382,33 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(act, act_safe, &r->actions, list) {
|
||||
log_error("%s:%s clear_locks cancel %s client %d",
|
||||
log_error("%s:%s clear_locks cancel %s client %u",
|
||||
ls->name, r->name, op_str(act->op), act->client_id);
|
||||
act->result = -ECANCELED;
|
||||
list_del(&act->list);
|
||||
add_client_result(act);
|
||||
}
|
||||
r_free:
|
||||
log_debug("%s:%s free", ls->name, r->name);
|
||||
log_debug("%s:%s clear_locks free_resource", ls->name, r->name);
|
||||
lm_rem_resource(ls, r);
|
||||
list_del(&r->list);
|
||||
free_resource(r);
|
||||
}
|
||||
}
|
||||
|
||||
return lk_count;
|
||||
static struct resource *find_dispose_act(struct lockspace *ls, struct action *act)
|
||||
{
|
||||
struct resource *r;
|
||||
|
||||
/* Only resources for unlocked LVs should exist on the dispose list. */
|
||||
|
||||
list_for_each_entry(r, &ls->dispose, list) {
|
||||
if (r->type == LD_RT_LV && !strcmp(r->name, act->lv_uuid)) {
|
||||
list_del(&r->list);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2496,6 +2547,7 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
int adopt_ok = 0;
|
||||
int wait_flag = 0;
|
||||
int nodelay = 0;
|
||||
int nocreate;
|
||||
int retry;
|
||||
int rv;
|
||||
|
||||
@ -2725,10 +2777,64 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (act->op == LD_OP_FREE && act->rt == LD_RT_LV) {
|
||||
list_del(&act->list);
|
||||
|
||||
r = find_dispose_act(ls, act); /* removes r from dispose list */
|
||||
if (r) {
|
||||
log_debug("%s:%s free_lv from dispose for %u", ls->name, r->name, act->client_id);
|
||||
rv = free_lv(ls, r);
|
||||
lm_rem_resource(ls, r);
|
||||
free_resource(r);
|
||||
act->result = rv;
|
||||
add_client_result(act);
|
||||
} else {
|
||||
/* Happens when init_lv was called, but lock was never acquired. */
|
||||
log_debug("%s:%s free_lv lock_args %s not found on dispose list",
|
||||
ls->name, act->lv_uuid, act->lv_args);
|
||||
if (!(r = alloc_resource())) {
|
||||
rv = -ENOMEM;
|
||||
} else {
|
||||
dm_strncpy(r->name, act->lv_uuid, sizeof(r->name));
|
||||
memcpy(r->lv_args, act->lv_args, MAX_ARGS);
|
||||
r->type = LD_RT_LV;
|
||||
r->mode = LD_LK_UN;
|
||||
lm_add_resource(ls, r);
|
||||
rv = free_lv(ls, r);
|
||||
lm_rem_resource(ls, r);
|
||||
free_resource(r);
|
||||
}
|
||||
act->result = rv;
|
||||
add_client_result(act);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
list_del(&act->list);
|
||||
|
||||
/* applies to all resources */
|
||||
if (act->op == LD_OP_CLOSE) {
|
||||
/*
|
||||
* free any resources the client moved to
|
||||
* ls->dispose after unlocking. Between the
|
||||
* time the client unlocked the LV, and now,
|
||||
* another client could have created a new
|
||||
* struct resource on ls->resources for the
|
||||
* same LV. This would not be a problem.
|
||||
*/
|
||||
list_for_each_entry_safe(r, r2, &ls->dispose, list) {
|
||||
if (r->dispose_client_id == act->client_id) {
|
||||
log_debug("%s:%s free_resource from dispose for %u",
|
||||
ls->name, r->name, act->client_id);
|
||||
list_del(&r->list);
|
||||
lm_rem_resource(ls, r);
|
||||
free_resource(r);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check all resources for transient locks the client
|
||||
* was holding that should be automatically unlocked
|
||||
*/
|
||||
list_add(&act->list, &act_close);
|
||||
continue;
|
||||
}
|
||||
@ -2741,10 +2847,12 @@ static void *lockspace_thread_main(void *arg_in)
|
||||
* (This creates a new resource if the one named in
|
||||
* the act is not found.)
|
||||
*/
|
||||
nocreate = (act->op == LD_OP_FREE) ||
|
||||
((act->op == LD_OP_LOCK) && (act->mode == LD_LK_UN));
|
||||
|
||||
r = find_resource_act(ls, act, (act->op == LD_OP_FREE) ? 1 : 0);
|
||||
r = find_resource_act(ls, act, nocreate);
|
||||
if (!r) {
|
||||
act->result = (act->op == LD_OP_FREE) ? -ENOENT : -ENOMEM;
|
||||
act->result = nocreate ? -ENOENT : -ENOMEM;
|
||||
add_client_result(act);
|
||||
continue;
|
||||
}
|
||||
@ -2803,7 +2911,7 @@ out_rem:
|
||||
|
||||
log_debug("S %s clearing locks", ls->name);
|
||||
|
||||
(void) clear_locks(ls, free_vg, drop_vg);
|
||||
clear_locks(ls, free_vg, drop_vg);
|
||||
|
||||
/*
|
||||
* Tell any other hosts in the lockspace to leave it
|
||||
@ -4073,9 +4181,9 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
if (act->lv_args[0])
|
||||
lv_args = act->lv_args;
|
||||
|
||||
log_debug("send %s[%d] cl %u %s %s rv %d vg_args %s lv_args %s",
|
||||
log_debug("send %s[%d][%u] %s%s%s result %d vg_args %s lv_args %s",
|
||||
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
|
||||
op_str(act->op), rt_str(act->rt),
|
||||
op_str(act->op), act->rt ? "_" : "", rt_str(act->rt),
|
||||
act->result, vg_args ? vg_args : "", lv_args ? lv_args : "");
|
||||
|
||||
res = daemon_reply_simple("OK",
|
||||
@ -4089,9 +4197,9 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
|
||||
} else if (act->op == LD_OP_QUERY_LOCK) {
|
||||
|
||||
log_debug("send %s[%d] cl %u %s %s rv %d mode %d",
|
||||
log_debug("send %s[%d][%u] %s%s%s result %d mode %d",
|
||||
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
|
||||
op_str(act->op), rt_str(act->rt),
|
||||
op_str(act->op), act->rt ? "_" : "", rt_str(act->rt),
|
||||
act->result, act->mode);
|
||||
|
||||
res = daemon_reply_simple("OK",
|
||||
@ -4119,7 +4227,7 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
else
|
||||
act->result = -EINVAL;
|
||||
|
||||
log_debug("send %s[%d] cl %u dump result %d dump_len %d",
|
||||
log_debug("send %s[%d][%u] dump result %d dump_len %d",
|
||||
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
|
||||
act->result, dump_len);
|
||||
|
||||
@ -4132,9 +4240,9 @@ static int client_send_result(struct client *cl, struct action *act)
|
||||
* A normal reply.
|
||||
*/
|
||||
|
||||
log_debug("send %s[%d] cl %u %s %s rv %d %s %s",
|
||||
log_debug("send %s[%d][%u] %s%s%s result %d %s %s",
|
||||
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
|
||||
op_mode_str(act->op, act->mode), rt_str(act->rt),
|
||||
op_mode_str(act->op, act->mode), act->rt ? "_" : "", rt_str(act->rt),
|
||||
act->result, (act->result == -ENOLS) ? "ENOLS" : "", result_flags);
|
||||
|
||||
res = daemon_reply_simple("OK",
|
||||
@ -5066,9 +5174,16 @@ skip_pvs_path:
|
||||
dm_config_destroy(req.cft);
|
||||
buffer_destroy(&req.buffer);
|
||||
|
||||
log_debug("recv %s[%d] cl %u %s %s \"%s\" flags %x",
|
||||
log_debug("recv %s[%d][%u] %s%s%s %s%s %s%s%s%s opts=%x",
|
||||
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
|
||||
op_mode_str(act->op, act->mode), rt_str(act->rt), act->vg_name, opts);
|
||||
op_mode_str(act->op, act->mode), act->rt ? "_" : "", rt_str(act->rt),
|
||||
act->vg_name[0] ? "vg=" : "",
|
||||
act->vg_name,
|
||||
act->lv_name[0] || act->lv_uuid[0] ? "lv=" : "",
|
||||
act->lv_name[0] ? act->lv_name : "",
|
||||
act->lv_uuid[0] ? ":" : "",
|
||||
act->lv_uuid[0] ? act->lv_uuid : "",
|
||||
opts);
|
||||
|
||||
if (lm == LD_LM_DLM && !lm_support_dlm()) {
|
||||
log_debug("dlm not supported");
|
||||
@ -5524,6 +5639,9 @@ static void adopt_locks(void)
|
||||
INIT_LIST_HEAD(&vg_lockd);
|
||||
INIT_LIST_HEAD(&to_unlock);
|
||||
|
||||
if (daemon_test)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Get list of lockspaces from currently running lock managers.
|
||||
* Get list of shared VGs from file written by prior lvmlockd.
|
||||
@ -6200,7 +6318,7 @@ static int main_loop(daemon_state *ds_arg)
|
||||
setup_worker_thread();
|
||||
setup_restart();
|
||||
|
||||
#ifdef USE_SD_NOTIFY
|
||||
#ifdef SD_NOTIFY_SUPPORT
|
||||
sd_notify(0, "READY=1");
|
||||
#endif
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "daemon-server.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
@ -169,8 +169,10 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls)
|
||||
struct lm_dlm *lmd;
|
||||
int rv;
|
||||
|
||||
if (daemon_test)
|
||||
if (daemon_test) {
|
||||
log_debug("lm_prepare_lockspace_dlm test");
|
||||
goto skip_args;
|
||||
}
|
||||
|
||||
memset(sys_clustername, 0, sizeof(sys_clustername));
|
||||
memset(arg_clustername, 0, sizeof(arg_clustername));
|
||||
@ -361,7 +363,7 @@ int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
|
||||
int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
|
||||
{
|
||||
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
|
||||
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "daemon-server.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
@ -490,7 +490,7 @@ out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
|
||||
#include "base/memory/container_of.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_NAME 64
|
||||
#define MAX_ARGS 64
|
||||
|
||||
@ -163,6 +166,7 @@ struct resource {
|
||||
unsigned int sh_count; /* number of sh locks on locks list */
|
||||
uint32_t version;
|
||||
uint32_t last_client_id; /* last client_id to lock or unlock resource */
|
||||
uint32_t dispose_client_id; /* client_id disposing of resource struct */
|
||||
unsigned int lm_init : 1; /* lm_data is initialized */
|
||||
unsigned int adopt : 1; /* temp flag in remove_inactive_lvs */
|
||||
unsigned int version_zero_valid : 1;
|
||||
@ -212,6 +216,7 @@ struct lockspace {
|
||||
|
||||
struct list_head actions; /* new client actions */
|
||||
struct list_head resources; /* resource/lock state for gl/vg/lv */
|
||||
struct list_head dispose; /* resources to free */
|
||||
};
|
||||
|
||||
/* val_blk version */
|
||||
@ -278,15 +283,15 @@ static inline int list_empty(const struct list_head *head)
|
||||
list_entry((ptr)->next, type, member)
|
||||
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
for (pos = list_entry((head)->next, __typeof__(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
pos = list_entry(pos->member.next, __typeof__(*pos), member))
|
||||
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
for (pos = list_entry((head)->next, __typeof__(*pos), member), \
|
||||
n = list_entry(pos->member.next, __typeof__(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
pos = n, n = list_entry(n->member.next, __typeof__(*n), member))
|
||||
|
||||
|
||||
/* to improve readability */
|
||||
@ -397,6 +402,7 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls);
|
||||
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok);
|
||||
int lm_purge_locks_dlm(struct lockspace *ls);
|
||||
int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg);
|
||||
int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl);
|
||||
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int adopt_only, int adopt_ok);
|
||||
int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
@ -420,69 +426,102 @@ static inline int lm_support_dlm(void)
|
||||
|
||||
static inline int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_prepare_lockspace_dlm(struct lockspace *ls)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_purge_locks_dlm(struct lockspace *ls)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int adopt_only, int adopt_ok)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
uint32_t r_version, uint32_t lmu_flags)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_data_size_dlm(void)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_is_running_dlm(void)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lm_support_dlm(void)
|
||||
{
|
||||
if (daemon_test)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -512,6 +551,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
|
||||
int lm_prepare_lockspace_sanlock(struct lockspace *ls);
|
||||
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok, int nodelay);
|
||||
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
|
||||
int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r);
|
||||
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int *retry,
|
||||
int adopt_only, int adopt_ok);
|
||||
@ -571,6 +611,11 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
struct val_blk *vb_out, int *retry,
|
||||
int adopt_only, int adopt_ok)
|
||||
@ -649,6 +694,7 @@ 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_only, int adopt_ok);
|
||||
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg);
|
||||
int lm_add_resource_idm(struct lockspace *ls, struct resource *r);
|
||||
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_only, int adopt_ok);
|
||||
@ -694,6 +740,11 @@ static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
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_only, int adopt_ok)
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "daemon-server.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
@ -153,11 +153,11 @@ struct lm_sanlock {
|
||||
};
|
||||
|
||||
struct rd_sanlock {
|
||||
struct val_blk *vb;
|
||||
union {
|
||||
struct sanlk_resource rs;
|
||||
char buf[sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk)];
|
||||
};
|
||||
struct val_blk *vb;
|
||||
};
|
||||
|
||||
struct sanlk_resourced {
|
||||
@ -298,8 +298,8 @@ static int read_host_id_file(void)
|
||||
*sep = '\0';
|
||||
memset(key_str, 0, sizeof(key_str));
|
||||
memset(val_str, 0, sizeof(val_str));
|
||||
(void) sscanf(key, "%s", key_str);
|
||||
(void) sscanf(val, "%s", val_str);
|
||||
(void) sscanf(key, "%63s", key_str);
|
||||
(void) sscanf(val, "%63s", val_str);
|
||||
|
||||
if (!strcmp(key_str, "host_id")) {
|
||||
host_id = atoi(val_str);
|
||||
@ -846,6 +846,11 @@ int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char
|
||||
offset = align_size * LV_LOCK_BEGIN;
|
||||
}
|
||||
|
||||
if (offset < (align_size * LV_LOCK_BEGIN)) {
|
||||
log_error("S %s init_lv_san invalid offset %llu", ls_name, (unsigned long long)offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
|
||||
rd.rs.num_disks = 1;
|
||||
memcpy(rd.rs.disks[0].path, disk_path, SANLK_PATH_LEN-1);
|
||||
@ -1094,22 +1099,35 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
|
||||
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
|
||||
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
|
||||
struct sanlk_resource *rs = &rds->rs;
|
||||
uint64_t offset = rds->rs.disks[0].offset;
|
||||
int rv;
|
||||
|
||||
log_debug("%s:%s free_lv_san", ls->name, r->name);
|
||||
log_debug("%s:%s free_lv_san %llu", ls->name, r->name, (unsigned long long)offset);
|
||||
|
||||
if (daemon_test)
|
||||
return 0;
|
||||
|
||||
strcpy_name_len(rs->name, "#unused", SANLK_NAME_LEN);
|
||||
|
||||
rv = sanlock_write_resource(rs, 0, 0, 0);
|
||||
if (rv < 0) {
|
||||
log_error("%s:%s free_lv_san write error %d",
|
||||
ls->name, r->name, rv);
|
||||
if (!offset) {
|
||||
lock_lv_offset_from_args(r->lv_args, &offset);
|
||||
rds->rs.disks[0].offset = offset;
|
||||
log_debug("%s:%s free_lv_san lock_args offset %llu", ls->name, r->name, (unsigned long long)offset);
|
||||
}
|
||||
|
||||
if (offset < (lms->align_size * LV_LOCK_BEGIN)) {
|
||||
log_error("%s:%s free_lv_san invalid offset %llu",
|
||||
ls->name, r->name, (unsigned long long)offset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = sanlock_write_resource(rs, 0, 0, 0);
|
||||
if (rv < 0)
|
||||
log_error("%s:%s free_lv_san %llu write error %d",
|
||||
ls->name, r->name, (unsigned long long)offset, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1734,7 +1752,7 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
|
||||
int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
|
||||
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
|
||||
|
@ -15,8 +15,8 @@
|
||||
#include "lvmpolld-common.h"
|
||||
|
||||
#include "lvm-version.h"
|
||||
#include "daemon-server.h"
|
||||
#include "daemon-log.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "libdaemon/server/daemon-log.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
@ -390,6 +390,11 @@ static void *fork_and_poll(void *args)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!pdlv->cmdargv || !*(pdlv->cmdargv)) {
|
||||
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "Missing command");
|
||||
goto err;
|
||||
}
|
||||
|
||||
DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "cmd line arguments:");
|
||||
debug_print(ls, pdlv->cmdargv);
|
||||
DEBUGLOG(ls, "%s: %s", PD_LOG_PREFIX, "---end---");
|
||||
|
@ -46,7 +46,7 @@ static char *_construct_lvm_system_dir_env(const char *sysdir)
|
||||
* - or -
|
||||
* just single char to store NULL byte
|
||||
*/
|
||||
size_t l = sysdir ? strlen(sysdir) + 16 : 1;
|
||||
size_t l = sysdir ? strlen(sysdir) + sizeof(LVM_SYSTEM_DIR): 1;
|
||||
char *env = (char *) malloc(l * sizeof(char));
|
||||
|
||||
if (!env)
|
||||
@ -89,6 +89,17 @@ char *construct_id(const char *sysdir, const char *uuid)
|
||||
return id;
|
||||
}
|
||||
|
||||
static void _free_lvmpolld_lv(struct lvmpolld_lv *p)
|
||||
{
|
||||
free((void *)p->devicesfile);
|
||||
free((void *)p->lvm_system_dir_env);
|
||||
free((void *)p->lvmpolld_id);
|
||||
free((void *)p->lvname);
|
||||
free((void *)p->sinterval);
|
||||
free((void *)p->cmdargv);
|
||||
free((void *)p->cmdenvp);
|
||||
}
|
||||
|
||||
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,
|
||||
@ -96,30 +107,26 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
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,
|
||||
.type = type,
|
||||
.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 */
|
||||
.lvmpolld_id = strdup(id),
|
||||
.lvname = _construct_full_lvname(vgname, lvname),
|
||||
.devicesfile = devicesfile ? strdup(devicesfile) : NULL,
|
||||
.lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir),
|
||||
.sinterval = strdup(sinterval),
|
||||
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
|
||||
.cmd_state = { .retcode = -1, .signal = 0 },
|
||||
.pdst = pdst,
|
||||
.init_rq_count = 1
|
||||
}, *pdlv = (struct lvmpolld_lv *) malloc(sizeof(struct lvmpolld_lv));
|
||||
|
||||
if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
|
||||
if (!pdlv || !tmp.lvmpolld_id || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
|
||||
goto err;
|
||||
|
||||
memcpy(pdlv, &tmp, sizeof(*pdlv));
|
||||
tmp.lvid = _get_lvid(tmp.lvmpolld_id, sysdir),
|
||||
|
||||
*pdlv = tmp;
|
||||
|
||||
if (pthread_mutex_init(&pdlv->lock, NULL))
|
||||
goto err;
|
||||
@ -127,29 +134,20 @@ 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);
|
||||
free((void *)tmp.sinterval);
|
||||
free((void *)pdlv);
|
||||
_free_lvmpolld_lv(&tmp);
|
||||
|
||||
free(pdlv);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
free((void *)pdlv->cmdargv);
|
||||
free((void *)pdlv->cmdenvp);
|
||||
_free_lvmpolld_lv(pdlv);
|
||||
|
||||
pthread_mutex_destroy(&pdlv->lock);
|
||||
|
||||
free((void *)pdlv);
|
||||
free(pdlv);
|
||||
}
|
||||
|
||||
unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv)
|
||||
|
@ -15,7 +15,10 @@
|
||||
#ifndef _LVM_LVMPOLLD_DATA_UTILS_H
|
||||
#define _LVM_LVMPOLLD_DATA_UTILS_H
|
||||
|
||||
#include "base/data-struct/hash.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct buffer;
|
||||
struct lvmpolld_state;
|
||||
@ -93,7 +96,7 @@ struct lvmpolld_thread_data {
|
||||
struct lvmpolld_lv *pdlv;
|
||||
};
|
||||
|
||||
char *construct_id(const char *sysdir, const char *lvid);
|
||||
char *construct_id(const char *sysdir, const char *uuid);
|
||||
|
||||
/* LVMPOLLD_LV_T section */
|
||||
|
||||
|
@ -191,7 +191,7 @@ struct dm_versions {
|
||||
|
||||
int dm_get_library_version(char *version, size_t size);
|
||||
int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size);
|
||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
|
||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *info);
|
||||
|
||||
/*
|
||||
* This function returns dm device's UUID based on the value
|
||||
@ -1051,7 +1051,7 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
|
||||
const char *vdo_pool_name,
|
||||
const char *data_uuid,
|
||||
uint64_t data_size,
|
||||
const struct dm_vdo_target_params *param);
|
||||
const struct dm_vdo_target_params *vtp);
|
||||
|
||||
/*
|
||||
* FIXME Add individual cache policy pairs <key> = value, like:
|
||||
@ -1178,9 +1178,9 @@ void dm_tree_node_set_presuspend_node(struct dm_tree_node *node,
|
||||
struct dm_tree_node *presuspend_node);
|
||||
|
||||
int dm_tree_node_add_target_area(struct dm_tree_node *node,
|
||||
const char *dev_name,
|
||||
const char *dlid,
|
||||
uint64_t offset);
|
||||
const char *dev_name,
|
||||
const char *uuid,
|
||||
uint64_t offset);
|
||||
|
||||
/*
|
||||
* Only for temporarily-missing raid devices where changes are tracked.
|
||||
@ -1590,9 +1590,9 @@ int dm_fclose(FILE *stream);
|
||||
* Pointer to the buffer is stored in *buf.
|
||||
* Returns -1 on failure leaving buf undefined.
|
||||
*/
|
||||
int dm_asprintf(char **buf, const char *format, ...)
|
||||
int dm_asprintf(char **result, const char *format, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
int dm_vasprintf(char **buf, const char *format, va_list ap)
|
||||
int dm_vasprintf(char **result, const char *format, va_list aq)
|
||||
__attribute__ ((format(printf, 2, 0)));
|
||||
|
||||
/*
|
||||
@ -1941,7 +1941,7 @@ void dm_report_free(struct dm_report *rh);
|
||||
* Prefix added to each field name with DM_REPORT_OUTPUT_FIELD_NAME_PREFIX
|
||||
*/
|
||||
int dm_report_set_output_field_name_prefix(struct dm_report *rh,
|
||||
const char *report_prefix);
|
||||
const char *output_field_name_prefix);
|
||||
|
||||
int dm_report_set_selection(struct dm_report *rh, const char *selection);
|
||||
|
||||
@ -2081,7 +2081,7 @@ int dm_config_write_one_node_out(const struct dm_config_node *cn, const struct d
|
||||
|
||||
struct dm_config_node *dm_config_find_node(const struct dm_config_node *cn, const char *path);
|
||||
int dm_config_has_node(const struct dm_config_node *cn, const char *path);
|
||||
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *remove);
|
||||
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *rem_node);
|
||||
const char *dm_config_find_str(const struct dm_config_node *cn, const char *path, const char *fail);
|
||||
const char *dm_config_find_str_allow_empty(const struct dm_config_node *cn, const char *path, const char *fail);
|
||||
int dm_config_find_int(const struct dm_config_node *cn, const char *path, int fail);
|
||||
@ -2113,7 +2113,7 @@ unsigned dm_config_maybe_section(const char *str, unsigned len);
|
||||
|
||||
const char *dm_config_parent_name(const struct dm_config_node *n);
|
||||
|
||||
struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *node, int siblings);
|
||||
struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const struct dm_config_node *cn, int siblings);
|
||||
struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key);
|
||||
struct dm_config_value *dm_config_create_value(struct dm_config_tree *cft);
|
||||
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *cn, int siblings);
|
||||
|
@ -70,6 +70,7 @@ static unsigned _dm_version_minor = 0;
|
||||
static unsigned _dm_version_patchlevel = 0;
|
||||
static int _log_suppress = 0;
|
||||
static struct dm_timestamp *_dm_ioctl_timestamp = NULL;
|
||||
static int _dm_warn_inactive_suppress = 0;
|
||||
|
||||
/*
|
||||
* If the kernel dm driver only supports one major number
|
||||
@ -485,7 +486,7 @@ static void _dm_zfree_string(char *string)
|
||||
{
|
||||
if (string) {
|
||||
memset(string, 0, strlen(string));
|
||||
asm volatile ("" ::: "memory"); /* Compiler barrier. */
|
||||
__asm__ volatile ("" ::: "memory"); /* Compiler barrier. */
|
||||
free(string);
|
||||
}
|
||||
}
|
||||
@ -494,7 +495,7 @@ static void _dm_zfree_dmi(struct dm_ioctl *dmi)
|
||||
{
|
||||
if (dmi) {
|
||||
memset(dmi, 0, dmi->data_size);
|
||||
asm volatile ("" ::: "memory"); /* Compiler barrier. */
|
||||
__asm__ volatile ("" ::: "memory"); /* Compiler barrier. */
|
||||
free(dmi);
|
||||
}
|
||||
}
|
||||
@ -1412,22 +1413,23 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
|
||||
}
|
||||
if (dmt->query_inactive_table) {
|
||||
if (!_dm_inactive_supported())
|
||||
log_warn("WARNING: Inactive table query unsupported "
|
||||
"by kernel. It will use live table.");
|
||||
log_warn_suppress(_dm_warn_inactive_suppress++,
|
||||
"WARNING: Inactive table query unsupported by kernel. "
|
||||
"It will use live table.");
|
||||
dmi->flags |= DM_QUERY_INACTIVE_TABLE_FLAG;
|
||||
}
|
||||
if (dmt->new_uuid) {
|
||||
if (_dm_version_minor < 19) {
|
||||
log_error("WARNING: Setting UUID unsupported by "
|
||||
"kernel. Aborting operation.");
|
||||
log_error("Setting UUID unsupported by kernel. "
|
||||
"Aborting operation.");
|
||||
goto bad;
|
||||
}
|
||||
dmi->flags |= DM_UUID_FLAG;
|
||||
}
|
||||
if (dmt->ima_measurement) {
|
||||
if (_dm_version_minor < 45) {
|
||||
log_error("WARNING: IMA measurement unsupported by "
|
||||
"kernel. Aborting operation.");
|
||||
log_error("IMA measurement unsupported by kernel. "
|
||||
"Aborting operation.");
|
||||
goto bad;
|
||||
}
|
||||
dmi->flags |= DM_IMA_MEASUREMENT_FLAG;
|
||||
|
@ -16,6 +16,8 @@
|
||||
#ifndef LIB_DMTARGETS_H
|
||||
#define LIB_DMTARGETS_H
|
||||
|
||||
#include "device_mapper/all.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
@ -511,7 +511,7 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
|
||||
char *buf, size_t buf_len, dm_string_mangling_t mode)
|
||||
{
|
||||
int strict = mode != DM_STRING_MANGLING_NONE;
|
||||
char str_rest[DM_NAME_LEN];
|
||||
char str_rest[DM_NAME_LEN + 1];
|
||||
size_t i, j;
|
||||
unsigned int code;
|
||||
int r = 0;
|
||||
|
@ -36,7 +36,7 @@ struct target *create_target(uint64_t start,
|
||||
uint64_t len,
|
||||
const char *type, const char *params);
|
||||
|
||||
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major,
|
||||
int add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
uid_t uid, gid_t gid, mode_t mode, int check_udev, unsigned rely_on_udev);
|
||||
int rm_dev_node(const char *dev_name, int check_udev, unsigned rely_on_udev);
|
||||
int rename_dev_node(const char *old_name, const char *new_name,
|
||||
|
@ -1461,9 +1461,9 @@ struct dm_config_node *dm_config_clone_node_with_mem(struct dm_pool *mem, const
|
||||
return new_cn;
|
||||
}
|
||||
|
||||
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *node, int sib)
|
||||
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *cn, int sib)
|
||||
{
|
||||
return dm_config_clone_node_with_mem(cft->mem, node, sib);
|
||||
return dm_config_clone_node_with_mem(cft->mem, cn, sib);
|
||||
}
|
||||
|
||||
struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key)
|
||||
|
@ -152,15 +152,17 @@ struct thin_message {
|
||||
struct load_segment {
|
||||
struct dm_list list;
|
||||
|
||||
unsigned type;
|
||||
|
||||
uint64_t size;
|
||||
|
||||
unsigned type;
|
||||
|
||||
unsigned area_count; /* Linear + Striped + Mirrored + Crypt */
|
||||
struct dm_list areas; /* Linear + Striped + Mirrored + Crypt */
|
||||
|
||||
uint32_t stripe_size; /* Striped + raid */
|
||||
|
||||
uint32_t region_size; /* Mirror + raid */
|
||||
|
||||
int persistent; /* Snapshot */
|
||||
uint32_t chunk_size; /* Snapshot */
|
||||
struct dm_tree_node *cow; /* Snapshot */
|
||||
@ -168,7 +170,6 @@ struct load_segment {
|
||||
struct dm_tree_node *merge; /* Snapshot */
|
||||
|
||||
struct dm_tree_node *log; /* Mirror */
|
||||
uint32_t region_size; /* Mirror + raid */
|
||||
unsigned clustered; /* Mirror */
|
||||
unsigned mirror_area_count; /* Mirror */
|
||||
uint64_t flags; /* Mirror + Raid + Cache */
|
||||
@ -540,7 +541,8 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
|
||||
struct dm_tree_node *node;
|
||||
dev_t dev;
|
||||
|
||||
if (!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
|
||||
if (!dtree || !dtree->mem ||
|
||||
!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
|
||||
!(node->name = dm_pool_strdup(dtree->mem, name)) ||
|
||||
!(node->uuid = dm_pool_strdup(dtree->mem, uuid))) {
|
||||
log_error("_create_dm_tree_node alloc failed.");
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
struct selection {
|
||||
struct dm_pool *mem;
|
||||
struct dm_pool *regex_mem;
|
||||
struct selection_node *selection_root;
|
||||
int add_new_fields;
|
||||
};
|
||||
@ -204,7 +205,9 @@ static const struct op_def _op_log[] = {
|
||||
|
||||
struct selection_str_list {
|
||||
struct dm_str_list str_list;
|
||||
unsigned type; /* either SEL_AND or SEL_OR */
|
||||
struct dm_regex *regex;
|
||||
size_t regex_num_patterns;
|
||||
unsigned type; /* either SEL_LIST_LS or SEL_LIST_SUBSET_LS with either SEL_AND or SEL_OR */
|
||||
};
|
||||
|
||||
struct field_selection_value {
|
||||
@ -547,7 +550,7 @@ static int _report_field_string_list(struct dm_report *rh,
|
||||
}
|
||||
|
||||
/* more than one item - allocate temporary array for string list items for further processing */
|
||||
if (!(arr = malloc(list_size * sizeof(struct str_pos_len)))) {
|
||||
if (!(arr = zalloc(list_size * sizeof(struct str_pos_len)))) {
|
||||
log_error("%s failed to allocate temporary array for processing", _error_msg_prefix);
|
||||
goto out;
|
||||
}
|
||||
@ -589,7 +592,8 @@ static int _report_field_string_list(struct dm_report *rh,
|
||||
for (i = 0, pos = 0; i < list_size; i++) {
|
||||
arr[i].item.pos = pos;
|
||||
|
||||
memcpy(repstr + pos, arr[i].str, arr[i].item.len);
|
||||
if (arr[i].str)
|
||||
memcpy(repstr + pos, arr[i].str, arr[i].item.len);
|
||||
memcpy(repstr_extra + i + 1, &arr[i].item, sizeof(struct pos_len));
|
||||
|
||||
pos += arr[i].item.len;
|
||||
@ -1411,8 +1415,11 @@ struct dm_report *dm_report_init(uint32_t *report_types,
|
||||
|
||||
void dm_report_free(struct dm_report *rh)
|
||||
{
|
||||
if (rh->selection)
|
||||
if (rh->selection) {
|
||||
dm_pool_destroy(rh->selection->mem);
|
||||
if (rh->selection->regex_mem)
|
||||
dm_pool_destroy(rh->selection->regex_mem);
|
||||
}
|
||||
if (rh->value_cache)
|
||||
dm_hash_destroy(rh->value_cache);
|
||||
dm_pool_destroy(rh->mem);
|
||||
@ -1751,8 +1758,74 @@ static int _cmp_field_time(struct dm_report *rh,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _str_list_item_match_regex(const struct str_list_sort_value *val, unsigned int i, struct dm_regex *regex)
|
||||
{
|
||||
struct pos_len *item = val->items + i;
|
||||
char *s = (char *) (val->value + item->pos);
|
||||
char c = s[item->len];
|
||||
int r;
|
||||
|
||||
/*
|
||||
* The val->items contains the whole string list in the form of a single string,
|
||||
* where each item is delimited by a delimiter.
|
||||
*
|
||||
* The item->pos + item->len pair then points to the exact item within the val->items.
|
||||
*
|
||||
* The dm_regex_match accepts a string, not the pos + len pair, so we need to adapt here:
|
||||
* replace the delimiter with '\0' temporarily so the item is a proper string.
|
||||
*/
|
||||
s[item->len] = '\0';
|
||||
r = dm_regex_match(regex, s);
|
||||
s[item->len] = c;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static size_t _bitset_count_set(dm_bitset_t bs)
|
||||
{
|
||||
size_t i, size = bs[0]/DM_BITS_PER_INT + 1;
|
||||
size_t count = 0;
|
||||
|
||||
for (i = 1; i <= size; i++)
|
||||
count += hweight32(bs[i]);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match list value strictly 1:1. */
|
||||
static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *val,
|
||||
static int _cmp_field_string_list_strict_regex_all(const struct dm_report *rh,
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int i;
|
||||
dm_bitset_t bs;
|
||||
int r;
|
||||
|
||||
if (!val->items)
|
||||
return (sel->regex_num_patterns == 1) && dm_regex_match(sel->regex, "") >= 0;
|
||||
|
||||
if (!(bs = dm_bitset_create(rh->selection->mem, sel->regex_num_patterns))) {
|
||||
log_error("Failed to create bitset for regex match counter.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
if ((r = _str_list_item_match_regex(val, i, sel->regex)) < 0) {
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
dm_bit_set(bs, r);
|
||||
}
|
||||
|
||||
r = _bitset_count_set(bs) == sel->regex_num_patterns;
|
||||
out:
|
||||
dm_pool_free(rh->selection->mem, bs);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match list value strictly 1:1. */
|
||||
static int _cmp_field_string_list_strict_all(const struct dm_report *rh,
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int sel_list_size = dm_list_size(&sel->str_list.list);
|
||||
@ -1784,7 +1857,36 @@ static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *v
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match a subset of list value. */
|
||||
static int _cmp_field_string_list_subset_all(const struct str_list_sort_value *val,
|
||||
static int _cmp_field_string_list_subset_regex_all(const struct dm_report *rh,
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
dm_bitset_t bs;
|
||||
unsigned int i;
|
||||
int r;
|
||||
|
||||
if (!val->items)
|
||||
return (sel->regex_num_patterns == 1) && dm_regex_match(sel->regex, "") >= 0;
|
||||
|
||||
if (!(bs = dm_bitset_create(rh->selection->mem, sel->regex_num_patterns))) {
|
||||
log_error("Failed to create bitset for regex match counter.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
if ((r = _str_list_item_match_regex(val, i, sel->regex)) < 0)
|
||||
continue;
|
||||
dm_bit_set(bs, r);
|
||||
}
|
||||
|
||||
r = _bitset_count_set(bs) == sel->regex_num_patterns;
|
||||
dm_pool_free(rh->selection->mem, bs);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match a subset of list value. */
|
||||
static int _cmp_field_string_list_subset_all(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int sel_list_size = dm_list_size(&sel->str_list.list);
|
||||
@ -1819,8 +1921,26 @@ static int _cmp_field_string_list_subset_all(const struct str_list_sort_value *v
|
||||
}
|
||||
|
||||
/* Matches if any item from selection string list matches list value. */
|
||||
static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
static int _cmp_field_string_list_subset_regex_any(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!val->items)
|
||||
return dm_regex_match(sel->regex, "") >= 0;
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
if (_str_list_item_match_regex(val, i, sel->regex) >= 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Matches if any item from selection string list matches list value. */
|
||||
static int _cmp_field_string_list_subset_any(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
struct dm_str_list *sel_item;
|
||||
unsigned int i;
|
||||
@ -1849,7 +1969,59 @@ static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _cmp_field_string_list(struct dm_report *rh __attribute__((unused)),
|
||||
/* Matches if all items from list value can be matched by any item from selection list. */
|
||||
static int _cmp_field_string_list_strict_regex_any(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!val->items)
|
||||
return dm_regex_match(sel->regex, "") >= 0;
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
if (_str_list_item_match_regex(val, i, sel->regex) < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Matches if all items from list value can be matched by any item from selection list. */
|
||||
static int _cmp_field_string_list_strict_any(const struct dm_report *rh __attribute__((unused)),
|
||||
const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
struct dm_str_list *sel_item;
|
||||
unsigned int i;
|
||||
int match;
|
||||
|
||||
/* match blank string list with selection that contains blank string */
|
||||
if (!val->items) {
|
||||
dm_list_iterate_items(sel_item, &sel->str_list.list) {
|
||||
if (!strcmp(sel_item->str, ""))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= val->items[0].pos; i++) {
|
||||
match = 0;
|
||||
dm_list_iterate_items(sel_item, &sel->str_list.list) {
|
||||
if ((strlen(sel_item->str) == val->items[i].len) &&
|
||||
!strncmp(sel_item->str, val->value + val->items[i].pos, val->items[i].len)) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _cmp_field_string_list(struct dm_report *rh,
|
||||
uint32_t field_num, const char *field_id,
|
||||
const struct str_list_sort_value *val,
|
||||
struct field_selection *fs)
|
||||
@ -1871,11 +2043,16 @@ static int _cmp_field_string_list(struct dm_report *rh __attribute__((unused)),
|
||||
|
||||
switch (sel->type & SEL_MASK) {
|
||||
case SEL_AND:
|
||||
r = subset ? _cmp_field_string_list_subset_all(val, sel)
|
||||
: _cmp_field_string_list_strict_all(val, sel);
|
||||
r = subset ? sel->regex ? _cmp_field_string_list_subset_regex_all(rh, val, sel)
|
||||
: _cmp_field_string_list_subset_all(rh, val, sel)
|
||||
: sel->regex ? _cmp_field_string_list_strict_regex_all(rh, val, sel)
|
||||
: _cmp_field_string_list_strict_all(rh, val, sel);
|
||||
break;
|
||||
case SEL_OR:
|
||||
r = _cmp_field_string_list_any(val, sel);
|
||||
r = subset ? sel->regex ? _cmp_field_string_list_subset_regex_any(rh, val, sel)
|
||||
: _cmp_field_string_list_subset_any(rh, val, sel)
|
||||
: sel->regex ? _cmp_field_string_list_strict_regex_any(rh, val, sel)
|
||||
: _cmp_field_string_list_strict_any(rh, val, sel);
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_cmp_field_string_list: unsupported string "
|
||||
@ -1909,7 +2086,17 @@ static int _compare_selection_field(struct dm_report *rh,
|
||||
}
|
||||
|
||||
if (fs->flags & FLD_CMP_REGEX)
|
||||
r = _cmp_field_regex((const char *) f->sort_value, fs);
|
||||
switch (f->props->flags & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
case DM_REPORT_FIELD_TYPE_STRING:
|
||||
r = _cmp_field_regex((const char *) f->sort_value, fs);
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_STRING_LIST:
|
||||
r = _cmp_field_string_list(rh, f->props->field_num, field_id, (const struct str_list_sort_value *) f->sort_value, fs);
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_compare_selection_field: regex: incorrect type %" PRIu32 " for field %s",
|
||||
f->props->flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
}
|
||||
else {
|
||||
switch(f->props->flags & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
case DM_REPORT_FIELD_TYPE_PERCENT:
|
||||
@ -1936,7 +2123,8 @@ static int _compare_selection_field(struct dm_report *rh,
|
||||
r = _cmp_field_time(rh, f->props->field_num, field_id, *(const time_t *) f->sort_value, fs);
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_compare_selection_field: unknown field type for field %s", field_id);
|
||||
log_error(INTERNAL_ERROR "_compare_selection_field: incorrect type %" PRIu32 " for field %s",
|
||||
f->props->flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2628,11 +2816,9 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
|
||||
static const char *_tok_value_regex(struct dm_report *rh,
|
||||
const struct dm_report_field_type *ft,
|
||||
const char *s, const char **begin,
|
||||
const char **end, uint32_t *flags,
|
||||
struct reserved_value_wrapper *rvw)
|
||||
const char **end, uint32_t *flags)
|
||||
{
|
||||
char c;
|
||||
rvw->reserved = NULL;
|
||||
|
||||
s = _skip_space(s);
|
||||
|
||||
@ -2695,7 +2881,8 @@ static int _add_item_to_string_list(struct dm_pool *mem, const char *begin,
|
||||
static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
struct dm_pool *mem, const char *s,
|
||||
const char **begin, const char **end,
|
||||
struct selection_str_list **sel_str_list)
|
||||
struct selection_str_list **sel_str_list,
|
||||
uint32_t *flags)
|
||||
{
|
||||
static const char _str_list_item_parsing_failed[] = "Failed to parse string list value "
|
||||
"for selection field %s.";
|
||||
@ -2709,12 +2896,11 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
int list_end = 0;
|
||||
char c;
|
||||
|
||||
if (!(ssl = dm_pool_alloc(mem, sizeof(*ssl)))) {
|
||||
log_error("_tok_value_string_list: memory allocation failed for selection list");
|
||||
if (!(ssl = dm_pool_zalloc(mem, sizeof(*ssl)))) {
|
||||
log_error("_tok_value_string_list: memory allocation failed for selection list.");
|
||||
goto bad;
|
||||
}
|
||||
dm_list_init(&ssl->str_list.list);
|
||||
ssl->type = 0;
|
||||
*begin = s;
|
||||
|
||||
if (!(op_flags = _tok_op_log(s, &tmp, SEL_LIST_LS | SEL_LIST_SUBSET_LS))) {
|
||||
@ -2726,7 +2912,7 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
}
|
||||
if (!_add_item_to_string_list(mem, begin_item, end_item, &ssl->str_list.list))
|
||||
goto_bad;
|
||||
ssl->type = SEL_OR | SEL_LIST_LS;
|
||||
ssl->type = SEL_OR | SEL_LIST_SUBSET_LS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2801,12 +2987,17 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
else
|
||||
ssl->type |= SEL_LIST_SUBSET_LS;
|
||||
|
||||
/* Sort the list. */
|
||||
if (!(list_size = dm_list_size(&ssl->str_list.list))) {
|
||||
log_error(INTERNAL_ERROR "_tok_value_string_list: list has no items");
|
||||
goto bad;
|
||||
} else if (list_size == 1)
|
||||
goto out;
|
||||
|
||||
if (*flags & FLD_CMP_REGEX)
|
||||
/* No need to sort the list for regex. */
|
||||
goto out;
|
||||
|
||||
/* Sort the list. */
|
||||
if (!(arr = malloc(sizeof(item) * list_size))) {
|
||||
log_error("_tok_value_string_list: memory allocation failed for sort array");
|
||||
goto bad;
|
||||
@ -3322,7 +3513,10 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
|
||||
s = _skip_space(s);
|
||||
|
||||
s = _get_reserved(rh, expected_type, field_num, implicit, s, begin, end, rvw);
|
||||
/* recognize possible reserved value (but not in a regex) */
|
||||
if (!(*flags & FLD_CMP_REGEX))
|
||||
s = _get_reserved(rh, expected_type, field_num, implicit, s, begin, end, rvw);
|
||||
|
||||
if (rvw->reserved) {
|
||||
/*
|
||||
* FLD_CMP_NUMBER shares operators with FLD_CMP_TIME,
|
||||
@ -3333,17 +3527,24 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
else if (expected_type == DM_REPORT_FIELD_TYPE_NUMBER)
|
||||
*flags &= ~FLD_CMP_TIME;
|
||||
*flags |= expected_type;
|
||||
|
||||
/* if we matched a reserved value, skip further processing of this token */
|
||||
return s;
|
||||
}
|
||||
|
||||
switch (expected_type) {
|
||||
|
||||
case DM_REPORT_FIELD_TYPE_STRING:
|
||||
c = _get_and_skip_quote_char(&s);
|
||||
if (!(s = _tok_value_string(s, begin, end, c, SEL_AND | SEL_OR | SEL_PRECEDENCE_PE, NULL))) {
|
||||
log_error("Failed to parse string value "
|
||||
"for selection field %s.", ft->id);
|
||||
return NULL;
|
||||
if (*flags & FLD_CMP_REGEX) {
|
||||
if (!(s = _tok_value_regex(rh, ft, s, begin, end, flags)))
|
||||
return NULL;
|
||||
} else {
|
||||
c = _get_and_skip_quote_char(&s);
|
||||
if (!(s = _tok_value_string(s, begin, end, c, SEL_AND | SEL_OR | SEL_PRECEDENCE_PE, NULL))) {
|
||||
log_error("Failed to parse string value "
|
||||
"for selection field %s.", ft->id);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*flags |= DM_REPORT_FIELD_TYPE_STRING;
|
||||
break;
|
||||
@ -3352,7 +3553,7 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
if (!(str_list = (struct selection_str_list **) custom))
|
||||
goto_bad;
|
||||
|
||||
s = _tok_value_string_list(ft, mem, s, begin, end, str_list);
|
||||
s = _tok_value_string_list(ft, mem, s, begin, end, str_list, flags);
|
||||
if (!(*str_list)) {
|
||||
log_error("Failed to parse string list value "
|
||||
"for selection field %s.", ft->id);
|
||||
@ -3436,7 +3637,7 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
|
||||
return s;
|
||||
bad:
|
||||
log_error(INTERNAL_ERROR "Forbidden NULL custom detected.");
|
||||
log_error(INTERNAL_ERROR "_tok_value: Forbidden NULL custom parameter detected.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -3507,6 +3708,19 @@ static int _get_reserved_value(struct dm_report *rh, uint32_t field_num,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct dm_regex *_selection_regex_create(struct selection *selection, const char * const *patterns,
|
||||
unsigned num_patterns)
|
||||
{
|
||||
if (!selection->regex_mem) {
|
||||
if (!(selection->regex_mem = dm_pool_create("report selection regex", 32 * 1024))) {
|
||||
log_error("Failed to create report selection regex memory pool.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return dm_regex_create(selection->regex_mem, patterns, num_patterns);
|
||||
}
|
||||
|
||||
static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
uint32_t field_num,
|
||||
int implicit,
|
||||
@ -3524,6 +3738,11 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
struct time_value *tval;
|
||||
uint64_t factor;
|
||||
char *s;
|
||||
const char *s_arr_single[2] = { 0 };
|
||||
const char **s_arr;
|
||||
size_t s_arr_size;
|
||||
struct dm_str_list *sl;
|
||||
size_t i;
|
||||
|
||||
dm_list_iterate_items(fp, &rh->field_props) {
|
||||
if ((fp->implicit == implicit) && (fp->field_num == field_num)) {
|
||||
@ -3588,20 +3807,53 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
/* store comparison operand */
|
||||
if (flags & FLD_CMP_REGEX) {
|
||||
/* REGEX */
|
||||
if (!(s = malloc(len + 1))) {
|
||||
log_error("dm_report: malloc failed to store "
|
||||
"regex value for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
memcpy(s, v, len);
|
||||
s[len] = '\0';
|
||||
switch (flags & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
case DM_REPORT_FIELD_TYPE_STRING:
|
||||
if (!(s = malloc(len + 1))) {
|
||||
log_error("dm_report: malloc failed to store "
|
||||
"regex value for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
memcpy(s, v, len);
|
||||
s[len] = '\0';
|
||||
s_arr_single[0] = s;
|
||||
|
||||
fs->value->v.r = dm_regex_create(rh->selection->mem, (const char * const *) &s, 1);
|
||||
free(s);
|
||||
if (!fs->value->v.r) {
|
||||
log_error("dm_report: failed to create regex "
|
||||
"matcher for selection field %s", field_id);
|
||||
goto error;
|
||||
fs->value->v.r = _selection_regex_create(rh->selection, s_arr_single, 1);
|
||||
free(s);
|
||||
if (!fs->value->v.r) {
|
||||
log_error("dm_report: failed to create regex "
|
||||
"matcher for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case DM_REPORT_FIELD_TYPE_STRING_LIST:
|
||||
if (!custom)
|
||||
goto bad;
|
||||
fs->value->v.l = *((struct selection_str_list **) custom);
|
||||
|
||||
s_arr_size = dm_list_size(&fs->value->v.l->str_list.list);
|
||||
if (!(s_arr = malloc(sizeof(char *) * s_arr_size))) {
|
||||
log_error("dm_report: malloc failed for regex array "
|
||||
"for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
i = 0;
|
||||
dm_list_iterate_items(sl, &fs->value->v.l->str_list.list)
|
||||
s_arr[i++] = sl->str;
|
||||
|
||||
fs->value->v.l->regex = _selection_regex_create(rh->selection, s_arr, s_arr_size);
|
||||
fs->value->v.l->regex_num_patterns = s_arr_size;
|
||||
free(s_arr);
|
||||
if (!fs->value->v.l->regex) {
|
||||
log_error("dm_report: failed to create regex "
|
||||
"matcher for selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: regex: incorrect type %" PRIu32 " for field %s",
|
||||
flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
/* STRING, NUMBER, SIZE, PERCENT, STRING_LIST, TIME */
|
||||
@ -3715,8 +3967,8 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: "
|
||||
"unknown type of selection field %s", field_id);
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: incorrect type %" PRIu32 " for field %s",
|
||||
flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@ -3727,7 +3979,7 @@ error_field_id:
|
||||
field_id);
|
||||
goto error;
|
||||
bad:
|
||||
log_error(INTERNAL_ERROR "Forbidden NULL custom detected.");
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: Forbidden NULL custom detected.");
|
||||
error:
|
||||
dm_pool_free(rh->selection->mem, fs);
|
||||
|
||||
@ -3863,7 +4115,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
char *tmp;
|
||||
char c;
|
||||
|
||||
/* field name */
|
||||
/* get field name */
|
||||
if (!(last = _tok_field_name(s, &ws, &we))) {
|
||||
log_error("Expecting field name");
|
||||
goto bad;
|
||||
@ -3896,7 +4148,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
} else
|
||||
ft = &rh->fields[field_num];
|
||||
|
||||
/* comparison operator */
|
||||
/* get comparison operator */
|
||||
if (!(flags = _tok_op_cmp(we, &last))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Unrecognised comparison operator: %s", we);
|
||||
@ -3908,50 +4160,49 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* comparison value */
|
||||
/* check we can use the operator with the field */
|
||||
if (flags & FLD_CMP_REGEX) {
|
||||
/*
|
||||
* REGEX value
|
||||
*/
|
||||
if (!(last = _tok_value_regex(rh, ft, last, &vs, &ve, &flags, &rvw)))
|
||||
goto_bad;
|
||||
} else {
|
||||
/*
|
||||
* STRING, NUMBER, SIZE, PERCENT, STRING_LIST, TIME value
|
||||
*/
|
||||
if (flags & FLD_CMP_NUMBER) {
|
||||
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_NUMBER |
|
||||
DM_REPORT_FIELD_TYPE_SIZE |
|
||||
DM_REPORT_FIELD_TYPE_PERCENT |
|
||||
DM_REPORT_FIELD_TYPE_TIME))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with number, size, time or percent fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
} else if (flags & FLD_CMP_TIME) {
|
||||
if (!(ft->flags & DM_REPORT_FIELD_TYPE_TIME)) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with time fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_STRING |
|
||||
DM_REPORT_FIELD_TYPE_STRING_LIST))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with string or string list fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
} else if (flags & FLD_CMP_NUMBER) {
|
||||
if (!(ft->flags & (DM_REPORT_FIELD_TYPE_NUMBER |
|
||||
DM_REPORT_FIELD_TYPE_SIZE |
|
||||
DM_REPORT_FIELD_TYPE_PERCENT |
|
||||
DM_REPORT_FIELD_TYPE_TIME))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with number, size, time or percent fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
} else if (flags & FLD_CMP_TIME) {
|
||||
if (!(ft->flags & DM_REPORT_FIELD_TYPE_TIME)) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Operator can be used only with time fields: %s", ws);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (ft->flags == DM_REPORT_FIELD_TYPE_SIZE ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_NUMBER ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_PERCENT)
|
||||
custom = &factor;
|
||||
else if (ft->flags & DM_REPORT_FIELD_TYPE_TIME)
|
||||
custom = &tval;
|
||||
else if (ft->flags == DM_REPORT_FIELD_TYPE_STRING_LIST)
|
||||
custom = &str_list;
|
||||
else
|
||||
custom = NULL;
|
||||
if (!(last = _tok_value(rh, ft, field_num, implicit,
|
||||
last, &vs, &ve, &flags,
|
||||
&rvw, rh->selection->mem, custom)))
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
/* assign custom structures to hold extra information for specific value types */
|
||||
if (ft->flags == DM_REPORT_FIELD_TYPE_SIZE ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_NUMBER ||
|
||||
ft->flags == DM_REPORT_FIELD_TYPE_PERCENT)
|
||||
custom = &factor;
|
||||
else if (ft->flags & DM_REPORT_FIELD_TYPE_TIME)
|
||||
custom = &tval;
|
||||
else if (ft->flags == DM_REPORT_FIELD_TYPE_STRING_LIST)
|
||||
custom = &str_list;
|
||||
else
|
||||
custom = NULL;
|
||||
|
||||
/* get value to compare with */
|
||||
if (!(last = _tok_value(rh, ft, field_num, implicit,
|
||||
last, &vs, &ve, &flags,
|
||||
&rvw, rh->selection->mem, custom)))
|
||||
goto_bad;
|
||||
|
||||
*next = _skip_space(last);
|
||||
|
||||
/* create selection */
|
||||
@ -4092,7 +4343,7 @@ error:
|
||||
static int _alloc_rh_selection(struct dm_report *rh)
|
||||
{
|
||||
if (!(rh->selection = dm_pool_zalloc(rh->mem, sizeof(struct selection))) ||
|
||||
!(rh->selection->mem = dm_pool_create("report selection", 10 * 1024))) {
|
||||
!(rh->selection->mem = dm_pool_create("report selection", 1024))) {
|
||||
log_error("Failed to allocate report selection structure.");
|
||||
if (rh->selection)
|
||||
dm_pool_free(rh->mem, rh->selection);
|
||||
|
@ -169,7 +169,7 @@ int dm_vasprintf(char **result, const char *format, va_list aq)
|
||||
}
|
||||
|
||||
if (i > 1) {
|
||||
/* Reallocating more then once? */
|
||||
/* Reallocating more than once? */
|
||||
if (!(*result = strdup(buf))) {
|
||||
free(buf);
|
||||
return -1;
|
||||
@ -591,7 +591,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
if ((s < NUM_UNIT_PREFIXES) &&
|
||||
((unit_type == 'R') || (unit_type == 'r'))) {
|
||||
/* When the rounding would cause difference, add '<' prefix
|
||||
* i.e. 2043M is more then 1.9949G prints <2.00G
|
||||
* i.e. 2043M is more than 1.9949G prints <2.00G
|
||||
* This version is for 2 digits fixed precision */
|
||||
d = 100. * (double) size / byte;
|
||||
if (!_close_enough(floorl(d), nearbyintl(d)))
|
||||
|
@ -120,7 +120,7 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
|
||||
if (!(pp = _skip_fields(p, 1)))
|
||||
goto_bad;
|
||||
|
||||
/* Raid target can actually report more then real number of legs in a case
|
||||
/* Raid target can actually report more than real number of legs in a case
|
||||
* raid legs have been removed during initial raid array resynchronization */
|
||||
if (i > (pp - p - 1))
|
||||
i = pp - p - 1;
|
||||
@ -401,12 +401,12 @@ int dm_get_status_integrity(struct dm_pool *mem, const char *params,
|
||||
struct dm_status_integrity **status)
|
||||
{
|
||||
struct dm_status_integrity *s;
|
||||
char recalc_str[16] = "\0";
|
||||
char recalc_str[16] = { 0 };
|
||||
|
||||
if (!(s = dm_pool_zalloc(mem, sizeof(*s))))
|
||||
return_0;
|
||||
|
||||
if (sscanf(params, "%llu %llu %s",
|
||||
if (sscanf(params, "%llu %llu %15s",
|
||||
(unsigned long long *)&s->number_of_mismatches,
|
||||
(unsigned long long *)&s->provided_data_sectors,
|
||||
recalc_str) != 3) {
|
||||
@ -571,7 +571,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
|
||||
pos += used;
|
||||
|
||||
if (num_devs > DM_MIRROR_MAX_IMAGES) {
|
||||
log_error(INTERNAL_ERROR "More then " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
|
||||
log_error(INTERNAL_ERROR "More than " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
|
||||
" reported in mirror status.");
|
||||
goto out;
|
||||
}
|
||||
|
@ -13,6 +13,8 @@
|
||||
# include <linux/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define DM_DIR "mapper" /* Slashes not supported */
|
||||
#define DM_CONTROL_NODE "control"
|
||||
#define DM_MAX_TYPE_NAME 16
|
||||
|
@ -13,7 +13,8 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "dmlib.h"
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include <assert.h>
|
||||
|
||||
struct block {
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#ifdef VALGRIND_POOL
|
||||
#include "memcheck.h"
|
||||
#include <memcheck.h>
|
||||
#endif
|
||||
|
||||
#include "base/memory/zalloc.h"
|
||||
|
@ -356,7 +356,7 @@ struct dm_regex *dm_regex_create(struct dm_pool *mem, const char * const *patter
|
||||
|
||||
for (i = 0; i < num_patterns; i++) {
|
||||
ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i], TARGET_TRANS);
|
||||
if (i < (num_patterns - 1))
|
||||
if ((i + 1) < num_patterns)
|
||||
*ptr++ = '|';
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "parse_rx.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -16,6 +16,8 @@
|
||||
#ifndef _DM_PARSE_REGEX_H
|
||||
#define _DM_PARSE_REGEX_H
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
|
||||
enum {
|
||||
CAT,
|
||||
STAR,
|
||||
|
@ -13,7 +13,6 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "ttree.h"
|
||||
|
||||
struct node {
|
||||
@ -84,9 +83,7 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
|
||||
} while (*c && count);
|
||||
|
||||
if (!*c) {
|
||||
count++;
|
||||
|
||||
while (count--) {
|
||||
do {
|
||||
if (!(*c = _tree_node(tt->mem, k)))
|
||||
return_0;
|
||||
|
||||
@ -94,7 +91,7 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
|
||||
k = *key++;
|
||||
c = &((*c)->m);
|
||||
}
|
||||
}
|
||||
} while (count--);
|
||||
}
|
||||
(*c)->data = data;
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#ifndef _DM_TTREE_H
|
||||
#define _DM_TTREE_H
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
|
||||
struct ttree;
|
||||
|
||||
struct ttree *ttree_create(struct dm_pool *mem, unsigned int klen);
|
||||
|
@ -226,7 +226,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
size = st.st_size;
|
||||
}
|
||||
|
||||
if (read(fh, buffer, sizeof(buffer)) < (MAGIC_NUMBER_SIZE + sizeof(h))) {
|
||||
if (read(fh, buffer, sizeof(buffer)) < (int)(MAGIC_NUMBER_SIZE + sizeof(h))) {
|
||||
log_sys_debug("read", vdo_path);
|
||||
goto err;
|
||||
}
|
||||
@ -270,7 +270,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (read(fh, buffer, sizeof(buffer)) < (sizeof(struct vdo_geometry_block) + sizeof(vn))) {
|
||||
if (read(fh, buffer, sizeof(buffer)) < (int)(sizeof(struct vdo_geometry_block) + sizeof(vn))) {
|
||||
log_sys_debug("read", vdo_path);
|
||||
goto err;
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
|
||||
if ((vtp->minimum_io_size != (512 >> SECTOR_SHIFT)) &&
|
||||
(vtp->minimum_io_size != (4096 >> SECTOR_SHIFT))) {
|
||||
log_error("VDO minimum io size %u is unsupported [512, 4096].",
|
||||
vtp->minimum_io_size);
|
||||
(vtp->minimum_io_size << SECTOR_SHIFT));
|
||||
valid = false;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ List of official [mirror sites](https://sourceware.org/mirrors.html) (including
|
||||
|
||||
### LVM Releases
|
||||
|
||||
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
|
||||
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit="2" show="2" rootpage="release-notes"]]
|
||||
|
||||
[[More releases|release-notes/index]]
|
||||
|
||||
|
@ -21,6 +21,6 @@ Version 2.03.27
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
|
||||
[[!meta date="Wed Oct 2 14:19:23 2024 +0200"]]
|
||||
-->
|
||||
|
||||
|
@ -15,6 +15,6 @@ Few bugfixes and a lot of speed improvements mainly for many LVs.
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
|
||||
[[!meta date="Mon Nov 4 16:42:12 2024 +0100"]]
|
||||
-->
|
||||
|
||||
|
23
doc/release-notes/2.03.29.mdwn
Normal file
23
doc/release-notes/2.03.29.mdwn
Normal file
@ -0,0 +1,23 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.29 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.29
|
||||
===============
|
||||
|
||||
Mostly bugfix release, few interesting changes:
|
||||
|
||||
* **Fix renaming of raid sub LVs when converting a volume to raid (2.03.28)**.
|
||||
* **Fix segfault/VG write error for raid LV `lvextend -i|--stripes -I|--stripesize`**.
|
||||
* Add configure --enable/disable-sd-notify to control lvmlockd build with sd-notify.
|
||||
* Allow test mode when lvmlockd is built without dlm support.
|
||||
* Add a note about RAID + integrity synchronization to lvmraid(7) man page.
|
||||
* Add a function for running lvconvert --repair on RAID LVs to lvmdbusd.
|
||||
* Improve option section of man pages for listing commands ({pv,lv,vg}{s,display}).
|
||||
* And some cleanup mostly in test code.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Mon Dec 09 12:57:57 2024 +0100"]]
|
||||
-->
|
24
doc/release-notes/2.03.30.mdwn
Normal file
24
doc/release-notes/2.03.30.mdwn
Normal file
@ -0,0 +1,24 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.30 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.30
|
||||
===============
|
||||
|
||||
Small bugfix release:
|
||||
|
||||
* **NEW** Create `/dev/disk/by-diskseq/<DISKSEQ>` symlink for public DM devices.
|
||||
* Lvresize reports origin vdo volume cannot be resized.
|
||||
* Support setting `reserved_memory|stack` using `--config` on cmdline.
|
||||
* Fix support for disabling memory locking (2.03.27).
|
||||
* Do not extend an LV if FS resize unsupported and `--fs resize` used.
|
||||
* Prevent leftover temporary device when converting in use volume to a pool.
|
||||
* lvconvert detects volume in use early when converting it to a pool.
|
||||
* Handle NVMe with quirk changed WWID not matching WWID in devices file.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Tue Jan 14 20:55:33 2025 +0100"]]
|
||||
-->
|
||||
|
33
doc/release-notes/2.03.31.mdwn
Normal file
33
doc/release-notes/2.03.31.mdwn
Normal file
@ -0,0 +1,33 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.31 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.31
|
||||
===============
|
||||
|
||||
Bugfix release:
|
||||
|
||||
* Disallow shared activation of LV with CoW snapshot.
|
||||
* Ignore reported `optimal_io_size` not divisible by 4096.
|
||||
* Restore support for `LVM_SUPPRESS_FD_WARNINGS` (2.03.24).
|
||||
* Fix DM cache preserving logic (2.03.28).
|
||||
* Restore missing symbol `dm_tree_node_size_changed@Base` (1.02.175).
|
||||
* Restore missing symbol `dm_bitset_parse_list@@DM_1_02_138` (1.02.175).
|
||||
* Fix uncache and split cache restoring original state of volume.
|
||||
* Extend use of lockopt skip to more scenarios.
|
||||
* Reduce `mandoc -T lint` reported issues for man pages.
|
||||
* Enhance error path resolving in polling code.
|
||||
* Fix lvmlockd use in lvremove of CoW snapshot, VDO pool, and uncache.
|
||||
* Improve mirror split with opened temporary volumes.
|
||||
* Improve pvmove finish with opened temporary volumes.
|
||||
* Fix backup limit for devices file, handle over 10,000 files.
|
||||
* Fix busy-loop in config reading when read returned 0.
|
||||
* Improve use of lvmlockd for usecases involving thin volumes and pools.
|
||||
|
||||
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
|
||||
[[!tag]]
|
||||
<!--
|
||||
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
|
||||
[[!meta date="Thu Feb 27 16:51:29 2025 +0100"]]
|
||||
-->
|
||||
|
||||
|
@ -4,5 +4,5 @@ This list is incomplete, only releases with a release-note are included.
|
||||
|
||||
For releases of stable branch 2.03 see [[index]].
|
||||
|
||||
[[!inline pages="release-notes/2.02.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
|
||||
[[!inline pages="release-notes/2.02.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" rootpage="release-notes"]]
|
||||
|
||||
|
@ -633,6 +633,9 @@
|
||||
/* Define to 1 to include code that uses dbus notification. */
|
||||
#undef NOTIFYDBUS_SUPPORT
|
||||
|
||||
/* Use libnvme for WWID. */
|
||||
#undef NVME_SUPPORT
|
||||
|
||||
/* Define to 1 to enable O_DIRECT support. */
|
||||
#undef O_DIRECT_SUPPORT
|
||||
|
||||
@ -660,6 +663,9 @@
|
||||
/* Define to 1 to include the LVM readline shell. */
|
||||
#undef READLINE_SUPPORT
|
||||
|
||||
/* Define to 1 to include code that uses sd_notify. */
|
||||
#undef SD_NOTIFY_SUPPORT
|
||||
|
||||
/* Define to 1 to include built-in support for snapshots. */
|
||||
#undef SNAPSHOT_INTERNAL
|
||||
|
||||
|
@ -43,6 +43,7 @@ SOURCES =\
|
||||
device/filesystem.c \
|
||||
device/online.c \
|
||||
device/parse_vpd.c \
|
||||
device/nvme.c \
|
||||
device/dev_util.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
@ -142,7 +143,7 @@ LIB_STATIC = $(LIB_NAME).a
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
PROGS_CFLAGS = $(BLKID_CFLAGS) $(UDEV_CFLAGS)
|
||||
PROGS_CFLAGS = $(BLKID_CFLAGS) $(LIBNVME_CFLAGS) $(UDEV_CFLAGS)
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
|
@ -902,7 +902,7 @@ int devno_dm_uuid(struct cmd_context *cmd, int major, int minor,
|
||||
const char *uuid;
|
||||
int r = 0;
|
||||
|
||||
if (major != cmd->dev_types->device_mapper_major)
|
||||
if (major != (int) cmd->dev_types->device_mapper_major)
|
||||
return 0;
|
||||
|
||||
if (dm_devs_cache_use()) {
|
||||
@ -2014,7 +2014,7 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
|
||||
|
||||
if (dm_get_next_target(dmt, NULL, &start, &length,
|
||||
&target_type, ¶ms)) {
|
||||
log_error("More then one table line found for %s.",
|
||||
log_error("More than one table line found for %s.",
|
||||
display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
@ -2067,7 +2067,7 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
|
||||
display_lvname(lv));
|
||||
|
||||
if (dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms)) {
|
||||
log_error("More then one table line found for %s.",
|
||||
log_error("More than one table line found for %s.",
|
||||
display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
@ -2121,7 +2121,7 @@ int dev_manager_vdo_pool_size_config(struct dev_manager *dm,
|
||||
display_lvname(lv));
|
||||
|
||||
if (dm_get_next_target(dmt, NULL, &start, &length, &type, ¶ms)) {
|
||||
log_error("More then one table line found for %s.",
|
||||
log_error("More than one table line found for %s.",
|
||||
display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
@ -2773,9 +2773,10 @@ static int _add_cvol_subdev_to_dtree(struct dev_manager *dm, struct dm_tree *dtr
|
||||
const struct logical_volume *pool_lv = lvseg->pool_lv;
|
||||
struct dm_info info;
|
||||
char *name ,*dlid;
|
||||
union lvid lvid = { { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
|
||||
union lvid lvid = { .id = { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
|
||||
lvid.s[sizeof(lvid.id)] = 0;
|
||||
|
||||
if (!(dlid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&lvid.s, layer)))
|
||||
if (!(dlid = dm_build_dm_uuid(mem, UUID_PREFIX, lvid.s, layer)))
|
||||
return_0;
|
||||
|
||||
/* Name is actually not really needed here, but aids debugging... */
|
||||
@ -3426,9 +3427,10 @@ static int _add_new_cvol_subdev_to_dtree(struct dev_manager *dm,
|
||||
const struct logical_volume *pool_lv = lvseg->pool_lv;
|
||||
struct dm_tree_node *dnode;
|
||||
char *dlid, *dlid_pool, *name;
|
||||
union lvid lvid = { { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
|
||||
union lvid lvid = { .id = { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
|
||||
lvid.s[sizeof(lvid.id)] = 0;
|
||||
|
||||
if (!(dlid = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid.s, layer)))
|
||||
if (!(dlid = dm_build_dm_uuid(dm->mem, UUID_PREFIX, lvid.s, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, pool_lv->name, layer)))
|
||||
|
@ -16,8 +16,12 @@
|
||||
#ifndef _LVM_TARGETS_H
|
||||
#define _LVM_TARGETS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct dev_manager;
|
||||
struct lv_segment;
|
||||
struct dm_tree_node;
|
||||
|
||||
int compose_areas_line(struct dev_manager *dm, struct lv_segment *seg,
|
||||
char *params, size_t paramsize, int *pos,
|
||||
|
121
lib/cache/lvmcache.c
vendored
121
lib/cache/lvmcache.c
vendored
@ -21,7 +21,6 @@
|
||||
#include "lib/device/device_id.h"
|
||||
#include "lib/locking/locking.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/mm/memlock.h"
|
||||
#include "lib/format_text/format-text.h"
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/filters/filter.h"
|
||||
@ -1954,7 +1953,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
|
||||
|
||||
log_warn("WARNING: VG name %s is used by VGs %s and %s.",
|
||||
vgname, vgid_dashed, other_dashed);
|
||||
log_warn("Fix duplicate VG names with vgrename uuid, a device filter, or system IDs.");
|
||||
log_warn("WARNING: fix duplicate VG names with vgrename uuid, or vgrename --devices");
|
||||
}
|
||||
|
||||
if (!vginfo_is_allowed && !other_is_allowed) {
|
||||
@ -2097,12 +2096,17 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
|
||||
vgid = vgname;
|
||||
}
|
||||
|
||||
/* FIXME: remove this, it shouldn't be needed */
|
||||
/* If PV without mdas is already in a real VG, don't make it orphan */
|
||||
if (is_orphan_vg(vgname) && info->vginfo &&
|
||||
mdas_empty_or_ignored(&info->mdas) &&
|
||||
!is_orphan_vg(info->vginfo->vgname) && critical_section())
|
||||
/*
|
||||
* This happens when vgremove does pv_write to make a PV
|
||||
* that was previously part of a VG into a new orphan.
|
||||
* FIXME: change pv_write to not use or update lvmcache,
|
||||
* which should only be updated by label_scan.
|
||||
*/
|
||||
if (is_orphan_vg(vgname) && info->vginfo && !is_orphan_vg(info->vginfo->vgname)) {
|
||||
log_debug("lvmcache change %s to orphan from previous VG %s.",
|
||||
dev_name(info->dev), info->vginfo->vgname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new vginfo struct for this vgname/vgid if none exists,
|
||||
@ -2265,7 +2269,7 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
|
||||
* using the 'vg'.
|
||||
*/
|
||||
|
||||
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
|
||||
void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_claim)
|
||||
{
|
||||
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
@ -2285,9 +2289,11 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vg->name, vgid))) {
|
||||
log_error(INTERNAL_ERROR "lvmcache_update_vg %s no vginfo", vg->name);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
log_debug_cache("lvmcache_update_vg %s vginfo from metadata", vg->name);
|
||||
|
||||
/*
|
||||
* The label scan doesn't know when a PV with old metadata has been
|
||||
* removed from the VG. Now with the vg we can tell, so remove the
|
||||
@ -2326,8 +2332,32 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
|
||||
continue;
|
||||
}
|
||||
|
||||
log_debug_cache("lvmcache_update_vg %s for info %s",
|
||||
vg->name, dev_name(info->dev));
|
||||
/*
|
||||
* If this PV info is already attached to a different VG, don't
|
||||
* override that. The info/vginfo map a PV to a VG based on the
|
||||
* metadata which appears on the PV itself. That has precedence
|
||||
* over a different mapping of PV to another VG (the vg arg here)
|
||||
* which is likely outdated metadata from some other device.
|
||||
*/
|
||||
if (info->vginfo && !is_orphan_vg(info->vginfo->vgname) &&
|
||||
(strcmp(info->vginfo->vgname, vg->name) || memcmp(info->vginfo->vgid, &vg->id, ID_LEN))) {
|
||||
char vgid_old[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
char vgid_new[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
memcpy(vgid_old, &vg->id, ID_LEN);
|
||||
memcpy(vgid_new, info->vginfo->vgid, ID_LEN);
|
||||
|
||||
if (!strcmp(info->vginfo->vgname, vg->name))
|
||||
log_warn("WARNING: PV %s %s belongs to VGID %s, ignoring claim from VGID %s (%s).",
|
||||
dev_name(info->dev), pvid, vgid_new, vgid_old, vg->name);
|
||||
else
|
||||
log_warn("WARNING: PV %s %s belongs to VG %s, ignoring claim from VG %s.",
|
||||
dev_name(info->dev), pvid, info->vginfo->vgname, vg->name);
|
||||
pvl->pv->wrong_vg = 1;
|
||||
*incorrect_pv_claim = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
log_debug_cache("lvmcache_update_vg %s for %s", vg->name, dev_name(info->dev));
|
||||
|
||||
/*
|
||||
* FIXME: use a different function that just attaches info's that
|
||||
@ -2359,8 +2389,6 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3203,6 +3231,73 @@ bool lvmcache_is_outdated_dev(struct cmd_context *cmd,
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Metadata is being processed which shows 'vg' containing 'pv'.
|
||||
* Verify that this is consistent with the headers/metadata that
|
||||
* were scanned from PV. The headers/metadata scanned from the
|
||||
* actual PV could be different from what 'vg' metadata claims,
|
||||
* if the 'vg' metadata is old/outdated.
|
||||
*/
|
||||
|
||||
int lvmcache_verify_info_in_vg(struct volume_group *vg, struct lvmcache_info *info)
|
||||
{
|
||||
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
|
||||
memcpy(vgid, &vg->id, ID_LEN);
|
||||
|
||||
if (!info->dev) {
|
||||
log_error(INTERNAL_ERROR "Verify PV info in %s: skip, no dev", vg->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!info->dev->pvid[0]) {
|
||||
log_debug("Verify PV %s in %s: uncertain, no pvid",
|
||||
dev_name(info->dev), vg->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!info->vginfo) {
|
||||
log_debug("Verify PV %s %s in %s: uncertain, no vginfo",
|
||||
info->dev->pvid, dev_name(info->dev), vg->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(vg->name, info->vginfo->vgname)) {
|
||||
log_debug("Verify PV %s %s in %s: fail, other VG %s",
|
||||
info->dev->pvid, dev_name(info->dev), vg->name, info->vginfo->vgname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp(vgid, info->vginfo->vgid, ID_LEN)) {
|
||||
log_debug("Verify PV %s %s in %s: fail, other vgid %s",
|
||||
info->dev->pvid, dev_name(info->dev), vg->name, info->vginfo->vgid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int lvmcache_verify_pv_in_vg(struct volume_group *vg, struct physical_volume *pv)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
|
||||
memcpy(&pvid, &pv->id.uuid, ID_LEN);
|
||||
|
||||
if (!(info = lvmcache_info_from_pvid(pvid, NULL, 0))) {
|
||||
log_debug("Verify PV %s in %s: skip, no info", pvid, vg->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pv->dev != info->dev) {
|
||||
log_debug("Verify PV %s in %s: skip, different devs", info->dev->pvid, vg->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return lvmcache_verify_info_in_vg(vg, info);
|
||||
}
|
||||
|
||||
const char *dev_filtered_reason(struct device *dev)
|
||||
{
|
||||
if (dev->filtered_flags & DEV_FILTERED_REGEX)
|
||||
|
7
lib/cache/lvmcache.h
vendored
7
lib/cache/lvmcache.h
vendored
@ -83,7 +83,7 @@ void lvmcache_del_dev(struct device *dev);
|
||||
/* Update things */
|
||||
int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info *info,
|
||||
struct lvmcache_vgsummary *vgsummary);
|
||||
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted);
|
||||
void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_claim);
|
||||
|
||||
void lvmcache_lock_vgname(const char *vgname, int read_only);
|
||||
void lvmcache_unlock_vgname(const char *vgname);
|
||||
@ -98,7 +98,7 @@ struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *d
|
||||
struct lvmcache_info *lvmcache_info_from_pv_id(const struct id *pv_id, struct device *dev, int valid_only);
|
||||
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
|
||||
const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgname);
|
||||
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pv_id, uint64_t *label_sector);
|
||||
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
|
||||
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
|
||||
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
|
||||
|
||||
@ -190,6 +190,9 @@ void lvmcache_save_metadata_size(uint64_t val);
|
||||
|
||||
bool lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, const char *vgid, struct device *dev);
|
||||
|
||||
int lvmcache_verify_pv_in_vg(struct volume_group *vg, struct physical_volume *pv);
|
||||
int lvmcache_verify_info_in_vg(struct volume_group *vg, struct lvmcache_info *info);
|
||||
|
||||
void lvmcache_get_outdated_devs(struct cmd_context *cmd,
|
||||
const char *vgname, const char *vgid,
|
||||
struct dm_list *devs);
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
enum {
|
||||
#define cmd(a, b) a ,
|
||||
#include "cmds.h"
|
||||
#include "include/cmds.h"
|
||||
#undef cmd
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "lib/device/dev-cache.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
#include "lib/commands/cmd_enum.h"
|
||||
#include "lib/log/lvm-logging.h"
|
||||
#include "lib/misc/lvm-string.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
@ -163,6 +165,10 @@ struct cmd_context {
|
||||
unsigned vg_read_print_access_error:1; /* print access errors from vg_read */
|
||||
unsigned allow_mixed_block_sizes:1;
|
||||
unsigned force_access_clustered:1;
|
||||
unsigned lockd_creating_thin_pool:1;
|
||||
unsigned lockd_creating_thin_volume:1;
|
||||
unsigned lockd_created_thin_pool:1;
|
||||
unsigned lockd_created_thin_volume:1;
|
||||
unsigned lockd_gl_disable:1;
|
||||
unsigned lockd_vg_disable:1;
|
||||
unsigned lockd_lv_disable:1;
|
||||
|
@ -66,11 +66,16 @@ struct config_source {
|
||||
* Map each ID to respective definition of the configuration item.
|
||||
*/
|
||||
static const struct cfg_def_item _cfg_def_items[CFG_COUNT + 1] = {
|
||||
#define cfg_section(id, name, parent, flags, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_SECTION, {0}, (flags), since_version, {0}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg(id, name, parent, flags, type, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment) {id, parent, name, type, {.v_##type = (default_value)}, (flags), since_version, {.v_UNCONFIGURED = (unconfigured_value)}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_runtime(id, name, parent, flags, type, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, type, {.fn_##type = get_default_##id}, (flags) | CFG_DEFAULT_RUN_TIME, since_version, {.fn_UNCONFIGURED = get_default_unconfigured_##id}, deprecated_since_version, (deprecation_comment), comment},
|
||||
#define cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_ARRAY | (types), {.v_CFG_TYPE_STRING = (default_value)}, (flags), (since_version), {.v_UNCONFIGURED = (unconfigured_value)}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_array_runtime(id, name, parent, flags, types, since_version, deprecated_since_version, deprecation_comment, comment) {id, parent, name, CFG_TYPE_ARRAY | (types), {.fn_CFG_TYPE_STRING = get_default_##id}, (flags) | CFG_DEFAULT_RUN_TIME, (since_version), {.fn_UNCONFIGURED = get_default_unconfigured_##id}, deprecated_since_version, deprecation_comment, comment},
|
||||
#define cfg_section(id, name, parent, flags, since_version, deprecated_since_version, deprecation_comment, comment)\
|
||||
{id, parent, name, CFG_TYPE_SECTION, (flags), since_version, deprecated_since_version, {0}, {0}, deprecation_comment, comment},
|
||||
#define cfg(id, name, parent, flags, type, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment)\
|
||||
{id, parent, name, type, (flags), since_version, deprecated_since_version, {.v_##type = (default_value)}, {.v_UNCONFIGURED = (unconfigured_value)}, deprecation_comment, comment},
|
||||
#define cfg_runtime(id, name, parent, flags, type, since_version, deprecated_since_version, deprecation_comment, comment)\
|
||||
{id, parent, name, type, (flags) | CFG_DEFAULT_RUN_TIME, since_version, deprecated_since_version, {.fn_##type = get_default_##id}, {.fn_UNCONFIGURED = get_default_unconfigured_##id}, (deprecation_comment), comment},
|
||||
#define cfg_array(id, name, parent, flags, types, default_value, since_version, unconfigured_value, deprecated_since_version, deprecation_comment, comment)\
|
||||
{id, parent, name, CFG_TYPE_ARRAY | (types), (flags), (since_version), deprecated_since_version, {.v_CFG_TYPE_STRING = (default_value)}, {.v_UNCONFIGURED = (unconfigured_value)}, deprecation_comment, comment},
|
||||
#define cfg_array_runtime(id, name, parent, flags, types, since_version, deprecated_since_version, deprecation_comment, comment)\
|
||||
{id, parent, name, CFG_TYPE_ARRAY | (types), (flags) | CFG_DEFAULT_RUN_TIME, (since_version), deprecated_since_version, {.fn_CFG_TYPE_STRING = get_default_##id}, {.fn_UNCONFIGURED = get_default_unconfigured_##id},deprecation_comment, comment},
|
||||
#include "lib/config/config_settings.h"
|
||||
#undef cfg_section
|
||||
#undef cfg
|
||||
@ -103,7 +108,7 @@ static inline int _is_file_based_config_source(config_source_t source)
|
||||
*/
|
||||
struct dm_config_tree *config_open(config_source_t source,
|
||||
const char *filename,
|
||||
int unused)
|
||||
int keep_open __attribute__((unused)))
|
||||
{
|
||||
struct dm_config_tree *cft = dm_config_create();
|
||||
struct config_source *cs;
|
||||
@ -520,7 +525,7 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
|
||||
sz = read(dev_fd(dev), buf + rsize, size - rsize);
|
||||
} while ((sz < 0) && ((errno == EINTR) || (errno == EAGAIN)));
|
||||
|
||||
if (sz < 0) {
|
||||
if (sz <= 0) {
|
||||
log_sys_error("read", dev_name(dev));
|
||||
goto out;
|
||||
}
|
||||
@ -927,7 +932,7 @@ static int _check_value_differs_from_default(struct cft_check_handle *handle,
|
||||
case DM_CFG_FLOAT:
|
||||
f = v_def ? v_def->v.f
|
||||
: cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_FLOAT, NULL);
|
||||
diff = fabs(f - v->v.f) < FLT_EPSILON;
|
||||
diff = fabsf(f - v->v.f) < FLT_EPSILON;
|
||||
break;
|
||||
case DM_CFG_STRING:
|
||||
/* string value can be a real string but it can also represent bool */
|
||||
@ -1936,11 +1941,13 @@ int config_write(struct dm_config_tree *cft,
|
||||
.tree_spec = tree_spec,
|
||||
.mem = cft->mem
|
||||
};
|
||||
int free_fp = 1;
|
||||
int r = 1;
|
||||
|
||||
if (!file) {
|
||||
baton.fp = stdout;
|
||||
file = "stdout";
|
||||
free_fp = 0;
|
||||
} else if (!(baton.fp = fopen(file, "w"))) {
|
||||
log_sys_error("open", file);
|
||||
return 0;
|
||||
@ -1971,7 +1978,7 @@ int config_write(struct dm_config_tree *cft,
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (baton.fp && baton.fp != stdout && dm_fclose(baton.fp)) {
|
||||
if (free_fp && baton.fp && dm_fclose(baton.fp)) {
|
||||
stack;
|
||||
r = 0;
|
||||
}
|
||||
|
@ -134,11 +134,11 @@ typedef struct cfg_def_item {
|
||||
int parent; /* ID of parent item */
|
||||
const char *name; /* name of the item in configuration tree */
|
||||
int type; /* configuration item type (bits of cfg_def_type_t) */
|
||||
cfg_def_value_t default_value; /* default value (only for settings) */
|
||||
uint16_t flags; /* configuration item definition flags */
|
||||
uint16_t since_version; /* version this item appeared in */
|
||||
cfg_def_unconfigured_value_t default_unconfigured_value; /* default value in terms of @FOO@, pre-configured (only for settings) */
|
||||
uint16_t deprecated_since_version; /* version since this item is deprecated */
|
||||
cfg_def_value_t default_value; /* default value (only for settings) */
|
||||
cfg_def_unconfigured_value_t default_unconfigured_value; /* default value in terms of @FOO@, pre-configured (only for settings) */
|
||||
const char *deprecation_comment; /* comment about reasons for deprecation and settings that supersede this one */
|
||||
const char *comment; /* comment */
|
||||
const char *file_preamble; /* comment text to use at the start of the file */
|
||||
@ -243,7 +243,7 @@ struct dm_config_tree *config_open(config_source_t source, const char *filename,
|
||||
int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_reason_t reason,
|
||||
off_t offset, size_t size, off_t offset2, size_t size2,
|
||||
checksum_fn_t checksum_fn, uint32_t checksum,
|
||||
int skip_parse, int no_dup_node_check, int only_pv_summary);
|
||||
int checksum_only, int no_dup_node_check, int only_pv_summary);
|
||||
int config_file_read_from_file(struct dm_config_tree *cft);
|
||||
struct dm_config_tree *config_file_open_and_read(const char *config_file, config_source_t source,
|
||||
struct cmd_context *cmd);
|
||||
|
@ -681,7 +681,7 @@ cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_
|
||||
|
||||
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"
|
||||
"This is slightly less than 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,
|
||||
|
@ -16,7 +16,10 @@
|
||||
#ifndef _LVM_BTREE_H
|
||||
#define _LVM_BTREE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct btree;
|
||||
struct dm_pool;
|
||||
|
||||
struct btree *btree_create(struct dm_pool *mem);
|
||||
|
||||
|
@ -64,7 +64,7 @@ struct block {
|
||||
/*
|
||||
* Ownership of engine passes. Engine will be destroyed even if this fails.
|
||||
*/
|
||||
struct bcache *bcache_create(sector_t block_size, unsigned nr_cache_blocks,
|
||||
struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks,
|
||||
struct io_engine *engine);
|
||||
void bcache_destroy(struct bcache *cache);
|
||||
|
||||
|
@ -871,7 +871,7 @@ static int _insert_dir(const char *dir)
|
||||
if (bsearch(path + 5, _no_scan, DM_ARRAY_SIZE(_no_scan), sizeof(_no_scan[0]),
|
||||
(int (*)(const void*, const void*))strcmp)) {
|
||||
/* Skip insertion of directories that can't have block devices */
|
||||
log_debug("Skipping \"%s\" (no block devices).", path);
|
||||
log_debug_devs("Skipping \"%s\" (no block devices).", path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -1161,12 +1161,12 @@ static int _insert(const char *path, const struct stat *info,
|
||||
}
|
||||
|
||||
if (S_ISLNK(tinfo.st_mode)) {
|
||||
log_debug_devs("%s: Symbolic link to directory", path);
|
||||
log_debug_devs("Skipping \"%s\" (symbolic link to directory).", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info->st_dev != _cache.st_dev) {
|
||||
log_debug_devs("%s: Different filesystem in directory", path);
|
||||
log_debug_devs("Skipping \"%s\" (different filesystem in directory).", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1314,7 +1314,7 @@ int dm_devs_cache_update(void)
|
||||
unsigned devs_features;
|
||||
uint32_t d;
|
||||
struct dm_list *dm_devs_new, *l;
|
||||
int cache_changed = 0;
|
||||
int cache_changed;
|
||||
|
||||
if (!get_dm_active_devices(NULL, &dm_devs_new, &devs_features))
|
||||
return 1;
|
||||
@ -1329,6 +1329,7 @@ int dm_devs_cache_update(void)
|
||||
/* Compare existing cached list with a new one.
|
||||
* When there is any mismatch, just rebuild whole cache */
|
||||
if ((l = dm_list_first(dm_devs_new))) {
|
||||
cache_changed = dm_list_empty(_cache.dm_devs); // 1 for empty cache and new list has entries */
|
||||
dm_list_iterate_items(dm_dev, _cache.dm_devs) {
|
||||
dm_dev_new = dm_list_item(l, struct dm_active_device);
|
||||
if ((dm_dev->devno != dm_dev_new->devno) ||
|
||||
@ -1394,8 +1395,6 @@ void dm_devs_cache_label_invalidate(struct cmd_context *cmd)
|
||||
struct dm_active_device *dm_dev;
|
||||
struct device *dev;
|
||||
|
||||
dm_devs_cache_update();
|
||||
|
||||
dm_list_iterate_items(dm_dev, _cache.dm_devs) {
|
||||
if (dm_dev->uuid &&
|
||||
strncmp(dm_dev->uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1) == 0) {
|
||||
@ -2385,7 +2384,7 @@ static char *_get_devname_from_devno(struct cmd_context *cmd, dev_t devno)
|
||||
static const char _partitions[] = "/proc/partitions";
|
||||
char path[PATH_MAX];
|
||||
char devname[PATH_MAX] = { 0 };
|
||||
char namebuf[NAME_LEN];
|
||||
char namebuf[NAME_LEN + 1];
|
||||
char line[1024];
|
||||
unsigned major = MAJOR(devno);
|
||||
unsigned minor = MINOR(devno);
|
||||
|
@ -487,7 +487,7 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
|
||||
*/
|
||||
holder_name = de->d_name;
|
||||
|
||||
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
|
||||
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.");
|
||||
continue;
|
||||
}
|
||||
@ -595,7 +595,7 @@ static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev,
|
||||
*/
|
||||
lookup:
|
||||
dm_list_iterate_items(dw, &dev->wwids) {
|
||||
if (dw->type == 1 || dw->type == 2 || dw->type == 3)
|
||||
if (dw->scsi_type == 1 || dw->scsi_type == 2 || dw->scsi_type == 3)
|
||||
wwid = &dw->id[4];
|
||||
else
|
||||
wwid = dw->id;
|
||||
@ -615,7 +615,7 @@ lookup:
|
||||
goto lookup;
|
||||
|
||||
if (!(dev->flags & DEV_ADDED_SYS_WWID) && dev_read_sys_wwid(cmd, dev, idbuf, sizeof(idbuf), &dw)) {
|
||||
if (dw->type == 1 || dw->type == 2 || dw->type == 3)
|
||||
if (dw->scsi_type == 1 || dw->scsi_type == 2 || dw->scsi_type == 3)
|
||||
wwid = &dw->id[4];
|
||||
else
|
||||
wwid = dw->id;
|
||||
@ -642,7 +642,7 @@ int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *h
|
||||
/*
|
||||
* multipath only uses SCSI or NVME devices
|
||||
*/
|
||||
if (!major_is_scsi_device(dt, MAJOR(dev->dev)) && !dev_is_nvme(dt, dev))
|
||||
if (!major_is_scsi_device(dt, MAJOR(dev->dev)) && !dev_is_nvme(dev))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
#include "lib/device/device-types.h"
|
||||
#include "lib/device/filesystem.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
@ -23,6 +24,7 @@
|
||||
#include "lib/label/label.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/display/display.h"
|
||||
#include "device_mapper/misc/dm-ioctl.h"
|
||||
|
||||
#ifdef BLKID_WIPING_SUPPORT
|
||||
@ -46,7 +48,7 @@
|
||||
* is excessive and unnecessary compared to just comparing /dev/name*.
|
||||
*/
|
||||
|
||||
int dev_is_nvme(struct dev_types *dt, struct device *dev)
|
||||
int dev_is_nvme(struct device *dev)
|
||||
{
|
||||
return (dev->flags & DEV_IS_NVME) ? 1 : 0;
|
||||
}
|
||||
@ -106,7 +108,7 @@ int dev_is_used_by_active_lv(struct cmd_context *cmd, struct device *dev, int *u
|
||||
* from this name, create path "/dev/dm-1" to run stat on.
|
||||
*/
|
||||
|
||||
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0)
|
||||
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s%s", cmd->dev_dir, holder_name) < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
@ -562,7 +564,7 @@ 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 (dev_is_nvme(dev)) {
|
||||
/* If this dev is already a partition then it's not partitionable. */
|
||||
if (_has_sys_partition(dev))
|
||||
return 0;
|
||||
@ -790,7 +792,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
|
||||
* 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))
|
||||
if (dev_is_nvme(dev))
|
||||
goto sys_partition;
|
||||
|
||||
/*
|
||||
@ -1378,6 +1380,22 @@ static unsigned long _dev_topology_attribute(struct dev_types *dt,
|
||||
return result;
|
||||
}
|
||||
|
||||
static unsigned long _dev_topology_attribute_4k(struct dev_types *dt,
|
||||
const char *attribute,
|
||||
struct device *dev,
|
||||
unsigned long default_value)
|
||||
{
|
||||
unsigned long result = _dev_topology_attribute(dt, attribute, dev, default_value);
|
||||
|
||||
if ((result > 1) && (result & 0x3)) {
|
||||
log_warn("WARNING: Ignoring %s = %lu for device %s (not divisible by 4KiB).",
|
||||
attribute, result << SECTOR_SHIFT, dev_name(dev));
|
||||
result = 8;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
return _dev_topology_attribute(dt, "alignment_offset", dev, 0UL);
|
||||
@ -1385,12 +1403,12 @@ unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev)
|
||||
|
||||
unsigned long dev_minimum_io_size(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
return _dev_topology_attribute(dt, "queue/minimum_io_size", dev, 0UL);
|
||||
return _dev_topology_attribute_4k(dt, "queue/minimum_io_size", dev, 0UL);
|
||||
}
|
||||
|
||||
unsigned long dev_optimal_io_size(struct dev_types *dt, struct device *dev)
|
||||
{
|
||||
return _dev_topology_attribute(dt, "queue/optimal_io_size", dev, 0UL);
|
||||
return _dev_topology_attribute_4k(dt, "queue/optimal_io_size", dev, 0UL);
|
||||
}
|
||||
|
||||
unsigned long dev_discard_max_bytes(struct dev_types *dt, struct device *dev)
|
||||
|
@ -16,9 +16,10 @@
|
||||
#define _LVM_DEV_TYPE_H
|
||||
|
||||
#include "lib/device/device.h"
|
||||
#include "lib/display/display.h"
|
||||
#include "lib/metadata/metadata-exported.h"
|
||||
#include "lib/label/label.h"
|
||||
#include "lib/device/filesystem.h"
|
||||
|
||||
struct fs_info;
|
||||
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
@ -58,10 +59,10 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev);
|
||||
int major_is_scsi_device(struct dev_types *dt, int major);
|
||||
|
||||
/* Signature/superblock recognition with position returned where found. */
|
||||
int dev_is_md_component(struct cmd_context *cmd, struct device *dev, uint64_t *sb, int full);
|
||||
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *mpath_devno);
|
||||
int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *signature, int full);
|
||||
int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *signature, int full);
|
||||
int dev_is_md_component(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full);
|
||||
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *holder_devno);
|
||||
int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full);
|
||||
int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full);
|
||||
int dasd_is_cdl_formatted(struct device *dev);
|
||||
|
||||
const char *dev_mpath_component_wwid(struct cmd_context *cmd, struct device *dev);
|
||||
@ -98,7 +99,7 @@ int dev_is_rotational(struct dev_types *dt, 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_nvme(struct device *dev);
|
||||
|
||||
int dev_is_lv(struct cmd_context *cmd, struct device *dev);
|
||||
|
||||
|
@ -16,11 +16,11 @@
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/device/device.h"
|
||||
|
||||
int device_id_list_remove(struct dm_list *list, struct device *dev)
|
||||
int device_id_list_remove(struct dm_list *devices, struct device *dev)
|
||||
{
|
||||
struct device_id_list *dil;
|
||||
|
||||
dm_list_iterate_items(dil, list) {
|
||||
dm_list_iterate_items(dil, devices) {
|
||||
if (dil->dev == dev) {
|
||||
dm_list_del(&dil->list);
|
||||
return 1;
|
||||
@ -29,22 +29,22 @@ int device_id_list_remove(struct dm_list *list, struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct device_id_list *device_id_list_find_dev(struct dm_list *list, struct device *dev)
|
||||
struct device_id_list *device_id_list_find_dev(struct dm_list *devices, struct device *dev)
|
||||
{
|
||||
struct device_id_list *dil;
|
||||
|
||||
dm_list_iterate_items(dil, list) {
|
||||
dm_list_iterate_items(dil, devices) {
|
||||
if (dil->dev == dev)
|
||||
return dil;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int device_list_remove(struct dm_list *list, struct device *dev)
|
||||
int device_list_remove(struct dm_list *devices, struct device *dev)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
dm_list_iterate_items(devl, list) {
|
||||
dm_list_iterate_items(devl, devices) {
|
||||
if (devl->dev == dev) {
|
||||
dm_list_del(&devl->list);
|
||||
return 1;
|
||||
@ -53,11 +53,11 @@ int device_list_remove(struct dm_list *list, struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct device_list *device_list_find_dev(struct dm_list *list, struct device *dev)
|
||||
struct device_list *device_list_find_dev(struct dm_list *devices, struct device *dev)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
dm_list_iterate_items(devl, list) {
|
||||
dm_list_iterate_items(devl, devices) {
|
||||
if (devl->dev == dev)
|
||||
return devl;
|
||||
}
|
||||
|
@ -13,6 +13,11 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef LIB_DEVICE_DEVICE_TYPES_H
|
||||
#define LIB_DEVICE_DEVICE_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
const char name[15];
|
||||
const int8_t max_partitions;
|
||||
@ -65,5 +70,8 @@ static const dev_known_type_t _dev_known_types[] = {
|
||||
{"nvme", 64, "NVM Express"},
|
||||
{"zvol", 16, "ZFS Zvols"},
|
||||
{"VxDMP", 16, "Veritas Dynamic Multipathing"},
|
||||
{"zram", 1, "zram block device"},
|
||||
{"", 0, ""}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -16,8 +16,10 @@
|
||||
#ifndef _LVM_DEVICE_H
|
||||
#define _LVM_DEVICE_H
|
||||
|
||||
#include "base/data-struct/list.h"
|
||||
#include "lib/uuid/uuid.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define DEV_REGULAR 0x00000002 /* Regular file? */
|
||||
@ -41,6 +43,8 @@
|
||||
#define DEV_MATCHED_USE_ID 0x00080000 /* matched an entry from cmd->use_devices */
|
||||
#define DEV_SCAN_FOUND_NOLABEL 0x00100000 /* label_scan read, passed filters, but no lvm label */
|
||||
#define DEV_SCAN_NOT_READ 0x00200000 /* label_scan not able to read dev */
|
||||
#define DEV_ADDED_NVME_WWIDS 0x00400000 /* wwids have been ready from libnvme */
|
||||
#define DEV_UPDATE_USE_ID 0x00800000 /* update system.devices entry to use preferred wwid */
|
||||
|
||||
/*
|
||||
* Support for external device info.
|
||||
@ -70,8 +74,12 @@ struct dev_ext {
|
||||
#define DEV_ID_TYPE_WWID_NAA 9
|
||||
#define DEV_ID_TYPE_WWID_EUI 10
|
||||
#define DEV_ID_TYPE_WWID_T10 11
|
||||
/* reserve 12 for "scsi name string" if we decide to add that */
|
||||
#define DEV_ID_TYPE_NVME_EUI64 13
|
||||
#define DEV_ID_TYPE_NVME_NGUID 14
|
||||
#define DEV_ID_TYPE_NVME_UUID 15
|
||||
|
||||
/* Max length of WWID_NAA, WWID_EUI, WWID_T10 */
|
||||
/* Max length of SCSI or NVME WWID */
|
||||
#define DEV_WWID_SIZE 128
|
||||
|
||||
/*
|
||||
@ -79,12 +87,14 @@ struct dev_ext {
|
||||
* /sys/dev/block/%d:%d/device/wwid
|
||||
* /sys/dev/block/%d:%d/wwid
|
||||
* /sys/dev/block/%d:%d/device/vpd_pg83
|
||||
* or libnvme
|
||||
*/
|
||||
|
||||
struct dev_wwid {
|
||||
struct dm_list list; /* dev->wwids */
|
||||
int type; /* 1,2,3 for NAA,EUI,T10 */
|
||||
char id[DEV_WWID_SIZE]; /* includes prefix naa.,eui.,t10. */
|
||||
struct dm_list list; /* dev->wwids */
|
||||
uint16_t scsi_type; /* 1,2,3 for SCSI NAA,EUI,T10 */
|
||||
uint16_t nvme_type; /* 1,2,3 for NVME EUI64,NGUID,UUID */
|
||||
char id[DEV_WWID_SIZE]; /* includes prefix e.g. naa.,eui.,t10. */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -14,8 +14,6 @@
|
||||
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
#include "lib/label/label.h"
|
||||
@ -26,6 +24,7 @@
|
||||
#include "lib/datastruct/str_list.h"
|
||||
#include "lib/metadata/metadata-exported.h"
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/display/display.h"
|
||||
#include "device_mapper/misc/dm-ioctl.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
@ -568,7 +567,7 @@ static int _dev_has_lvmlv_uuid(struct cmd_context *cmd, struct device *dev, char
|
||||
* The numbers 1,2,3 for NAA,EUI,T10 are part of the standard
|
||||
* and are used in the vpd data.
|
||||
*/
|
||||
static int _wwid_type_num(char *id)
|
||||
static int _scsi_wwid_type_num(char *id)
|
||||
{
|
||||
if (!strncmp(id, "naa.", 4))
|
||||
return 3;
|
||||
@ -580,9 +579,9 @@ static int _wwid_type_num(char *id)
|
||||
return 0; /* any unrecognized, non-standard prefix */
|
||||
}
|
||||
|
||||
int wwid_type_to_idtype(int wwid_type)
|
||||
int scsi_type_to_idtype(int scsi_type)
|
||||
{
|
||||
switch (wwid_type) {
|
||||
switch (scsi_type) {
|
||||
case 3: return DEV_ID_TYPE_WWID_NAA;
|
||||
case 2: return DEV_ID_TYPE_WWID_EUI;
|
||||
case 1: return DEV_ID_TYPE_WWID_T10;
|
||||
@ -591,7 +590,7 @@ int wwid_type_to_idtype(int wwid_type)
|
||||
}
|
||||
}
|
||||
|
||||
int idtype_to_wwid_type(int idtype)
|
||||
int idtype_to_scsi_type(int idtype)
|
||||
{
|
||||
switch (idtype) {
|
||||
case DEV_ID_TYPE_WWID_NAA: return 3;
|
||||
@ -602,6 +601,45 @@ int idtype_to_wwid_type(int idtype)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* libnvme only returns the standard identifiers UUID/NGUID/EUI64
|
||||
* sysfs wwid file will return "nvme." identifier when one of the
|
||||
* others is not available.
|
||||
*/
|
||||
static int _nvme_wwid_type_num(char *id)
|
||||
{
|
||||
if (!strncmp(id, "uuid.", 5))
|
||||
return 3; /* UUID is 16 bytes */
|
||||
else if (!strncmp(id, "eui.", 4)) {
|
||||
if (strlen(id) > 15)
|
||||
return 2; /* NGUID is 16 bytes */
|
||||
return 1; /* EUI64 is 8 bytes */
|
||||
}
|
||||
return 0; /* any other prefix, including "nvme.", which must come from sysfs wwid file */
|
||||
}
|
||||
|
||||
int nvme_type_to_idtype(int nvme_type)
|
||||
{
|
||||
switch (nvme_type) {
|
||||
case 3: return DEV_ID_TYPE_NVME_UUID;
|
||||
case 2: return DEV_ID_TYPE_NVME_NGUID;
|
||||
case 1: return DEV_ID_TYPE_NVME_EUI64;
|
||||
case 0: return DEV_ID_TYPE_SYS_WWID;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int idtype_to_nvme_type(int idtype)
|
||||
{
|
||||
switch (idtype) {
|
||||
case DEV_ID_TYPE_NVME_UUID: return 3;
|
||||
case DEV_ID_TYPE_NVME_NGUID: return 2;
|
||||
case DEV_ID_TYPE_NVME_EUI64: return 1;
|
||||
case DEV_ID_TYPE_SYS_WWID: return 0;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void free_wwids(struct dm_list *ids)
|
||||
{
|
||||
struct dev_wwid *dw, *safe;
|
||||
@ -620,22 +658,41 @@ void free_wwids(struct dm_list *ids)
|
||||
* in /etc/multipath/wwids.
|
||||
*/
|
||||
|
||||
struct dev_wwid *dev_add_wwid(char *id, int id_type, struct dm_list *ids)
|
||||
struct dev_wwid *dev_add_wwid(char *id, int dw_type, int is_nvme, struct dm_list *ids)
|
||||
{
|
||||
struct dev_wwid *dw;
|
||||
uint16_t scsi_type = 0;
|
||||
uint16_t nvme_type = 0;
|
||||
|
||||
if (!id_type)
|
||||
id_type = _wwid_type_num(id);
|
||||
if (is_nvme)
|
||||
nvme_type = dw_type ?: _nvme_wwid_type_num(id);
|
||||
else
|
||||
scsi_type = dw_type ?: _scsi_wwid_type_num(id);
|
||||
|
||||
/* nvme_type/scsi_type will be 0 for any sysfs wwid string that
|
||||
doesn't begin with a prefix recognized by lvm, e.g. that
|
||||
comes from sysfs wwid. */
|
||||
|
||||
if (!(dw = zalloc(sizeof(*dw))))
|
||||
return_NULL;
|
||||
/* Copy id string with upto DEV_WWID_SIZE characters */
|
||||
dm_strncpy(dw->id, id, sizeof(dw->id));
|
||||
dw->type = id_type;
|
||||
dw->scsi_type = scsi_type;
|
||||
dw->nvme_type = nvme_type;
|
||||
dm_list_add(ids, &dw->list);
|
||||
return dw;
|
||||
}
|
||||
|
||||
struct dev_wwid *dev_add_scsi_wwid(char *id, int dw_type, struct dm_list *ids)
|
||||
{
|
||||
return dev_add_wwid(id, dw_type, 0, ids);
|
||||
}
|
||||
|
||||
struct dev_wwid *dev_add_nvme_wwid(char *id, int dw_type, struct dm_list *ids)
|
||||
{
|
||||
return dev_add_wwid(id, dw_type, 1, ids);
|
||||
}
|
||||
|
||||
#define VPD_SIZE 4096
|
||||
|
||||
int dev_read_vpd_wwids(struct cmd_context *cmd, struct device *dev)
|
||||
@ -693,9 +750,13 @@ int dev_read_sys_wwid(struct cmd_context *cmd, struct device *dev,
|
||||
else
|
||||
format_general_id((const char *)buf, sizeof(buf), (unsigned char *)outbuf, outbufsize);
|
||||
|
||||
/* We don't currently add the sysfs wwid to dev->wwids for nvme, it's not needed. */
|
||||
if (dev_is_nvme(dev))
|
||||
return 1;
|
||||
|
||||
/* Note, if wwids are also read from vpd, this same wwid will be added again. */
|
||||
|
||||
if (!(dw = dev_add_wwid(buf, 0, &dev->wwids)))
|
||||
if (!(dw = dev_add_wwid(buf, 0, dev_is_nvme(dev), &dev->wwids)))
|
||||
return_0;
|
||||
if (dw_out)
|
||||
*dw_out = dw;
|
||||
@ -809,7 +870,17 @@ char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_
|
||||
if (!(dev->flags & DEV_ADDED_VPD_WWIDS))
|
||||
dev_read_vpd_wwids(cmd, dev);
|
||||
dm_list_iterate_items(dw, &dev->wwids) {
|
||||
if (idtype_to_wwid_type(idtype) == dw->type)
|
||||
if (idtype_to_scsi_type(idtype) == dw->scsi_type)
|
||||
return strdup(dw->id);
|
||||
}
|
||||
return NULL;
|
||||
case DEV_ID_TYPE_NVME_EUI64:
|
||||
case DEV_ID_TYPE_NVME_NGUID:
|
||||
case DEV_ID_TYPE_NVME_UUID:
|
||||
if (!(dev->flags & DEV_ADDED_NVME_WWIDS))
|
||||
dev_read_nvme_wwids(dev);
|
||||
dm_list_iterate_items(dw, &dev->wwids) {
|
||||
if (idtype_to_nvme_type(idtype) == dw->nvme_type)
|
||||
return strdup(dw->id);
|
||||
}
|
||||
return NULL;
|
||||
@ -823,6 +894,9 @@ char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_
|
||||
*/
|
||||
if ((idtype != DEV_ID_TYPE_SYS_WWID) &&
|
||||
(idtype != DEV_ID_TYPE_SYS_SERIAL) &&
|
||||
(idtype != DEV_ID_TYPE_NVME_EUI64) &&
|
||||
(idtype != DEV_ID_TYPE_NVME_NGUID) &&
|
||||
(idtype != DEV_ID_TYPE_NVME_UUID) &&
|
||||
(idtype != DEV_ID_TYPE_WWID_NAA) &&
|
||||
(idtype != DEV_ID_TYPE_WWID_EUI) &&
|
||||
(idtype != DEV_ID_TYPE_WWID_T10)) {
|
||||
@ -1043,6 +1117,9 @@ static const char _dev_id_types[][16] = {
|
||||
[DEV_ID_TYPE_WWID_NAA] = "wwid_naa",
|
||||
[DEV_ID_TYPE_WWID_EUI] = "wwid_eui",
|
||||
[DEV_ID_TYPE_WWID_T10] = "wwid_t10",
|
||||
[DEV_ID_TYPE_NVME_EUI64] = "nvme_eui64",
|
||||
[DEV_ID_TYPE_NVME_NGUID] = "nvme_nguid",
|
||||
[DEV_ID_TYPE_NVME_UUID] = "nvme_uuid",
|
||||
};
|
||||
|
||||
static int _is_idtype(uint16_t idtype) {
|
||||
@ -1107,6 +1184,17 @@ static const char *_dev_idname(struct device *dev, uint16_t idtype)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dev_id *get_dev_id(struct device *dev, uint16_t idtype)
|
||||
{
|
||||
struct dev_id *id;
|
||||
|
||||
dm_list_iterate_items(id, &dev->ids) {
|
||||
if (id->idtype == idtype)
|
||||
return id;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _dev_has_id(struct device *dev, uint16_t idtype, const char *idname)
|
||||
{
|
||||
struct dev_id *id;
|
||||
@ -1343,12 +1431,20 @@ int device_ids_read(struct cmd_context *cmd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define BACKUP_NAME_LEN 35
|
||||
#define BACKUP_NAME_SIZE BACKUP_NAME_LEN+1 /* +1 null byte */
|
||||
/*
|
||||
* backup files with version 1-9999 use a 4 digit suffix:
|
||||
* 31 chars + 4 chars (zero padded counter) + null byte
|
||||
*
|
||||
* backup files with version >9999:
|
||||
* 31 chars + 5+ chars (uint32 counter, not zero padded, up to 10 chars) + null byte
|
||||
*/
|
||||
#define BACKUP_NAME_SIZE 48 /* larger than the longest backup file name */
|
||||
|
||||
static int _filter_backup_files(const struct dirent *de)
|
||||
{
|
||||
if (strlen(de->d_name) != BACKUP_NAME_LEN)
|
||||
int len = strlen(de->d_name);
|
||||
|
||||
if (len < 35 || len > BACKUP_NAME_SIZE-1)
|
||||
return 0;
|
||||
if (strncmp(de->d_name, "system.devices-", 15))
|
||||
return 0;
|
||||
@ -1372,6 +1468,7 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
|
||||
uint32_t low_date = 0, low_time = 0, low_count = 0;
|
||||
uint32_t de_date, de_time, de_count;
|
||||
unsigned int backup_limit = 0, backup_count = 0, remove_count;
|
||||
int namelen;
|
||||
int sort_count;
|
||||
int dir_fd;
|
||||
int i;
|
||||
@ -1392,10 +1489,21 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
|
||||
tm = localtime(tp);
|
||||
strftime(datetime_str, sizeof(datetime_str), "%Y%m%d.%H%M%S", tm);
|
||||
|
||||
/* system.devices-YYYYMMDD.HHMMSS.000N (fixed length 35) */
|
||||
if (dm_snprintf(path, sizeof(path), "%s/devices/backup/system.devices-%s.%04u",
|
||||
cmd->system_dir, datetime_str, df_counter) < 0)
|
||||
goto_out;
|
||||
/* arbitrary max for devicesfile_backup_limit setting */
|
||||
if (backup_limit > 5000)
|
||||
backup_limit = 5000;
|
||||
|
||||
if (df_counter < 10000) {
|
||||
/* system.devices-YYYYMMDD.HHMMSS.NNNN (fixed length 35, uses 4 digit zero padded suffix) */
|
||||
if (dm_snprintf(path, sizeof(path), "%s/devices/backup/system.devices-%s.%04u",
|
||||
cmd->system_dir, datetime_str, df_counter) < 0)
|
||||
goto_out;
|
||||
} else {
|
||||
/* system.devices-YYYYMMDD.HHMMSS.NNNNN... (variable length, suffix has no fixed width) */
|
||||
if (dm_snprintf(path, sizeof(path), "%s/devices/backup/system.devices-%s.%u",
|
||||
cmd->system_dir, datetime_str, df_counter) < 0)
|
||||
goto_out;
|
||||
}
|
||||
|
||||
if (!(fp = fopen(path, "w+"))) {
|
||||
log_warn("WARNING: Failed to create backup file %s", path);
|
||||
@ -1433,7 +1541,10 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
|
||||
while ((de = readdir(dir))) {
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
if (strlen(de->d_name) != BACKUP_NAME_LEN)
|
||||
|
||||
namelen = strlen(de->d_name);
|
||||
|
||||
if (namelen < 35 || namelen > BACKUP_NAME_SIZE-1)
|
||||
continue;
|
||||
|
||||
memset(de_date_str, 0, sizeof(de_date_str));
|
||||
@ -1441,16 +1552,22 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
|
||||
memset(de_count_str, 0, sizeof(de_count_str));
|
||||
|
||||
/*
|
||||
* Save the oldest backup file name.
|
||||
* system.devices-YYYYMMDD.HHMMSS.NNNN
|
||||
* Save the oldest backup file name:
|
||||
*
|
||||
* backup files with version 1-9999 have 4 digit suffix:
|
||||
* system.devices-YYYYMMDD.HHMMSS.NNNN
|
||||
* 12345678901234567890123456789012345 (len 35)
|
||||
* date YYYYMMDD is 8 chars 16-23
|
||||
* time HHMMSS is 6 chars 25-30
|
||||
* count NNNN is 4 chars 32-35
|
||||
*
|
||||
* backup files with version >9999 have
|
||||
* non-zero-padded variable length suffix:
|
||||
* system.devices-YYYYMMDD.HHMMSS.NNNNN...
|
||||
*/
|
||||
memcpy(de_date_str, de->d_name+15, 8);
|
||||
memcpy(de_time_str, de->d_name+24, 6);
|
||||
memcpy(de_count_str, de->d_name+31, 4);
|
||||
memcpy(de_count_str, de->d_name+31, namelen - 31);
|
||||
|
||||
de_date = (uint32_t)strtoul(de_date_str, NULL, 10);
|
||||
de_time = (uint32_t)strtoul(de_time_str, NULL, 10);
|
||||
@ -1488,7 +1605,7 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
|
||||
|
||||
/* Remove the n oldest files by sorting system.devices-*. */
|
||||
setlocale(LC_COLLATE, "C"); /* Avoid sorting by locales */
|
||||
sort_count = scandir(dirpath, &namelist, _filter_backup_files, alphasort);
|
||||
sort_count = scandir(dirpath, &namelist, _filter_backup_files, versionsort);
|
||||
setlocale(LC_COLLATE, "");
|
||||
if (sort_count < 0) {
|
||||
log_warn("WARNING: Failed to sort backup devices files.");
|
||||
@ -1508,6 +1625,7 @@ static void devices_file_backup(struct cmd_context *cmd, char *fc, char *fb, tim
|
||||
free(namelist[i]);
|
||||
}
|
||||
free(namelist);
|
||||
|
||||
out:
|
||||
if (fp && fclose(fp))
|
||||
stack;
|
||||
@ -2564,33 +2682,63 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI:
|
||||
* Make the du match this device if the dev has a vpd_pg83 wwid
|
||||
* that matches du->idname, even if the sysfs wwid for dev did
|
||||
* not match the du->idname. This could happen if sysfs changes
|
||||
* which wwid it reports (there are often multiple), or if lvm in
|
||||
* the future selects a sys_wwid value from vpd_pg83 data rather
|
||||
* than from the sysfs wwid.
|
||||
*
|
||||
* TODO: update the df entry IDTYPE somewhere?
|
||||
*
|
||||
* NVME:
|
||||
* For some nvme drives (faulty hw, flagged with quirk), the sysfs wwid
|
||||
* file changed to reporting a new/correct wwid. The du->idname may
|
||||
* still have the wwid from the old sysfs wwid, so we need to look
|
||||
* at the old wwids that can be found from libnvme.
|
||||
*
|
||||
* device_ids_validate updates system.devices to use the latest value
|
||||
* from sysfs wwid.
|
||||
*
|
||||
* In future, we could limit dev_read_nvme_wwids() to only devices
|
||||
* that have the quirk flag (indicating a bad wwid had been used.)
|
||||
* dev_has_nvme_quirk() checks a flag in a newly exposed sysfs file.
|
||||
* If that sysfs file doesn't exist because of an older kernel, then
|
||||
* the function returns -1. When the quirk file exists and says 0,
|
||||
* then the device hasn't changed its reported sys_wwid value, and
|
||||
* we don't need to check libnvme for other wwids that the dev
|
||||
* might have displayed in the past.
|
||||
*/
|
||||
if (du->idtype == DEV_ID_TYPE_SYS_WWID) {
|
||||
struct dev_wwid *dw;
|
||||
|
||||
if (!(dev->flags & DEV_ADDED_VPD_WWIDS))
|
||||
if (!(dev->flags & DEV_ADDED_VPD_WWIDS) && !dev_is_nvme(dev))
|
||||
dev_read_vpd_wwids(cmd, dev);
|
||||
|
||||
if (!(dev->flags & DEV_ADDED_NVME_WWIDS) && dev_is_nvme(dev))
|
||||
dev_read_nvme_wwids(dev);
|
||||
|
||||
dm_list_iterate_items(dw, &dev->wwids) {
|
||||
if (!strcmp(dw->id, du_idname)) {
|
||||
if (!(id = zalloc(sizeof(struct dev_id))))
|
||||
return_0;
|
||||
/* wwid types are 1,2,3 and idtypes are DEV_ID_TYPE_ */
|
||||
id->idtype = wwid_type_to_idtype(dw->type);
|
||||
/* scsi/nvme types are 1,2,3 and idtypes are DEV_ID_TYPE_ */
|
||||
if (dev_is_nvme(dev))
|
||||
id->idtype = nvme_type_to_idtype(dw->nvme_type);
|
||||
else
|
||||
id->idtype = scsi_type_to_idtype(dw->scsi_type);
|
||||
id->idname = strdup(dw->id);
|
||||
dm_list_add(&dev->ids, &id->list);
|
||||
du->dev = dev;
|
||||
dev->id = id;
|
||||
dev->flags |= DEV_MATCHED_USE_ID;
|
||||
log_debug("Match %s %s to %s: using vpd_pg83 %s %s",
|
||||
|
||||
/* update system.devices with sysfs wwid value since IDTYPE=sys_wwid */
|
||||
/* FIXME: also do this for scsi */
|
||||
if (dev_is_nvme(dev))
|
||||
dev->flags |= DEV_UPDATE_USE_ID;
|
||||
|
||||
log_debug("Match %s %s to %s: using extra %s %s",
|
||||
idtype_to_str(du->idtype), du_idname, dev_name(dev),
|
||||
idtype_to_str(id->idtype), id->idname ?: ".");
|
||||
du->idtype = id->idtype;
|
||||
@ -2939,6 +3087,31 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
du->dev ? dev_name(du->dev) : "not set");
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace old wwid with new value displayed by sysfs wwid.
|
||||
*/
|
||||
dm_list_iterate_items(du, &cmd->use_devices) {
|
||||
if (!du->dev)
|
||||
continue;
|
||||
if (!(du->dev->flags & DEV_UPDATE_USE_ID))
|
||||
continue;
|
||||
if ((id = get_dev_id(du->dev, DEV_ID_TYPE_SYS_WWID)) && id->idname) {
|
||||
log_debug("Validate %s %s PVID %s on %s: replace old wwid with %s",
|
||||
idtype_to_str(du->idtype), du->idname ?: ".", du->pvid ?: ".",
|
||||
dev_name(du->dev), id->idname);
|
||||
if (!(tmpdup = strdup(id->idname)))
|
||||
continue;
|
||||
free(du->idname);
|
||||
du->idtype = DEV_ID_TYPE_SYS_WWID;
|
||||
du->idname = tmpdup;
|
||||
du->dev->id = id;
|
||||
update_file = 1;
|
||||
} else {
|
||||
log_warn("Device %s PVID %s is using only old wwid %s.",
|
||||
dev_name(du->dev), du->pvid ?: ".", du->idname ?: ".");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate entries with proper device id types.
|
||||
* idname is the authority for pairing du and dev.
|
||||
|
@ -16,10 +16,13 @@
|
||||
#ifndef _LVM_DEVICE_ID_H
|
||||
#define _LVM_DEVICE_ID_H
|
||||
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device.h"
|
||||
|
||||
void free_du(struct dev_use *du);
|
||||
void free_dus(struct dm_list *list);
|
||||
void free_dus(struct dm_list *dus);
|
||||
void free_did(struct dev_id *did);
|
||||
void free_dids(struct dm_list *list);
|
||||
void free_dids(struct dm_list *ids);
|
||||
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);
|
||||
@ -69,11 +72,16 @@ int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
|
||||
|
||||
int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, char **idname_out);
|
||||
|
||||
int wwid_type_to_idtype(int wwid_type);
|
||||
int idtype_to_wwid_type(int idtype);
|
||||
int scsi_type_to_idtype(int scsi_type);
|
||||
int nvme_type_to_idtype(int nvme_type);
|
||||
int idtype_to_scsi_type(int idtype);
|
||||
int idtype_to_nvme_type(int idtype);
|
||||
void free_wwids(struct dm_list *ids);
|
||||
struct dev_wwid *dev_add_wwid(char *id, int id_type, struct dm_list *ids);
|
||||
struct dev_wwid *dev_add_wwid(char *id, int dw_type, int is_nvme, struct dm_list *ids);
|
||||
struct dev_wwid *dev_add_scsi_wwid(char *id, int dw_type, struct dm_list *ids);
|
||||
struct dev_wwid *dev_add_nvme_wwid(char *id, int dw_type, struct dm_list *ids);
|
||||
int dev_read_vpd_wwids(struct cmd_context *cmd, struct device *dev);
|
||||
void dev_read_nvme_wwids(struct device *dev);
|
||||
int dev_read_sys_wwid(struct cmd_context *cmd, struct device *dev,
|
||||
char *buf, int bufsize, struct dev_wwid **dw_out);
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
#include "lib/device/filesystem.h"
|
||||
#include "lib/display/display.h"
|
||||
#include "lib/misc/lvm-exec.h"
|
||||
#include "lib/activate/dev_manager.h"
|
||||
|
||||
@ -239,9 +239,9 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l
|
||||
{
|
||||
FILE *fp;
|
||||
char proc_line[PATH_MAX];
|
||||
char proc_fstype[FSTYPE_MAX];
|
||||
char proc_devpath[PATH_MAX];
|
||||
char proc_mntpath[PATH_MAX];
|
||||
char proc_fstype[FSTYPE_MAX + 1];
|
||||
char proc_devpath[PATH_MAX + 1];
|
||||
char proc_mntpath[PATH_MAX + 1];
|
||||
char mtab_mntpath[PATH_MAX] = { 0 };
|
||||
char dm_devpath[PATH_MAX];
|
||||
char tmp_path[PATH_MAX];
|
||||
@ -327,7 +327,7 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l
|
||||
if (sscanf(proc_line, "%"
|
||||
DM_TO_STRING(PATH_MAX) "s %"
|
||||
DM_TO_STRING(PATH_MAX) "s %"
|
||||
DM_TO_STRING(PATH_MAX) "s", proc_devpath, proc_mntpath, proc_fstype) != 3)
|
||||
DM_TO_STRING(FSTYPE_MAX) "s", proc_devpath, proc_mntpath, proc_fstype) != 3)
|
||||
continue;
|
||||
if (strcmp(fstype, proc_fstype))
|
||||
continue;
|
||||
@ -375,8 +375,7 @@ int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *l
|
||||
|
||||
#define FS_CMD_MAX_ARGS 16
|
||||
|
||||
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes_fs)
|
||||
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi)
|
||||
{
|
||||
char crypt_path[PATH_MAX];
|
||||
char newsize_str[16] = { 0 };
|
||||
@ -384,7 +383,7 @@ int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, stru
|
||||
int args = 0;
|
||||
int status;
|
||||
|
||||
if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)newsize_bytes_fs) < 0)
|
||||
if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)fsi->new_size_bytes) < 0)
|
||||
return_0;
|
||||
|
||||
if (dm_snprintf(crypt_path, sizeof(crypt_path), "/dev/dm-%u", MINOR(fsi->crypt_devt)) < 0)
|
||||
@ -420,12 +419,11 @@ int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, stru
|
||||
* if needs_crypt
|
||||
* cryptsetup resize --size $newsize_sectors $cryptpath
|
||||
*
|
||||
* Note: when a crypt layer is included, newsize_bytes_fs is smaller
|
||||
* Note: when a crypt layer is included, new_size_bytes is smaller
|
||||
* than newsize_bytes_lv because of the crypt header.
|
||||
*/
|
||||
|
||||
int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes_fs, char *fsmode)
|
||||
int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, char *fsmode)
|
||||
{
|
||||
char lv_path[PATH_MAX];
|
||||
char crypt_path[PATH_MAX];
|
||||
@ -435,7 +433,7 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
|
||||
int args = 0;
|
||||
int status;
|
||||
|
||||
if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)newsize_bytes_fs) < 0)
|
||||
if (dm_snprintf(newsize_str, sizeof(newsize_str), "%llu", (unsigned long long)fsi->new_size_bytes) < 0)
|
||||
return_0;
|
||||
|
||||
if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", lv->vg->cmd->dev_dir, lv->vg->name, lv->name) < 0)
|
||||
@ -448,7 +446,7 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
|
||||
argv[++args] = "--lvpath";
|
||||
argv[++args] = lv_path;
|
||||
|
||||
if (newsize_bytes_fs) {
|
||||
if (fsi->new_size_bytes) {
|
||||
argv[++args] = "--newsizebytes";
|
||||
argv[++args] = newsize_str;
|
||||
}
|
||||
@ -484,8 +482,8 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
|
||||
devpath = fsi->needs_crypt ? crypt_path : (char *)display_lvname(lv);
|
||||
|
||||
log_print_unless_silent("Reducing file system %s to %s (%llu bytes) on %s...",
|
||||
fsi->fstype, display_size(cmd, newsize_bytes_fs/512),
|
||||
(unsigned long long)newsize_bytes_fs, devpath);
|
||||
fsi->fstype, display_size(cmd, fsi->new_size_bytes/512),
|
||||
(unsigned long long)fsi->new_size_bytes, devpath);
|
||||
|
||||
if (!exec_cmd(cmd, argv, &status, 1)) {
|
||||
log_error("Failed to reduce file system with lvresize_fs_helper.");
|
||||
@ -513,12 +511,12 @@ int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct
|
||||
* if $fstype == "xfs"
|
||||
* xfs_growfs $devpath
|
||||
*
|
||||
* Note: when a crypt layer is included, newsize_bytes_fs is smaller
|
||||
* Note: when a crypt layer is included, new_size_bytes is smaller
|
||||
* than newsize_bytes_lv because of the crypt header.
|
||||
*/
|
||||
|
||||
int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes_fs, char *fsmode)
|
||||
char *fsmode)
|
||||
{
|
||||
char lv_path[PATH_MAX];
|
||||
char crypt_path[PATH_MAX];
|
||||
@ -569,8 +567,8 @@ int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct
|
||||
devpath = fsi->needs_crypt ? crypt_path : (char *)display_lvname(lv);
|
||||
|
||||
log_print_unless_silent("Extending file system %s to %s (%llu bytes) on %s...",
|
||||
fsi->fstype, display_size(cmd, newsize_bytes_fs/512),
|
||||
(unsigned long long)newsize_bytes_fs, devpath);
|
||||
fsi->fstype, display_size(cmd, fsi->new_size_bytes/512),
|
||||
(unsigned long long)fsi->new_size_bytes, devpath);
|
||||
|
||||
if (!exec_cmd(cmd, argv, &status, 1)) {
|
||||
log_error("Failed to extend file system with lvresize_fs_helper.");
|
||||
|
@ -15,6 +15,9 @@
|
||||
#ifndef _FILESYSTEM_H
|
||||
#define _FILESYSTEM_H
|
||||
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device.h"
|
||||
|
||||
#define FSTYPE_MAX 16
|
||||
|
||||
struct fs_info {
|
||||
@ -26,6 +29,7 @@ struct fs_info {
|
||||
uint32_t crypt_offset_bytes; /* offset in bytes of crypt data on LV */
|
||||
dev_t crypt_devt; /* dm-crypt device between the LV and FS */
|
||||
uint64_t crypt_dev_size_bytes;
|
||||
uint64_t new_size_bytes;
|
||||
|
||||
unsigned nofs:1;
|
||||
unsigned unmounted:1;
|
||||
@ -42,12 +46,9 @@ struct fs_info {
|
||||
int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct fs_info *fsi, int include_mount);
|
||||
|
||||
int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes, char *fsmode);
|
||||
int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes, char *fsmode);
|
||||
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes_fs);
|
||||
int fs_extend_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, char *fsmode);
|
||||
int fs_reduce_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi, char *fsmode);
|
||||
int crypt_resize_script(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi);
|
||||
|
||||
int fs_mount_state_is_misnamed(struct cmd_context *cmd, struct logical_volume *lv, char *lv_path, char *fstype);
|
||||
int lv_crypt_is_active(struct cmd_context *cmd, char *lv_path);
|
||||
|
274
lib/device/nvme.c
Normal file
274
lib/device/nvme.c
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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/commands/toolcontext.h"
|
||||
#include "lib/device/device.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef NVME_SUPPORT
|
||||
#include <libnvme.h>
|
||||
|
||||
static int iszero(unsigned char *d, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (d[i])
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _save_uuid(struct device *dev, unsigned char *uuid)
|
||||
{
|
||||
char idname[DEV_WWID_SIZE] = {0};
|
||||
int max, pos, num, i;
|
||||
|
||||
max = sizeof(idname);
|
||||
pos = 0;
|
||||
|
||||
num = snprintf(idname + pos, max - pos, "uuid.");
|
||||
if (num >= max - pos)
|
||||
goto bad;
|
||||
pos += num;
|
||||
|
||||
for (i = 0; i < NVME_UUID_LEN; ++i) {
|
||||
num = snprintf(idname + pos, max - pos, "%02x", uuid[i]);
|
||||
if (num >= max - pos)
|
||||
goto bad;
|
||||
pos += num;
|
||||
|
||||
if (i == 3 || i == 5 || i == 7 || i == 9) {
|
||||
num = snprintf(idname + pos, max - pos, "-");
|
||||
if (num >= max - pos)
|
||||
goto bad;
|
||||
pos += num;
|
||||
}
|
||||
}
|
||||
|
||||
idname[DEV_WWID_SIZE-1] = '\0';
|
||||
|
||||
dev_add_nvme_wwid(idname, 3, &dev->wwids);
|
||||
|
||||
return;
|
||||
bad:
|
||||
log_debug("dev_read_nvme_wwids ignore invalid uuid %s for %s", uuid, dev_name(dev));
|
||||
}
|
||||
|
||||
static void _save_nguid(struct device *dev, unsigned char *nguid)
|
||||
{
|
||||
char idname[DEV_WWID_SIZE] = {0};
|
||||
int max, pos, num, i;
|
||||
|
||||
max = sizeof(idname);
|
||||
pos = 0;
|
||||
|
||||
num = snprintf(idname + pos, max - pos, "eui.");
|
||||
if (num >= max - pos)
|
||||
goto bad;
|
||||
pos += num;
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
num = snprintf(idname + pos, max - pos, "%02x", nguid[i]);
|
||||
if (num >= max - pos)
|
||||
goto bad;
|
||||
pos += num;
|
||||
}
|
||||
|
||||
idname[DEV_WWID_SIZE-1] = '\0';
|
||||
|
||||
dev_add_nvme_wwid(idname, 2, &dev->wwids);
|
||||
|
||||
return;
|
||||
bad:
|
||||
log_debug("dev_read_nvme_wwids ignore invalid nguid %s for %s", nguid, dev_name(dev));
|
||||
}
|
||||
|
||||
static void _save_eui64(struct device *dev, unsigned char *eui64)
|
||||
{
|
||||
char idname[DEV_WWID_SIZE] = {0};
|
||||
int max, pos, num, i;
|
||||
|
||||
max = sizeof(idname);
|
||||
pos = 0;
|
||||
|
||||
num = snprintf(idname + pos, max - pos, "eui.");
|
||||
if (num >= max - pos)
|
||||
goto bad;
|
||||
pos += num;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
num = snprintf(idname + pos, max - pos, "%02x", eui64[i]);
|
||||
if (num >= max - pos)
|
||||
goto bad;
|
||||
pos += num;
|
||||
}
|
||||
|
||||
idname[DEV_WWID_SIZE-1] = '\0';
|
||||
|
||||
dev_add_nvme_wwid(idname, 1, &dev->wwids);
|
||||
|
||||
return;
|
||||
bad:
|
||||
log_debug("dev_read_nvme_wwids ignore invalid eui64 %s for %s", eui64, dev_name(dev));
|
||||
}
|
||||
|
||||
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
|
||||
static void *_nvme_alloc(size_t len)
|
||||
{
|
||||
size_t _len = ROUND_UP(len, 0x1000);
|
||||
void *p;
|
||||
|
||||
if (posix_memalign((void *)&p, getpagesize(), _len))
|
||||
return NULL;
|
||||
|
||||
memset(p, 0, _len);
|
||||
return p;
|
||||
}
|
||||
|
||||
void dev_read_nvme_wwids(struct device *dev)
|
||||
{
|
||||
const char *devpath;
|
||||
unsigned char *data = NULL;
|
||||
struct nvme_id_ns *ns = NULL;
|
||||
struct nvme_id_ctrl *ctrl_id = NULL;
|
||||
unsigned char nguid[16] = {0};
|
||||
unsigned char eui64[8] = {0};
|
||||
unsigned char uuid[NVME_UUID_LEN] = {0};
|
||||
uint32_t nsid = 0;
|
||||
int fd, i, len;
|
||||
|
||||
dev->flags |= DEV_ADDED_NVME_WWIDS;
|
||||
|
||||
/* shouldn't happen */
|
||||
if (dm_list_empty(&dev->aliases))
|
||||
return;
|
||||
|
||||
devpath = dev_name(dev);
|
||||
|
||||
if ((fd = open(devpath, O_RDONLY)) < 0) {
|
||||
log_debug("dev_read_nvme_wwids cannot open %s", devpath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nvme_get_nsid(fd, &nsid)) {
|
||||
log_print("dev_read_nvme_wwids nvme_get_nsid error %d %s", errno, devpath);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(ns = _nvme_alloc(sizeof(*ns))))
|
||||
goto_out;
|
||||
|
||||
if (nvme_identify_ns(fd, nsid, ns)) {
|
||||
log_debug("dev_read_nvme_wwids nvme_identify_ns error %d %s", errno, devpath);
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(nguid, ns->nguid, 16);
|
||||
memcpy(eui64, ns->eui64, 8);
|
||||
|
||||
if (!iszero(nguid, 16))
|
||||
_save_nguid(dev, nguid);
|
||||
if (!iszero(eui64, 8))
|
||||
_save_eui64(dev, eui64);
|
||||
|
||||
if (!(ctrl_id = _nvme_alloc(sizeof(struct nvme_id_ctrl))))
|
||||
goto_out;
|
||||
|
||||
/* Avoid using nvme_identify_ns_descs before ver 1.3. */
|
||||
if (!nvme_identify_ctrl(fd, ctrl_id)) {
|
||||
if (le32_to_cpu(ctrl_id->ver) < 0x10300)
|
||||
goto_out;
|
||||
}
|
||||
|
||||
if (!(data = _nvme_alloc(NVME_IDENTIFY_DATA_SIZE)))
|
||||
goto_out;
|
||||
|
||||
if (nvme_identify_ns_descs(fd, nsid, (struct nvme_ns_id_desc *)data)) {
|
||||
log_debug("dev_read_nvme_wwids nvme_identify_ns_descs error %d %s", errno, devpath);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < NVME_IDENTIFY_DATA_SIZE; i += len) {
|
||||
struct nvme_ns_id_desc *cur = (struct nvme_ns_id_desc *)(data + i);
|
||||
|
||||
if (cur->nidl == 0)
|
||||
break;
|
||||
|
||||
memset(eui64, 0, sizeof(eui64));
|
||||
memset(nguid, 0, sizeof(nguid));
|
||||
memset(uuid, 0, sizeof(uuid));
|
||||
|
||||
switch (cur->nidt) {
|
||||
case NVME_NIDT_EUI64:
|
||||
memcpy(eui64, data + i + sizeof(*cur), sizeof(eui64));
|
||||
len = sizeof(eui64);
|
||||
break;
|
||||
case NVME_NIDT_NGUID:
|
||||
memcpy(nguid, data + i + sizeof(*cur), sizeof(nguid));
|
||||
len = sizeof(nguid);
|
||||
break;
|
||||
case NVME_NIDT_UUID:
|
||||
memcpy(uuid, data + i + sizeof(*cur), NVME_UUID_LEN);
|
||||
len = sizeof(uuid);
|
||||
break;
|
||||
case NVME_NIDT_CSI:
|
||||
len = 1;
|
||||
break;
|
||||
default:
|
||||
len = cur->nidl;
|
||||
break;
|
||||
}
|
||||
|
||||
len += sizeof(*cur);
|
||||
|
||||
if (!iszero(uuid, NVME_UUID_LEN))
|
||||
_save_uuid(dev, uuid);
|
||||
else if (!iszero(nguid, 16))
|
||||
_save_nguid(dev, nguid);
|
||||
else if (!iszero(eui64, 8))
|
||||
_save_eui64(dev, eui64);
|
||||
}
|
||||
out:
|
||||
free(ctrl_id);
|
||||
free(ns);
|
||||
free(data);
|
||||
|
||||
if (close(fd))
|
||||
log_sys_debug("close", devpath);
|
||||
}
|
||||
#else
|
||||
void dev_read_nvme_wwids(struct device *dev)
|
||||
{
|
||||
}
|
||||
#endif
|
@ -14,9 +14,8 @@
|
||||
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device.h"
|
||||
#include "lib/device/online.h"
|
||||
#include "lib/config/defaults.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
|
@ -15,6 +15,9 @@
|
||||
#ifndef _ONLINE_H
|
||||
#define _ONLINE_H
|
||||
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device.h"
|
||||
|
||||
struct pv_online {
|
||||
struct dm_list list;
|
||||
struct device *dev;
|
||||
|
@ -177,7 +177,7 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
|
||||
break;
|
||||
if (id_size >= ID_BUFSIZE)
|
||||
id_size = ID_BUFSIZE - 1;
|
||||
dev_add_wwid(id, 1, ids);
|
||||
dev_add_scsi_wwid(id, 1, ids);
|
||||
break;
|
||||
case 0x2:
|
||||
/* EUI-64 */
|
||||
@ -203,7 +203,7 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
|
||||
break;
|
||||
if (id_size >= ID_BUFSIZE)
|
||||
id_size = ID_BUFSIZE - 1;
|
||||
dev_add_wwid(id, 2, ids);
|
||||
dev_add_scsi_wwid(id, 2, ids);
|
||||
break;
|
||||
case 0x3:
|
||||
/* NAA */
|
||||
@ -225,7 +225,7 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
|
||||
break;
|
||||
if (id_size >= ID_BUFSIZE)
|
||||
id_size = ID_BUFSIZE - 1;
|
||||
dev_add_wwid(id, 3, ids);
|
||||
dev_add_scsi_wwid(id, 3, ids);
|
||||
break;
|
||||
case 0x8:
|
||||
/* SCSI name string */
|
||||
@ -257,7 +257,7 @@ int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list
|
||||
for (i = 0; i < strlen(id); i++)
|
||||
id[i] = tolower(id[i]);
|
||||
}
|
||||
dev_add_wwid(id, type, ids);
|
||||
dev_add_scsi_wwid(id, type, ids);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -934,13 +934,13 @@ void display_name_error(name_error_t name_error)
|
||||
char yes_no_prompt(const char *prompt, ...)
|
||||
{
|
||||
/* Lowercase Yes/No strings */
|
||||
static const char _yes[] = "yes";
|
||||
static const char _no[] = "no";
|
||||
char buf[12] = { 0 };
|
||||
static const char _yes[sizeof(buf)] = "yes";
|
||||
static const char _no[sizeof(buf)] = "no";
|
||||
const char *answer = NULL;
|
||||
int c = silent_mode() ? EOF : 0;
|
||||
int ret = 0, sig = 0;
|
||||
unsigned i = 0;
|
||||
char buf[12];
|
||||
va_list ap;
|
||||
|
||||
sigint_allow();
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "base/data-struct/radix-tree.h"
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/filters/filter.h"
|
||||
#include "lib/config/config.h"
|
||||
|
||||
struct pfilter {
|
||||
struct radix_tree *devices;
|
||||
@ -74,7 +73,7 @@ static void _persistent_filter_wipe(struct cmd_context *cmd, struct dev_filter *
|
||||
_init_hash(pf);
|
||||
} else {
|
||||
dm_list_iterate_items(sl, &dev->aliases)
|
||||
radix_tree_remove(pf->devices, sl->str, strlen(sl->str));
|
||||
(void) radix_tree_remove(pf->devices, sl->str, strlen(sl->str));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/filters/filter.h"
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/activate/activate.h"
|
||||
|
||||
static const char _too_small_to_hold_pv_msg[] = "Too small to hold a PV";
|
||||
|
@ -27,7 +27,7 @@ struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *d
|
||||
struct dev_filter *fwraid_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *mpath_filter_create(struct dev_types *dt);
|
||||
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 *persistent_filter_create(struct dev_types *dt, struct dev_filter *real);
|
||||
struct dev_filter *sysfs_filter_create(const char *sysfs_dir);
|
||||
struct dev_filter *signature_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd);
|
||||
|
@ -219,7 +219,7 @@ static void _remove_expired(const char *dir, const char *vgname,
|
||||
|
||||
sum /= 1024 * 1024;
|
||||
if (sum > 128 || archives_size > 8192)
|
||||
log_print_unless_silent("Consider pruning %s VG archive with more then %u MiB in %u files (see archiving settings in lvm.conf).",
|
||||
log_print_unless_silent("Consider pruning %s VG archive with more than %u MiB in %u files (see archiving settings in lvm.conf).",
|
||||
vgname, (unsigned)sum, archives_size);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ int print_segtype_lvflags(char *buffer, size_t size, uint64_t status);
|
||||
int read_lvflags(uint64_t *status, const char *flags_str);
|
||||
|
||||
int text_vg_export_file(struct volume_group *vg, const char *desc, FILE *fp);
|
||||
size_t text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf, uint32_t *alloc_size);
|
||||
size_t text_vg_export_raw(struct volume_group *vg, const char *desc, char **buf, uint32_t *buf_size);
|
||||
struct volume_group *text_read_metadata_file(struct format_instance *fid,
|
||||
const char *file,
|
||||
time_t *when, char **desc);
|
||||
|
@ -16,6 +16,8 @@
|
||||
#ifndef _LVM_TEXT_EXPORT_H
|
||||
#define _LVM_TEXT_EXPORT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define outsize(args...) do {if (!out_size(args)) return_0;} while (0)
|
||||
#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)
|
||||
|
@ -21,6 +21,7 @@
|
||||
struct dm_hash_table;
|
||||
struct lv_segment;
|
||||
struct dm_config_node;
|
||||
struct dm_config_value;
|
||||
|
||||
int text_import_areas(struct lv_segment *seg, const struct dm_config_node *sn,
|
||||
const struct dm_config_value *cv, uint64_t status);
|
||||
|
@ -141,7 +141,6 @@
|
||||
#include "lib/misc/crc.h"
|
||||
#include "lib/cache/lvmcache.h"
|
||||
#include "lib/device/bcache.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/label/hints.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
|
@ -15,6 +15,8 @@
|
||||
#ifndef _LVM_HINTS_H
|
||||
#define _LVM_HINTS_H
|
||||
|
||||
#include "lib/commands/toolcontext.h"
|
||||
|
||||
struct hint {
|
||||
struct dm_list list;
|
||||
dev_t devt;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user