mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-15 00:23:51 +03:00
Compare commits
5 Commits
dev-dct-lo
...
zkabelac-m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d63165de4b | ||
|
|
7c88012ded | ||
|
|
8d2cb42166 | ||
|
|
bee8c1b921 | ||
|
|
e9605bacde |
@@ -1,7 +1,6 @@
|
||||
stages:
|
||||
- approve
|
||||
- test
|
||||
- post
|
||||
|
||||
approve1:
|
||||
stage: approve
|
||||
@@ -58,7 +57,6 @@ test-job:
|
||||
paths:
|
||||
- test/results/
|
||||
expire_in: 1 week
|
||||
when: always
|
||||
tags:
|
||||
- ${TAG}
|
||||
timeout: 2h
|
||||
@@ -94,10 +92,9 @@ test-job:
|
||||
- rm -rf /dev/shm/lvm2-test
|
||||
- cut -d' ' -f2 test/results/list | sort | uniq -c
|
||||
# Filter artifacts - keep only logs from tests which are not pass
|
||||
- (cd test/results && rm $(grep 'passed$' list | cut -d' ' -f1 | sed -e 's|/|_|g' -e 's|.*|\0.txt|'))
|
||||
- find test/results -type f -empty -delete
|
||||
- cd test/results && rm $(grep 'passed$' list | cut -d' ' -f1 | sed -e 's|/|_|g' -e 's|.*|\0.txt|')
|
||||
# TODO: Keep a list of known failures, and translate into regexp - or simply use python...
|
||||
- if grep failed test/results/list | grep -v '\(dbustest\|lvconvert-mirror\)\.sh' | sort; then false; else true; fi
|
||||
- if grep failed test/results/list | grep -v '\\\(dbustest\|lvconvert-mirror\)\.sh' | sort; then false; else true; fi
|
||||
rules:
|
||||
# Filter only safe repositories, or user in developers:
|
||||
# NOTE: Already done in approve stage, may be more caution than necessary
|
||||
@@ -105,25 +102,3 @@ test-job:
|
||||
when: manual
|
||||
- when: on_success
|
||||
|
||||
# reboot must be configured to let runner finish cleanly while not accepting new jobs
|
||||
# NOTE: If this causes warnings, gitlab-runner needs to be configured to be stopped using SIGQUIT
|
||||
# See: https://docs.gitlab.com/runner/commands/#gitlab-runner-stop-doesnt-shut-down-gracefully
|
||||
# NOTE: It should be possible to use after_script in test job, which runs
|
||||
# before artifacts collection, but reboot may be too eager to stop the job
|
||||
# while collecting artifacts
|
||||
# NOTE: What would happen when there are multiple jobs in the queue for each
|
||||
# tag? Could the tests run first and reboot only after them? I think so!
|
||||
reboot:
|
||||
stage: post
|
||||
parallel:
|
||||
matrix:
|
||||
- TAG: rhel8
|
||||
- TAG: rhel9
|
||||
tags:
|
||||
- ${TAG}
|
||||
timeout: 1m
|
||||
script:
|
||||
- reboot
|
||||
allow_failure: true
|
||||
when: always
|
||||
|
||||
|
||||
@@ -134,7 +134,6 @@ install_system_dirs:
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_LOCK_DIR)
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_RUN_DIR)
|
||||
$(INSTALL_ROOT_DATA) /dev/null $(DESTDIR)$(DEFAULT_CACHE_DIR)/.cache
|
||||
$(INSTALL_ROOT_DIR) $(DESTDIR)/var/lib/lvm
|
||||
|
||||
install_initscripts:
|
||||
$(MAKE) -C scripts install_initscripts
|
||||
@@ -173,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."
|
||||
@@ -195,8 +194,7 @@ ifneq ("$(GENHTML)", "")
|
||||
lcov:
|
||||
$(RM) -rf $(LCOV_REPORTS_DIR)
|
||||
$(MKDIR_P) $(LCOV_REPORTS_DIR)
|
||||
-find . -name '*.gc[dn][ao]' ! -newer make.tmpl -delete
|
||||
-$(LCOV) --capture --directory $(top_builddir) --ignore-errors source,negative,gcov \
|
||||
$(LCOV) --capture --directory $(top_builddir) --ignore-errors source \
|
||||
--output-file $(LCOV_REPORTS_DIR)/out.info
|
||||
-test ! -s $(LCOV_REPORTS_DIR)/out.info || \
|
||||
$(GENHTML) -o $(LCOV_REPORTS_DIR) --ignore-errors source \
|
||||
|
||||
2
README
2
README
@@ -6,8 +6,8 @@ Installation instructions are in INSTALL.
|
||||
There is no warranty - see COPYING and COPYING.LIB.
|
||||
|
||||
Tarballs are available from:
|
||||
https://sourceware.org/pub/lvm2/releases/
|
||||
ftp://sourceware.org/pub/lvm2/
|
||||
https://github.com/lvmteam/lvm2/releases
|
||||
|
||||
The source code is stored in git:
|
||||
https://gitlab.com/lvmteam/lvm2
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.02.211-git (2025-10-24)
|
||||
1.02.203-git (2024-11-04)
|
||||
|
||||
111
WHATS_NEW
111
WHATS_NEW
@@ -1,114 +1,5 @@
|
||||
Version 2.03.37 -
|
||||
Version 2.03.29 -
|
||||
==================
|
||||
Add missing synchronization while converting cachevols.
|
||||
Warn on classic snapshot on raid creation and error on activation + test.
|
||||
Translate udev device paths in lvmdbusd for test environments.
|
||||
Use source='udev' in lvmdbusd to monitor processed udev events.
|
||||
Symlink to /dev nodes when using alternative dev dir to trigger udev.
|
||||
Avoid passing uninitilized buffer in dmeventd to fix valgrind report.
|
||||
Improve lvmdbusd matching of udevd reported device paths.
|
||||
|
||||
Version 2.03.36 - 24th October 2025
|
||||
===================================
|
||||
Fix uninitialized chunk_size_calc_policy in pool parameter functions.
|
||||
Fix approximate allocation for Raid with insufficient extents.
|
||||
Fix race in dmeventd remonitoring optimization (2.03.35).
|
||||
Use -real suffix for pvmove UUID.
|
||||
Add support pvmove segmentation allocation/pvmove_max_segmentation_size_mb.
|
||||
Allow creating _imeta with multiple segments.
|
||||
Fix driver_version() accepts NULL version buffer pointer.
|
||||
Fix invalid free() call in error path of _add_metadata_area_to_pv().
|
||||
Avoid destroying aio context in forked process.
|
||||
Add lvs -o cache_promotions,cache_promotions fields.
|
||||
Update pvmove logic when moving i.e. raid legs.
|
||||
Display integrity info in lvdisplay.
|
||||
Increase storage size for internal filter chain.
|
||||
Add helper function display_mb_size().
|
||||
Enhance code for adding and removing integrity to RAID volumes.
|
||||
Add code for basic validation of integrity segment.
|
||||
Use -real private suffix for integrity origin and meta volumes.
|
||||
Use -real private suffix for mirror and raid legs.
|
||||
Detect and use existing XFS quota mount options for lvresize --fs resize.
|
||||
|
||||
Version 2.03.35 - 09th September 2025
|
||||
=====================================
|
||||
Fix unlocking devices file only after all PVs are processed.
|
||||
Avoid creating system.devices when deleting entries.
|
||||
Fix existing issues with persistent reservations.
|
||||
Fix possible report output format inconsistencies while processing PVs.
|
||||
Allow report options for pv/vg/lvdisplay only if used with -C|--columns.
|
||||
Fix vgsplit failing to split a VG with RAID+integrity or cache with cachevol.
|
||||
Fix --lockopt handling in lvmlockd when --nolocking is used.
|
||||
Optimize dmeventd when remonitoring active devices.
|
||||
|
||||
Version 2.03.34 - 30th July 2025
|
||||
================================
|
||||
Support dmeventd restart when there are no monitored devices.
|
||||
Dmeventd no longer calls 'action commands' on removed devices.
|
||||
Fix reader of VDO metadata on 32bit architecture.
|
||||
Fix lvmdevices --deldev/--delpvid to error out if devices file not writeable.
|
||||
Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
|
||||
Enhanced lvresize -r support for btrfs.
|
||||
Use glibc standard functions htoX, Xtoh functions for endian conversion.
|
||||
Fix structure copying within sanlock's release_rename().
|
||||
Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
|
||||
Add lvmlockd --lockopt repair to reinitialize corrupted sanlock leases.
|
||||
Fix support for lvcreate -T --setautoactivation.
|
||||
Add lvm.conf global/lvresize_fs_helper_executable.
|
||||
Enable lvm to use persistent reservations on a VG.
|
||||
|
||||
Version 2.03.33 - 27th June 2025
|
||||
================================
|
||||
Various spelling, grammar, formatting, test, and build script improvements.
|
||||
Override LC_NUMERIC locale if unsuitable for json_std report format.
|
||||
Repair raid arrays with transiently lost devices.
|
||||
|
||||
Version 2.03.32 - 05th May 2025
|
||||
===============================
|
||||
Lvconvert vdopool conversion properly validates acceptable LVs.
|
||||
Accept thin pool data LV as cacheable 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.
|
||||
Ignore PV claims from old metadata when then PV belongs to a new VG.
|
||||
Fix integrity metadata rounding.
|
||||
Accept --autobackup option in pvresize.
|
||||
|
||||
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).
|
||||
|
||||
38
WHATS_NEW_DM
38
WHATS_NEW_DM
@@ -1,39 +1,5 @@
|
||||
Version 1.02.211 -
|
||||
Version 1.02.203 -
|
||||
===================
|
||||
Dmeventd starts to use mutex per thread.
|
||||
Consolidate dmsetup stats display functions using helper macros.
|
||||
Refactor dmsetup _process_tree_options to use bsearch.
|
||||
|
||||
Version 1.02.210 - 24th October 2025
|
||||
====================================
|
||||
|
||||
Version 1.02.209 - 09th September 2025
|
||||
======================================
|
||||
|
||||
Version 1.02.208 - 30th July 2025
|
||||
=================================
|
||||
|
||||
Version 1.02.207 - 27th June 2025
|
||||
=================================
|
||||
Escape the escape character itself on JSON report format output.
|
||||
Fail dm_report_group_create if radix char from locale unsuitable for JSON_STD.
|
||||
|
||||
Version 1.02.206 - 05th May 2025
|
||||
================================
|
||||
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
|
||||
=====================================
|
||||
@@ -300,7 +266,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 than 31 legs of raid.
|
||||
Use unsigned math when checking more then 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.18.1 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2025 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2021 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-2025 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -456,12 +456,9 @@ 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 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
|
||||
[python python2 python3 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])
|
||||
|
||||
@@ -656,29 +653,15 @@ try:
|
||||
if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
|
||||
can_use_sysconfig = 0
|
||||
except ImportError:
|
||||
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
|
||||
pass"
|
||||
|
||||
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 as in early automake betas. This behavior
|
||||
dnl directory like in previous automake betas. This behavior
|
||||
dnl is more consistent with lispdir.m4 for example.
|
||||
dnl Query sysconfig or distutils (per above) for this directory.
|
||||
dnl Query distutils for this directory.
|
||||
dnl
|
||||
AC_CACHE_CHECK([for $am_display_PYTHON script directory (pythondir)],
|
||||
[am_cv_python_pythondir],
|
||||
@@ -690,11 +673,7 @@ except ImportError:
|
||||
am_cv_python_pythondir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
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'})
|
||||
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')
|
||||
@@ -724,8 +703,7 @@ sys.stdout.write(sitedir)"`
|
||||
|
||||
dnl 3. pyexecdir: directory for installing python extension modules
|
||||
dnl (shared libraries).
|
||||
dnl Query sysconfig or distutils for this directory.
|
||||
dnl Much of this is the same as for prefix setup above.
|
||||
dnl Query distutils for this directory.
|
||||
dnl
|
||||
AC_CACHE_CHECK([for $am_display_PYTHON extension module directory (pyexecdir)],
|
||||
[am_cv_python_pyexecdir],
|
||||
@@ -737,11 +715,7 @@ sys.stdout.write(sitedir)"`
|
||||
am_cv_python_pyexecdir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
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'})
|
||||
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')
|
||||
@@ -792,7 +766,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-2025 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
||||
@@ -191,8 +191,8 @@ static bool _insert_unset(struct radix_tree *rt, struct value *v, const uint8_t
|
||||
v->value = rv;
|
||||
rt->nr_entries++;
|
||||
} else {
|
||||
// prefix -> value (all fields explicitly initialized)
|
||||
struct prefix_chain *pc = malloc(sizeof(*pc) + len);
|
||||
// prefix -> value
|
||||
struct prefix_chain *pc = zalloc(sizeof(*pc) + len);
|
||||
if (!pc)
|
||||
return false;
|
||||
|
||||
@@ -267,8 +267,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const u
|
||||
if (kb[i] != pc->prefix[i])
|
||||
break;
|
||||
|
||||
// All fields of pc2 are explicitly initialized
|
||||
if (!(pc2 = malloc(sizeof(*pc2) + pc->len - i)))
|
||||
if (!(pc2 = zalloc(sizeof(*pc2) + pc->len - i)))
|
||||
return false;
|
||||
pc2->len = pc->len - i;
|
||||
memmove(pc2->prefix, pc->prefix + i, pc2->len);
|
||||
@@ -280,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(pc->child.value.ptr);
|
||||
free(pc2);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -294,7 +293,6 @@ 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--;
|
||||
@@ -445,8 +443,7 @@ static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, c
|
||||
v->value = rv;
|
||||
|
||||
} else {
|
||||
// All fields explicitly initialized
|
||||
struct value_chain *vc = malloc(sizeof(*vc));
|
||||
struct value_chain *vc = zalloc(sizeof(*vc));
|
||||
if (!vc)
|
||||
return false;
|
||||
|
||||
@@ -574,6 +571,22 @@ int radix_tree_uniq_insert(struct radix_tree *rt, const void *key, size_t keylen
|
||||
((entries != rt->nr_entries) ? 1 : -1) : 0;
|
||||
}
|
||||
|
||||
// Note the degrade functions also free the original node.
|
||||
static void _degrade_to_n4(struct node16 *n16, struct value *result)
|
||||
{
|
||||
struct node4 *n4 = zalloc(sizeof(*n4));
|
||||
|
||||
assert(n4 != NULL);
|
||||
|
||||
n4->nr_entries = n16->nr_entries;
|
||||
memcpy(n4->keys, n16->keys, n16->nr_entries * sizeof(*n4->keys));
|
||||
memcpy(n4->values, n16->values, n16->nr_entries * sizeof(*n4->values));
|
||||
free(n16);
|
||||
|
||||
result->type = NODE4;
|
||||
result->value.ptr = n4;
|
||||
}
|
||||
|
||||
static void _degrade_to_n16(struct node48 *n48, struct value *result)
|
||||
{
|
||||
unsigned i, count = 0;
|
||||
@@ -654,10 +667,9 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
|
||||
return true;
|
||||
|
||||
} else if (root->type == VALUE_CHAIN) {
|
||||
// Free value_chain after copying child out
|
||||
vc = root->value.ptr;
|
||||
_dtr(rt, vc->value);
|
||||
*root = vc->child;
|
||||
memcpy(root, &vc->child, sizeof(*root));
|
||||
free(vc);
|
||||
return true;
|
||||
|
||||
@@ -731,9 +743,8 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
|
||||
}
|
||||
|
||||
n16->nr_entries--;
|
||||
if (!n16->nr_entries) {
|
||||
free(n16);
|
||||
root->type = UNSET;
|
||||
if (n16->nr_entries <= 4) {
|
||||
_degrade_to_n4(n16, root);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
@@ -888,10 +899,8 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uin
|
||||
}
|
||||
|
||||
n16->nr_entries--;
|
||||
if (!n16->nr_entries) {
|
||||
free(n16);
|
||||
root->type = UNSET;
|
||||
}
|
||||
if (n16->nr_entries <= 4)
|
||||
_degrade_to_n4(n16, root);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -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 *prefix, size_t prefix_len)
|
||||
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *key, size_t keylen)
|
||||
{
|
||||
const uint8_t *kb = prefix;
|
||||
const uint8_t *ke = kb + prefix_len;
|
||||
const uint8_t *kb = key;
|
||||
const uint8_t *ke = kb + keylen;
|
||||
struct node **pn;
|
||||
unsigned count = 0;
|
||||
unsigned count;
|
||||
|
||||
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: %lu\n", (unsigned long) n->value.n);
|
||||
fprintf(out, "value: %llu\n", n->value.n);
|
||||
} else {
|
||||
fprintf(out, "key: '%c' [0x%02x] %u\n",
|
||||
isprint(n->key) ? n->key : ' ', n->key, indent);
|
||||
|
||||
@@ -37,7 +37,7 @@ config {
|
||||
# checks = 1
|
||||
|
||||
# Configuration option config/validate_metadata.
|
||||
# Allows selecting the level of validation after metadata transformation.
|
||||
# Allows to select the level of validation after metadata transformation.
|
||||
# Validation takes extra CPU time to verify internal consistency.
|
||||
# Accepted values:
|
||||
# full
|
||||
@@ -207,7 +207,7 @@ devices {
|
||||
# device is rejected. Unmatching path names do not affect the accept
|
||||
# or reject decision. If no path names for a device match a pattern,
|
||||
# then the device is accepted. Be careful mixing 'a' and 'r' patterns,
|
||||
# as the combination might produce unexpected results (test changes).
|
||||
# as the combination might produce unexpected results (test changes.)
|
||||
# Run vgscan after changing the filter to regenerate the cache.
|
||||
#
|
||||
# Example
|
||||
@@ -249,7 +249,7 @@ devices {
|
||||
# Configuration option devices/sysfs_scan.
|
||||
# Restrict device scanning to block devices appearing in sysfs.
|
||||
# This is a quick way of filtering out block devices that are not
|
||||
# present on the system. sysfs must be part of the kernel and mounted.
|
||||
# present on the system. sysfs must be part of the kernel and mounted.)
|
||||
# This configuration option has an automatic default value.
|
||||
# sysfs_scan = 1
|
||||
|
||||
@@ -259,7 +259,7 @@ devices {
|
||||
# avoid using PVs that belong to guest images stored on LVs.
|
||||
# When enabled, the LVs scanned should be restricted using the
|
||||
# devices file or the filter. This option does not enable autoactivation
|
||||
# of layered VGs, which requires editing LVM udev rules (see LVM_PVSCAN_ON_LVS).
|
||||
# of layered VGs, which requires editing LVM udev rules (see LVM_PVSCAN_ON_LVS.)
|
||||
# This configuration option has an automatic default value.
|
||||
# scan_lvs = 0
|
||||
|
||||
@@ -337,7 +337,7 @@ devices {
|
||||
# penalty, e.g. MD chunk size. optimal_io_size is the device's
|
||||
# preferred unit of receiving I/O, e.g. MD stripe width.
|
||||
# minimum_io_size is used if optimal_io_size is undefined (0).
|
||||
# If md_chunk_alignment is enabled, it will detect the optimal_io_size.
|
||||
# If md_chunk_alignment is enabled, that detects the optimal_io_size.
|
||||
# default_data_alignment and md_chunk_alignment will be overridden
|
||||
# if they are not aligned with the value detected for this setting.
|
||||
# This setting is overridden by data_alignment and the --dataalignment
|
||||
@@ -497,7 +497,7 @@ allocation {
|
||||
# is not claimed incorrectly by other tools because of old signatures
|
||||
# from previous use. The number of signatures that LVM can detect
|
||||
# depends on the detection code that is selected (see
|
||||
# use_blkid_wiping). Wiping each detected signature must be confirmed.
|
||||
# use_blkid_wiping.) Wiping each detected signature must be confirmed.
|
||||
# When this setting is disabled, signatures on new LVs are not detected
|
||||
# or erased unless the --wipesignatures option is used directly.
|
||||
# This configuration option has an automatic default value.
|
||||
@@ -529,7 +529,7 @@ allocation {
|
||||
# Accepted values:
|
||||
# 0 Automatically detected best available format
|
||||
# 1 Original format
|
||||
# 2 Improved second-generation format
|
||||
# 2 Improved 2nd. generation format
|
||||
#
|
||||
# This configuration option has an automatic default value.
|
||||
# cache_metadata_format = 0
|
||||
@@ -579,26 +579,15 @@ allocation {
|
||||
# Using cache pool with more chunks may degrade cache performance.
|
||||
# This configuration option does not have a default value defined.
|
||||
|
||||
# Configuration option allocation/pvmove_max_segment_size_mb.
|
||||
# Maximum size in MiB of segments to mirror at once during pvmove.
|
||||
# When pvmove needs to move large segments, it will split them into
|
||||
# smaller chunks of this size, mirror each chunk, and update metadata
|
||||
# between chunks. This prevents mirroring excessively large amounts
|
||||
# of data at once. A value of 0 (default) means no limit - the entire
|
||||
# segment will be mirrored at once. Setting this to e.g. 10240 will
|
||||
# limit each mirroring operation to 10GiB chunks.
|
||||
# This configuration option has an automatic default value.
|
||||
# pvmove_max_segment_size_mb = 0
|
||||
|
||||
# Configuration option allocation/thin_pool_metadata_require_separate_pvs.
|
||||
# Thin pool metadata and data will always use different PVs.
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_pool_metadata_require_separate_pvs = 0
|
||||
|
||||
# Configuration option allocation/thin_pool_crop_metadata.
|
||||
# Older versions of lvm2 cropped pool's metadata size to 15.81 GiB.
|
||||
# This is slightly less than the actual maximum 15.88 GiB.
|
||||
# For compatibility with older versions and to use the cropped size, set to 1.
|
||||
# Older version of lvm2 cropped pool's metadata size to 15.81 GiB.
|
||||
# This is slightly less then the actual maximum 15.88 GiB.
|
||||
# For compatibility with older version and use of cropped size set to 1.
|
||||
# This configuration option has an automatic default value.
|
||||
# thin_pool_crop_metadata = 0
|
||||
|
||||
@@ -910,7 +899,7 @@ log {
|
||||
|
||||
# Configuration option log/activation.
|
||||
# Log messages during activation.
|
||||
# Do not use this in low memory situations (can deadlock).
|
||||
# Don't use this in low memory situations (can deadlock).
|
||||
# This configuration option has an automatic default value.
|
||||
# activation = 0
|
||||
|
||||
@@ -1085,7 +1074,7 @@ global {
|
||||
# Additionally, read-only commands that encounter metadata in need of
|
||||
# repair will still be allowed to proceed exactly as if the repair had
|
||||
# been performed (except for the unchanged vg_seqno). Inappropriate
|
||||
# use could corrupt your system, so seek advice first!
|
||||
# use could mess up your system, so seek advice first!
|
||||
# This configuration option has an automatic default value.
|
||||
# metadata_read_only = 0
|
||||
|
||||
@@ -1119,7 +1108,7 @@ global {
|
||||
# Configuration option global/support_mirrored_mirror_log.
|
||||
# Enable mirrored 'mirror' log type for testing.
|
||||
#
|
||||
# This type is deprecated for creation or conversion but can
|
||||
# This type is deprecated to create or convert to but can
|
||||
# be enabled to test that activation of existing mirrored
|
||||
# logs and conversion to disk/core works.
|
||||
#
|
||||
@@ -1219,7 +1208,7 @@ global {
|
||||
# Configuration option global/sanlock_align_size.
|
||||
# The sanlock lease size in MiB to use on disks with a 4K sector size.
|
||||
# Possible values are 1,2,4,8. The default is 8, which supports up to
|
||||
# 2000 hosts (and max host_id 2000). Smaller values support smaller
|
||||
# 2000 hosts (and max host_id 2000.) Smaller values support smaller
|
||||
# numbers of max hosts (and max host_ids): 250, 500, 1000, 2000 for
|
||||
# lease sizes 1,2,4,8. Disks with 512 byte sectors always use 1MiB
|
||||
# leases and support 2000 hosts, and are not affected by this setting.
|
||||
@@ -1229,7 +1218,7 @@ global {
|
||||
# Configuration option global/lvmlockctl_kill_command.
|
||||
# The command that lvmlockctl --kill should use to force LVs offline.
|
||||
# The lvmlockctl --kill command is run when a shared VG has lost
|
||||
# access to locks (e.g. when sanlock has lost access to storage).
|
||||
# access to locks (e.g. when sanlock has lost access to storage.)
|
||||
# An empty string means that there will be no automatic attempt by
|
||||
# lvmlockctl --kill to forcibly shut down LVs in the VG, and the user
|
||||
# can manually intervene as described in lvmlockd(8).
|
||||
@@ -1390,16 +1379,10 @@ global {
|
||||
# This configuration option has an automatic default value.
|
||||
# fsadm_executable = "@FSADM_PATH@"
|
||||
|
||||
# Configuration option global/lvresize_fs_helper_executable.
|
||||
# The full path to the lvresize_fs_helper command.
|
||||
# LVM uses this command to help with filesystem operations during lvresize.
|
||||
# This configuration option has an automatic default value.
|
||||
# lvresize_fs_helper_executable = "@LVRESIZE_FS_HELPER_PATH@"
|
||||
|
||||
# Configuration option global/system_id_source.
|
||||
# The method LVM uses to set the local system ID.
|
||||
# Volume Groups can also be given a system ID (by vgcreate, vgchange,
|
||||
# or vgimport). A VG on shared storage devices is accessible only to
|
||||
# or vgimport.) A VG on shared storage devices is accessible only to
|
||||
# the host with a matching system ID. See 'man lvmsystemid' for
|
||||
# information on limitations and correct usage.
|
||||
#
|
||||
@@ -1743,7 +1726,7 @@ activation {
|
||||
# Configuration option activation/snapshot_autoextend_threshold.
|
||||
# Auto-extend a snapshot when its usage exceeds this percent.
|
||||
# Setting this to 100 disables automatic extension.
|
||||
# The minimum value is 50 (a smaller value is treated as 50).
|
||||
# The minimum value is 50 (a smaller value is treated as 50.)
|
||||
# Also see snapshot_autoextend_percent.
|
||||
# Automatic extension requires dmeventd to be monitoring the LV.
|
||||
#
|
||||
@@ -1773,7 +1756,7 @@ activation {
|
||||
# Configuration option activation/thin_pool_autoextend_threshold.
|
||||
# Auto-extend a thin pool when its usage exceeds this percent.
|
||||
# Setting this to 100 disables automatic extension.
|
||||
# The minimum value is 50 (a smaller value is treated as 50).
|
||||
# The minimum value is 50 (a smaller value is treated as 50.)
|
||||
# Also see thin_pool_autoextend_percent.
|
||||
# Automatic extension requires dmeventd to be monitoring the LV.
|
||||
#
|
||||
@@ -1803,7 +1786,7 @@ activation {
|
||||
# Configuration option activation/vdo_pool_autoextend_threshold.
|
||||
# Auto-extend a VDO pool when its usage exceeds this percent.
|
||||
# Setting this to 100 disables automatic extension.
|
||||
# The minimum value is 50 (a smaller value is treated as 50).
|
||||
# The minimum value is 50 (a smaller value is treated as 50.)
|
||||
# Also see vdo_pool_autoextend_percent.
|
||||
# Automatic extension requires dmeventd to be monitoring the LV.
|
||||
#
|
||||
@@ -2035,7 +2018,7 @@ report {
|
||||
|
||||
# Configuration option report/compact_output.
|
||||
# Do not print empty values for all report fields.
|
||||
# If enabled, all fields that do not have a value set for any of the
|
||||
# If enabled, all fields that don't have a value set for any of the
|
||||
# rows reported are skipped and not printed. Compact output is
|
||||
# applicable only if report/buffered is enabled. If you need to
|
||||
# compact only specified fields, use compact_output=0 and define
|
||||
@@ -2045,7 +2028,7 @@ report {
|
||||
|
||||
# Configuration option report/compact_output_cols.
|
||||
# Do not print empty values for specified report fields.
|
||||
# If defined, specified fields that do not have a value set for any
|
||||
# If defined, specified fields that don't have a value set for any
|
||||
# of the rows reported are skipped and not printed. Compact output
|
||||
# is applicable only if report/buffered is enabled. If you need to
|
||||
# compact all fields, use compact_output=1 instead in which case
|
||||
|
||||
@@ -38,14 +38,6 @@ local {
|
||||
# This configuration option has an automatic default value.
|
||||
# system_id = ""
|
||||
|
||||
# Configuration option local/pr_key.
|
||||
# The local persistent reservation key in hexadecimal.
|
||||
# The value must be unique among all hosts using the same VG.
|
||||
# The max length is 16 hex characters (8 bytes), plus an optional
|
||||
# 0x prefix. If pr_key is not set, host_id will be used to create a key.
|
||||
# This configuration option has an automatic default value.
|
||||
# pr_key = ""
|
||||
|
||||
# Configuration option local/extra_system_ids.
|
||||
# A list of extra VG system IDs the local host can access.
|
||||
# VGs with the system IDs listed here (in addition to the host's own
|
||||
@@ -60,9 +52,7 @@ local {
|
||||
# The sanlock host_id used by lvmlockd. This must be unique among all the hosts
|
||||
# using shared VGs with sanlock. Accepted values are 1-2000, except when sanlock_align_size
|
||||
# is configured to 1, 2 or 4, which correspond to max host_id values of 250, 500, or 1000.
|
||||
# When using persistent reservations, lvm will generate a PR key from the host_id
|
||||
# if pr_key is not defined. All hosts using a sanlock shared VG with PR must use
|
||||
# the same approach for configuring their PR key (pr_key or host_id.)
|
||||
# Applicable only if LVM is compiled with support for lvmlockd+sanlock.
|
||||
# This configuration option has an automatic default value.
|
||||
# host_id = 0
|
||||
}
|
||||
|
||||
330
configure
vendored
330
configure
vendored
@@ -678,7 +678,6 @@ SILENT_RULES
|
||||
SHARED_LINK
|
||||
SELINUX_STATIC_LIBS
|
||||
SELINUX_PC
|
||||
SD_NOTIFY_SUPPORT
|
||||
SBINDIR
|
||||
RT_LIBS
|
||||
PYTHON3DIR
|
||||
@@ -788,8 +787,6 @@ LIBSYSTEMD_LIBS
|
||||
LIBSYSTEMD_CFLAGS
|
||||
UDEV_LIBS
|
||||
UDEV_CFLAGS
|
||||
LIBNVME_LIBS
|
||||
LIBNVME_CFLAGS
|
||||
BLKID_LIBS
|
||||
BLKID_CFLAGS
|
||||
SYSTEMD_RUN_CMD
|
||||
@@ -915,7 +912,6 @@ enable_silent_rules
|
||||
enable_static_link
|
||||
enable_shared
|
||||
with_blkid
|
||||
with_libnvme
|
||||
with_systemd
|
||||
with_udev
|
||||
with_user
|
||||
@@ -975,10 +971,8 @@ 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
|
||||
@@ -1051,8 +1045,6 @@ LIBSEAGATEILM_CFLAGS
|
||||
LIBSEAGATEILM_LIBS
|
||||
BLKID_CFLAGS
|
||||
BLKID_LIBS
|
||||
LIBNVME_CFLAGS
|
||||
LIBNVME_LIBS
|
||||
UDEV_CFLAGS
|
||||
UDEV_LIBS
|
||||
LIBSYSTEMD_CFLAGS
|
||||
@@ -1721,10 +1713,8 @@ 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
|
||||
@@ -1751,7 +1741,6 @@ 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=]
|
||||
@@ -1891,10 +1880,6 @@ 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
|
||||
@@ -9143,16 +9128,6 @@ 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 :
|
||||
@@ -12174,31 +12149,6 @@ printf "%s\n" "$BUILD_LOCKDSANLOCK" >&6; }
|
||||
if test "$BUILD_LOCKDSANLOCK" = "yes"
|
||||
then :
|
||||
|
||||
LOCKDSANLOCK_SUPPORT=370
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.0.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.0.0") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
LOCKDSANLOCK_SUPPORT=400
|
||||
fi
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.1.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.1.0") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
LOCKDSANLOCK_SUPPORT=410
|
||||
fi
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsanlock_client >= 4.2.0\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libsanlock_client >= 4.2.0") 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
LOCKDSANLOCK_SUPPORT=420
|
||||
fi
|
||||
|
||||
pkg_failed=no
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsanlock_client >= 3.7.0" >&5
|
||||
@@ -12291,7 +12241,7 @@ printf "%s\n" "yes" >&6; }
|
||||
BUILD_LVMLOCKD="yes"
|
||||
fi
|
||||
|
||||
printf "%s\n" "#define LOCKDSANLOCK_SUPPORT $LOCKDSANLOCK_SUPPORT" >>confdefs.h
|
||||
printf "%s\n" "#define LOCKDSANLOCK_SUPPORT 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
@@ -12774,18 +12724,9 @@ 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=$?
|
||||
@@ -12873,41 +12814,6 @@ 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.
|
||||
@@ -13223,181 +13129,6 @@ 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; }
|
||||
@@ -13696,11 +13427,7 @@ printf "%s\n" "$BUILD_LVMDBUSD" >&6; }
|
||||
# Check whether --enable-notify-dbus was given.
|
||||
if test ${enable_notify_dbus+y}
|
||||
then :
|
||||
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
|
||||
enableval=$enable_notify_dbus; NOTIFYDBUS_SUPPORT=$enableval
|
||||
fi
|
||||
|
||||
|
||||
@@ -13717,6 +13444,10 @@ 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
|
||||
|
||||
@@ -13728,10 +13459,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" || test "$SD_NOTIFY_SUPPORT" = "yes"
|
||||
if test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"
|
||||
then :
|
||||
|
||||
|
||||
pkg_failed=no
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5
|
||||
printf %s "checking for libsystemd... " >&6; }
|
||||
@@ -13822,6 +13553,7 @@ else
|
||||
printf "%s\n" "yes" >&6; }
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
@@ -14148,21 +13880,7 @@ try:
|
||||
if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
|
||||
can_use_sysconfig = 0
|
||||
except ImportError:
|
||||
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
|
||||
pass"
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory (pythondir)" >&5
|
||||
@@ -14179,11 +13897,7 @@ else case e in #(
|
||||
am_cv_python_pythondir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
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'})
|
||||
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')
|
||||
@@ -14213,7 +13927,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 :
|
||||
@@ -14227,11 +13941,7 @@ else case e in #(
|
||||
am_cv_python_pyexecdir=`$PYTHON -c "
|
||||
$am_python_setup_sysconfig
|
||||
if can_use_sysconfig:
|
||||
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'})
|
||||
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')
|
||||
@@ -14580,7 +14290,7 @@ printf %s "checking whether to compile liblvm2cmd.so... " >&6; }
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CMDLIB" >&5
|
||||
printf "%s\n" "$CMDLIB" >&6; }
|
||||
|
||||
if test "$CMDLIB" = "yes" && test "$SHARED_LINK" = "no"
|
||||
if test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"
|
||||
then :
|
||||
as_fn_error $? "--enable-cmdlib requires dynamic linking." "$LINENO" 5
|
||||
fi
|
||||
@@ -16511,11 +16221,6 @@ LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
|
||||
printf "%s\n" "#define LVRESIZE_FS_HELPER_PATH \"$LVRESIZE_FS_HELPER_PATH\"" >>confdefs.h
|
||||
|
||||
|
||||
LVMPERSIST_PATH="$SBINDIR/lvmpersist"
|
||||
|
||||
printf "%s\n" "#define LVMPERSIST_PATH \"$LVMPERSIST_PATH\"" >>confdefs.h
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
# Check whether --with-dmeventd-pidfile was given.
|
||||
@@ -16859,7 +16564,6 @@ AIO_LIBS=${AIO_LIBS:--laio}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
@@ -18257,9 +17961,3 @@ 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
|
||||
|
||||
|
||||
85
configure.ac
85
configure.ac
@@ -1,3 +1,4 @@
|
||||
###############################################################################
|
||||
## Copyright (C) 2000-2004 Sistina Software, Inc. All rights reserved.
|
||||
## Copyright (C) 2004-2023 Red Hat, Inc. All rights reserved.
|
||||
##
|
||||
@@ -216,8 +217,6 @@ 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])],
|
||||
@@ -934,12 +933,8 @@ AC_MSG_RESULT([$BUILD_LOCKDSANLOCK])
|
||||
|
||||
dnl -- Look for sanlock libraries
|
||||
AS_IF([test "$BUILD_LOCKDSANLOCK" = "yes"], [
|
||||
LOCKDSANLOCK_SUPPORT=370
|
||||
PKG_CHECK_EXISTS(libsanlock_client >= 4.0.0, [LOCKDSANLOCK_SUPPORT=400])
|
||||
PKG_CHECK_EXISTS(libsanlock_client >= 4.1.0, [LOCKDSANLOCK_SUPPORT=410])
|
||||
PKG_CHECK_EXISTS(libsanlock_client >= 4.2.0, [LOCKDSANLOCK_SUPPORT=420])
|
||||
PKG_CHECK_MODULES(LIBSANLOCKCLIENT, libsanlock_client >= 3.7.0, [BUILD_LVMLOCKD="yes"])
|
||||
AC_DEFINE_UNQUOTED([LOCKDSANLOCK_SUPPORT], [$LOCKDSANLOCK_SUPPORT], [Define version of sanlock.])
|
||||
AC_DEFINE([LOCKDSANLOCK_SUPPORT], 1, [Define to 1 to include code that uses lvmlockd sanlock option.])
|
||||
])
|
||||
|
||||
################################################################################
|
||||
@@ -1051,9 +1046,7 @@ 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"]))
|
||||
|
||||
@@ -1089,22 +1082,6 @@ 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,
|
||||
@@ -1162,38 +1139,6 @@ 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])
|
||||
@@ -1286,25 +1231,24 @@ AC_MSG_RESULT([$BUILD_LVMDBUSD])
|
||||
dnl -- Build notifydbus
|
||||
AC_ARG_ENABLE(notify-dbus,
|
||||
[AS_HELP_STRING([--enable-notify-dbus], [enable LVM notification using dbus])],
|
||||
[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])
|
||||
[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"],
|
||||
[AC_DEFINE([NOTIFYDBUS_SUPPORT], 1, [Define to 1 to include code that uses dbus notification.])])
|
||||
[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])
|
||||
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" || test "$SD_NOTIFY_SUPPORT" = "yes"],
|
||||
[PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])])
|
||||
AS_IF([test "$NOTIFYDBUS_SUPPORT" = "yes" || test "$SYSTEMD_JOURNAL_SUPPORT" = "yes" || test "$APP_MACHINEID_SUPPORT" = "yes"], [
|
||||
PKG_CHECK_MODULES(LIBSYSTEMD, [libsystemd])
|
||||
])
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable Python dbus library
|
||||
@@ -1397,7 +1341,7 @@ AS_IF([test "$CMDLIB" != "yes"], [CMDLIB="no" LVM2CMD_LIB=], [LVM2CMD_LIB="-llvm
|
||||
AC_MSG_CHECKING([whether to compile liblvm2cmd.so])
|
||||
AC_MSG_RESULT([$CMDLIB])
|
||||
|
||||
AS_IF([test "$CMDLIB" = "yes" && test "$SHARED_LINK" = "no"],
|
||||
AS_IF([test "$CMDLIB" == "yes" && test "$SHARED_LINK" = "no"],
|
||||
[AC_MSG_ERROR([--enable-cmdlib requires dynamic linking.])])
|
||||
|
||||
|
||||
@@ -1773,9 +1717,6 @@ LIBEXECDIR="$(eval echo $(eval echo $libexecdir))"
|
||||
LVRESIZE_FS_HELPER_PATH="$LIBEXECDIR/lvresize_fs_helper"
|
||||
AC_DEFINE_UNQUOTED(LVRESIZE_FS_HELPER_PATH, ["$LVRESIZE_FS_HELPER_PATH"], [Path to lvresize_fs_helper script.])
|
||||
|
||||
LVMPERSIST_PATH="$SBINDIR/lvmpersist"
|
||||
AC_DEFINE_UNQUOTED(LVMPERSIST_PATH, ["$LVMPERSIST_PATH"], [Path to lvmpersist script.])
|
||||
|
||||
################################################################################
|
||||
dnl -- dmeventd pidfile and executable path
|
||||
AC_ARG_WITH(dmeventd-pidfile,
|
||||
@@ -1997,7 +1938,6 @@ 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)
|
||||
@@ -2135,6 +2075,3 @@ 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!])])
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2025 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of LVM2.
|
||||
*
|
||||
@@ -28,333 +28,121 @@
|
||||
* cov-format-errors --dir cov --html-output html
|
||||
*/
|
||||
|
||||
/* Define NULL for Coverity modeling */
|
||||
#define NULL ((void *)0)
|
||||
|
||||
/* Forward declarations */
|
||||
struct lv_segment;
|
||||
struct logical_volume;
|
||||
struct cmd_context;
|
||||
struct profile;
|
||||
struct dm_pool;
|
||||
struct dm_list;
|
||||
|
||||
/* Partial definition of segment_type - only fields we need for modeling */
|
||||
struct segment_type {
|
||||
const char *name;
|
||||
const char *dso;
|
||||
/* other fields omitted */
|
||||
};
|
||||
|
||||
/*
|
||||
* These functions never return NULL for valid LVs with segments
|
||||
*/
|
||||
struct lv_segment *first_seg(const struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
|
||||
/* Model: assume lv is valid and has at least one segment */
|
||||
if (lv) {
|
||||
__coverity_read_pointee__(lv);
|
||||
return seg;
|
||||
}
|
||||
|
||||
__coverity_panic__(); /* Should never happen in valid code */
|
||||
return ((struct lv_segment **)lv)[0];
|
||||
}
|
||||
|
||||
struct lv_segment *last_seg(const struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
|
||||
if (lv) {
|
||||
__coverity_read_pointee__(lv);
|
||||
return seg;
|
||||
}
|
||||
|
||||
__coverity_panic__();
|
||||
return ((struct lv_segment **)lv)[0];
|
||||
}
|
||||
|
||||
const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile)
|
||||
{
|
||||
char *str;
|
||||
return "STRING";
|
||||
}
|
||||
|
||||
__coverity_read_pointee__(cmd);
|
||||
|
||||
if (str)
|
||||
return str;
|
||||
/*
|
||||
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
|
||||
{
|
||||
if (lv)
|
||||
return lv;
|
||||
|
||||
__coverity_panic__();
|
||||
}
|
||||
*/
|
||||
|
||||
/* simple_memccpy() from glibc */
|
||||
void *memccpy(void *dest, const void *src, int c, size_t n)
|
||||
{
|
||||
const char *s = src;
|
||||
char *d = dest;
|
||||
|
||||
while (n-- > 0)
|
||||
if ((*d++ = *s++) == (char) c)
|
||||
return d;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 2 lines below needs to be placed in coverity/config/user_nodefs.h
|
||||
* Not sure about any other way.
|
||||
* Without them, coverity shows warning since x86 system header files
|
||||
* are using inline assembly to reset fdset
|
||||
*/
|
||||
//#nodef FD_ZERO model_FD_ZERO
|
||||
//void model_FD_ZERO(void *fdset);
|
||||
|
||||
void model_FD_ZERO(void *fdset)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 1024 / 8 / sizeof(long); ++i)
|
||||
((long*)fdset)[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Resent Coverity reports quite weird errors... */
|
||||
int *__errno_location(void)
|
||||
{
|
||||
}
|
||||
const unsigned short **__ctype_b_loc (void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Added extra pointer check to not need these models,
|
||||
* for now just keep then in file
|
||||
*/
|
||||
|
||||
/*
|
||||
struct cmd_context;
|
||||
struct profile;
|
||||
|
||||
const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile *profile)
|
||||
{
|
||||
return "text";
|
||||
}
|
||||
|
||||
const char *find_config_tree_str_allow_empty(struct cmd_context *cmd, int id, struct profile *profile)
|
||||
{
|
||||
char *str;
|
||||
|
||||
__coverity_read_pointee__(cmd);
|
||||
|
||||
if (str)
|
||||
return str;
|
||||
|
||||
__coverity_panic__();
|
||||
return "text";
|
||||
}
|
||||
*/
|
||||
|
||||
struct segment_type *init_unknown_segtype(struct cmd_context *cmd, const char *name)
|
||||
{
|
||||
struct segment_type *seg_type;
|
||||
|
||||
__coverity_read_pointee__(cmd);
|
||||
__coverity_read_pointee__(name);
|
||||
|
||||
if (seg_type)
|
||||
return seg_type;
|
||||
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
/* simple_memccpy() from glibc */
|
||||
void *memccpy(void *dest, const void *src, int c, unsigned long n)
|
||||
{
|
||||
int success;
|
||||
|
||||
__coverity_negative_sink__(n);
|
||||
__coverity_negative_sink__(c);
|
||||
__coverity_tainted_data_transitive__(dest, src);
|
||||
__coverity_write_buffer_bytes__(dest, n);
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* dm_pool_alloc - can return NULL on allocation failure */
|
||||
void *dm_pool_alloc(struct dm_pool *p, unsigned long s)
|
||||
{
|
||||
void *ptr;
|
||||
int success;
|
||||
|
||||
if (!p) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
__coverity_negative_sink__(s); /* Catch negative sizes */
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
ptr = __coverity_alloc__(s);
|
||||
|
||||
/* Mark as escaped - pool memory doesn't need individual free */
|
||||
__coverity_escape__(ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* dm_pool_zalloc - allocates and zeros */
|
||||
void *dm_pool_zalloc(struct dm_pool *p, unsigned long s)
|
||||
{
|
||||
void *ptr;
|
||||
int success;
|
||||
|
||||
if (!p) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
__coverity_negative_sink__(s); /* Catch negative sizes */
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
ptr = __coverity_alloc__(s);
|
||||
__coverity_writeall0__(ptr); /* Memory is zeroed */
|
||||
|
||||
/* Mark as escaped - pool memory doesn't need individual free */
|
||||
__coverity_escape__(ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* dm_pool_strdup - duplicates string in pool */
|
||||
char *dm_pool_strdup(struct dm_pool *p, const char *str)
|
||||
{
|
||||
char *ptr;
|
||||
unsigned long size;
|
||||
int success;
|
||||
|
||||
if (!p || !str) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
__coverity_string_null_sink__(str); /* str must be null-terminated */
|
||||
__coverity_string_size_sink__(str); /* Coverity tracks the size */
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
/* Allocate symbolic size - Coverity will track this appropriately */
|
||||
ptr = __coverity_alloc__(size);
|
||||
__coverity_tainted_data_transitive__(ptr, str);
|
||||
|
||||
/* Mark as escaped - pool memory doesn't need individual free */
|
||||
__coverity_escape__(ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* dm_pool_strndup - duplicates up to n characters */
|
||||
char *dm_pool_strndup(struct dm_pool *p, const char *str, unsigned long n)
|
||||
{
|
||||
char *ptr;
|
||||
int success;
|
||||
|
||||
if (!p) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
__coverity_string_size_source__(str);
|
||||
__coverity_negative_sink__(n);
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
ptr = __coverity_alloc__(n + 1);
|
||||
|
||||
__coverity_tainted_data_transitive__(ptr, str);
|
||||
__coverity_string_null_copy__(ptr, str, n);
|
||||
|
||||
/* Mark as escaped - pool memory doesn't need individual free */
|
||||
__coverity_escape__(ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* dm_pool_free - frees memory back to the pool */
|
||||
void dm_pool_free(struct dm_pool *p, void *ptr)
|
||||
{
|
||||
if (!p || !ptr) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
}
|
||||
|
||||
void dm_pool_empty(struct dm_pool *p)
|
||||
{
|
||||
if (!p) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
}
|
||||
|
||||
/* dm_malloc - standard malloc wrapper */
|
||||
void *dm_malloc_wrapper(unsigned long s, const char *file, int line)
|
||||
{
|
||||
void *ptr;
|
||||
int success;
|
||||
|
||||
__coverity_negative_sink__(s);
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
ptr = __coverity_alloc__(s);
|
||||
|
||||
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* dm_zalloc - standard calloc wrapper */
|
||||
void *dm_zalloc_wrapper(unsigned long s, const char *file, int line)
|
||||
{
|
||||
void *ptr;
|
||||
int success;
|
||||
|
||||
__coverity_negative_sink__(s);
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
ptr = __coverity_alloc__(s);
|
||||
|
||||
__coverity_mark_as_afm_allocated__(ptr, AFM_free);
|
||||
__coverity_writeall0__(ptr);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* dm_free - standard free wrapper */
|
||||
void dm_free_wrapper(void *ptr, const char *file, int line)
|
||||
{
|
||||
if (ptr) {
|
||||
__coverity_free__(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* dm_list_init - initializes a list head */
|
||||
void dm_list_init(struct dm_list *head)
|
||||
{
|
||||
if (head) {
|
||||
__coverity_writeall__(head);
|
||||
}
|
||||
}
|
||||
|
||||
/* dm_list_empty - checks if list is empty (never fails) */
|
||||
int dm_list_empty(const struct dm_list *head)
|
||||
{
|
||||
int is_empty;
|
||||
|
||||
if (head)
|
||||
return is_empty;
|
||||
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
/* dm_list_add - adds to list (never fails) */
|
||||
void dm_list_add(struct dm_list *head, struct dm_list *elem)
|
||||
{
|
||||
if (!head || !elem) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
/* Modification happens, but no failure */
|
||||
__coverity_writeall__(head);
|
||||
__coverity_writeall__(elem);
|
||||
__coverity_escape__(elem);
|
||||
}
|
||||
|
||||
struct segtype_library;
|
||||
|
||||
/* lvm_register_segtype - registers a segment type
|
||||
* Returns 1 on success, 0 on failure
|
||||
* On failure, it calls segtype->ops->destroy(segtype) which frees the resource
|
||||
* On success, the segtype is added to the list and ownership is transferred
|
||||
/*
|
||||
* Until fixed coverity case# 00531860:
|
||||
* A FORWARD_NULL false positive on a recursive function call
|
||||
*
|
||||
* model also these functions:
|
||||
*/
|
||||
int lvm_register_segtype(struct segtype_library *seglib,
|
||||
struct segment_type *segtype)
|
||||
/*
|
||||
const struct dm_config_node;
|
||||
const struct dm_config_node *find_config_tree_array(struct cmd_context *cmd, int id, struct profile *profile)
|
||||
{
|
||||
int success;
|
||||
char *dso;
|
||||
const struct dm_config_node *cn;
|
||||
|
||||
if (!seglib || !segtype) {
|
||||
__coverity_panic__();
|
||||
}
|
||||
|
||||
__coverity_read_pointee__(seglib);
|
||||
__coverity_read_pointee__(segtype);
|
||||
|
||||
if (!success) {
|
||||
/* On failure, the function calls segtype->ops->destroy(segtype)
|
||||
* which frees both segtype->dso and segtype itself */
|
||||
|
||||
/* Read dso field and mark it as freed if it exists */
|
||||
dso = segtype->dso;
|
||||
if (dso)
|
||||
__coverity_free__(dso);
|
||||
|
||||
/* Then free the segtype structure itself */
|
||||
__coverity_free__(segtype);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* On success, segtype is added to the list and ownership transfers */
|
||||
__coverity_escape__(segtype);
|
||||
return 1;
|
||||
return cn;
|
||||
}
|
||||
|
||||
const struct dm_config_node *find_config_tree_node(struct cmd_context *cmd, int id, struct profile *profile)
|
||||
{
|
||||
const struct dm_config_node *cn;
|
||||
|
||||
return cn;
|
||||
}
|
||||
|
||||
int find_config_tree_bool(struct cmd_context *cmd, int id, struct profile *profile)
|
||||
{
|
||||
int b;
|
||||
|
||||
return b;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -197,7 +197,7 @@ int cluster_send(struct clog_request *rq)
|
||||
iov.iov_base = rq;
|
||||
iov.iov_len = sizeof(struct clog_request) + rq->u_rq.data_size;
|
||||
|
||||
rq->u.version[0] = htole64(CLOG_TFR_VERSION);
|
||||
rq->u.version[0] = xlate64(CLOG_TFR_VERSION);
|
||||
rq->u.version[1] = CLOG_TFR_VERSION;
|
||||
|
||||
r = clog_request_to_network(rq);
|
||||
|
||||
@@ -52,19 +52,19 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
|
||||
case DM_ULOG_GET_REGION_SIZE:
|
||||
case DM_ULOG_GET_SYNC_COUNT:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
*pu64 = htole64(*pu64);
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
case DM_ULOG_IS_CLEAN:
|
||||
case DM_ULOG_IN_SYNC:
|
||||
pi64 = (int64_t *)rq->u_rq.data;
|
||||
*pi64 = htole64(*pi64);
|
||||
*pi64 = xlate64(*pi64);
|
||||
break;
|
||||
case DM_ULOG_GET_RESYNC_WORK:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
pi64 = (int64_t *)rq->u_rq.data;
|
||||
pu64 = ((uint64_t *)rq->u_rq.data) + 1;
|
||||
*pi64 = htole64(*pi64);
|
||||
*pu64 = htole64(*pu64);
|
||||
*pi64 = xlate64(*pi64);
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown request type, %u", rq_type);
|
||||
@@ -94,7 +94,7 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
|
||||
case DM_ULOG_IN_SYNC:
|
||||
case DM_ULOG_IS_REMOTE_RECOVERING:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
*pu64 = htole64(*pu64);
|
||||
*pu64 = xlate64(*pu64);
|
||||
break;
|
||||
case DM_ULOG_MARK_REGION:
|
||||
case DM_ULOG_CLEAR_REGION:
|
||||
@@ -102,13 +102,13 @@ static void v5_data_endian_switch(struct clog_request *rq, int to_network __attr
|
||||
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
for (i = 0; i < end; i++)
|
||||
pu64[i] = htole64(pu64[i]);
|
||||
pu64[i] = xlate64(pu64[i]);
|
||||
break;
|
||||
case DM_ULOG_SET_REGION_SYNC:
|
||||
pu64 = (uint64_t *)rq->u_rq.data;
|
||||
pi64 = ((int64_t *)rq->u_rq.data) + 1;
|
||||
*pu64 = htole64(*pu64);
|
||||
*pi64 = htole64(*pi64);
|
||||
*pu64 = xlate64(*pu64);
|
||||
*pi64 = xlate64(*pi64);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown request type, %u", rq_type);
|
||||
@@ -124,15 +124,15 @@ static int v5_endian_to_network(struct clog_request *rq)
|
||||
|
||||
size = sizeof(*rq) + u_rq->data_size;
|
||||
|
||||
u_rq->error = htole32(u_rq->error);
|
||||
u_rq->seq = htole32(u_rq->seq);
|
||||
u_rq->error = xlate32(u_rq->error);
|
||||
u_rq->seq = xlate32(u_rq->seq);
|
||||
|
||||
rq->originator = htole32(rq->originator);
|
||||
rq->originator = xlate32(rq->originator);
|
||||
|
||||
v5_data_endian_switch(rq, 1);
|
||||
|
||||
u_rq->request_type = htole32(u_rq->request_type);
|
||||
u_rq->data_size = htole32(u_rq->data_size);
|
||||
u_rq->request_type = xlate32(u_rq->request_type);
|
||||
u_rq->data_size = xlate32(u_rq->data_size);
|
||||
|
||||
return size;
|
||||
}
|
||||
@@ -142,7 +142,7 @@ int clog_request_to_network(struct clog_request *rq)
|
||||
int r;
|
||||
|
||||
/* FIXME: Remove this safety check */
|
||||
if (rq->u.version[0] != htole64(rq->u.version[1])) {
|
||||
if (rq->u.version[0] != xlate64(rq->u.version[1])) {
|
||||
LOG_ERROR("Programmer error: version[0] must be LE");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -165,12 +165,12 @@ static int v5_endian_from_network(struct clog_request *rq)
|
||||
int size;
|
||||
struct dm_ulog_request *u_rq = &rq->u_rq;
|
||||
|
||||
u_rq->error = htole32(u_rq->error);
|
||||
u_rq->seq = htole32(u_rq->seq);
|
||||
u_rq->request_type = htole32(u_rq->request_type);
|
||||
u_rq->data_size = htole32(u_rq->data_size);
|
||||
u_rq->error = xlate32(u_rq->error);
|
||||
u_rq->seq = xlate32(u_rq->seq);
|
||||
u_rq->request_type = xlate32(u_rq->request_type);
|
||||
u_rq->data_size = xlate32(u_rq->data_size);
|
||||
|
||||
rq->originator = htole32(rq->originator);
|
||||
rq->originator = xlate32(rq->originator);
|
||||
|
||||
size = sizeof(*rq) + u_rq->data_size;
|
||||
|
||||
@@ -182,7 +182,7 @@ static int v5_endian_from_network(struct clog_request *rq)
|
||||
int clog_request_from_network(void *data, size_t data_len)
|
||||
{
|
||||
uint64_t *vp = data;
|
||||
uint64_t version = htole64(vp[0]);
|
||||
uint64_t version = xlate64(vp[0]);
|
||||
struct clog_request *rq = data;
|
||||
|
||||
switch (version) {
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#ifndef _LVM_CLOG_COMPAT_H
|
||||
#define _LVM_CLOG_COMPAT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* The intermachine communication structure version are:
|
||||
* 0: Unused
|
||||
@@ -21,8 +19,6 @@
|
||||
*/
|
||||
#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);
|
||||
|
||||
|
||||
@@ -380,8 +380,8 @@ static int _clog_ctr(char *uuid, uint64_t luid,
|
||||
int disk_log;
|
||||
char disk_path[PATH_MAX] = { 0 };
|
||||
int unlink_path = 0;
|
||||
long ps;
|
||||
size_t pages, page_size;
|
||||
long page_size;
|
||||
int pages;
|
||||
|
||||
/* If core log request, then argv[0] will be region_size */
|
||||
if (!strtoll(argv[0], &p, 0) || *p) {
|
||||
@@ -488,15 +488,14 @@ static int _clog_ctr(char *uuid, uint64_t luid,
|
||||
lc->sync_count = (log_sync == NOSYNC) ? region_count : 0;
|
||||
|
||||
if (disk_log) {
|
||||
if (((ps = sysconf(_SC_PAGESIZE)) <= 0) ||
|
||||
(ps > (1 << 24))) {
|
||||
if ((page_size = sysconf(_SC_PAGESIZE)) < 0) {
|
||||
LOG_ERROR("Unable to read pagesize: %s",
|
||||
strerror(errno));
|
||||
r = errno;
|
||||
goto fail;
|
||||
}
|
||||
page_size = (size_t)ps;
|
||||
pages = (*(lc->clean_bits) + page_size - 1) / page_size;
|
||||
pages = *(lc->clean_bits) / page_size;
|
||||
pages += *(lc->clean_bits) % page_size ? 1 : 0;
|
||||
pages += 1; /* for header */
|
||||
|
||||
r = open(disk_path, O_RDWR | O_DIRECT);
|
||||
|
||||
@@ -326,11 +326,10 @@ static int do_local_work(void *data __attribute__((unused)))
|
||||
*
|
||||
* Returns: 0 on success, -EXXX on failure
|
||||
*/
|
||||
int kernel_send(void *data)
|
||||
int kernel_send(struct dm_ulog_request *u_rq)
|
||||
{
|
||||
int r;
|
||||
uint16_t size;
|
||||
struct dm_ulog_request *u_rq = data;
|
||||
|
||||
if (!u_rq)
|
||||
return -EINVAL;
|
||||
@@ -354,7 +353,7 @@ int kernel_send(void *data)
|
||||
size = sizeof(struct dm_ulog_request);
|
||||
}
|
||||
|
||||
r = kernel_send_helper(data, size);
|
||||
r = kernel_send_helper(u_rq, size);
|
||||
if (r)
|
||||
LOG_ERROR("Failed to send msg to kernel.");
|
||||
|
||||
|
||||
@@ -12,11 +12,9 @@
|
||||
#ifndef _LVM_CLOG_LOCAL_H
|
||||
#define _LVM_CLOG_LOCAL_H
|
||||
|
||||
struct dm_ulog_request;
|
||||
|
||||
int init_local(void);
|
||||
void cleanup_local(void);
|
||||
|
||||
int kernel_send(void *data);
|
||||
int kernel_send(struct dm_ulog_request *rq);
|
||||
|
||||
#endif /* _LVM_CLOG_LOCAL_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,6 @@
|
||||
#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"
|
||||
|
||||
@@ -829,7 +829,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
|
||||
}
|
||||
|
||||
dm_event_handler_set_dso(dmevh, reply_dso);
|
||||
dm_event_handler_set_event_mask(dmevh, (enum dm_event_mask) reply_mask);
|
||||
dm_event_handler_set_event_mask(dmevh, reply_mask);
|
||||
|
||||
free(reply_dso);
|
||||
reply_dso = NULL;
|
||||
@@ -956,13 +956,12 @@ void dm_event_log(const char *subsys, int level, const char *file,
|
||||
prio = LOG_CRIT;
|
||||
}
|
||||
|
||||
/* Serialize to keep lines readable */
|
||||
pthread_mutex_lock(&_log_mutex);
|
||||
|
||||
if (_use_syslog) {
|
||||
/* vsyslog() is thread-safe per POSIX, no mutex needed */
|
||||
vsyslog(prio, format, ap);
|
||||
} else {
|
||||
/* Serialize to keep lines readable */
|
||||
pthread_mutex_lock(&_log_mutex);
|
||||
|
||||
if (_debug_level) {
|
||||
#define _NSEC_PER_SEC (1000000000LL)
|
||||
#ifdef HAVE_REALTIME
|
||||
@@ -989,10 +988,10 @@ void dm_event_log(const char *subsys, int level, const char *file,
|
||||
fprintf(stream, "%28s:%4d %s", file, line, indent);
|
||||
vfprintf(stream, _(format), ap);
|
||||
fputc('\n', stream);
|
||||
(void) fflush(stream);
|
||||
pthread_mutex_unlock(&_log_mutex);
|
||||
fflush(stream);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_log_mutex);
|
||||
|
||||
if (_abort_on_internal_errors < 0)
|
||||
/* Set when env DM_ABORT_ON_INTERNAL_ERRORS is not "0" */
|
||||
|
||||
@@ -29,22 +29,19 @@
|
||||
*/
|
||||
|
||||
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_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_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
|
||||
DM_EVENT_TIMEOUT = 0x020000, /* Timeout has occurred */
|
||||
|
||||
DM_EVENT_REGISTRATION_PENDING = 0x1000000, /* Monitor thread is setting-up/shutting-down */
|
||||
};
|
||||
@@ -73,10 +70,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 dev_name, uuid or
|
||||
* Identify the device to monitor by exactly one of device_name, uuid or
|
||||
* device number. String arguments are duplicated, see above.
|
||||
*/
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name);
|
||||
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
|
||||
|
||||
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "lib/misc/lib.h"
|
||||
#include "dmeventd_lvm.h"
|
||||
#include "daemons/dmeventd/libdevmapper-event.h"
|
||||
#include "lib/metadata/metadata-exported.h" /* MIRROR_SYNC_LAYER */
|
||||
#include "tools/lvm2cmd.h"
|
||||
|
||||
#include <pthread.h>
|
||||
@@ -144,7 +143,7 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
|
||||
}
|
||||
|
||||
/* strip off the mirror component designations */
|
||||
if ((layer = strstr(lv, MIRROR_SYNC_LAYER)) ||
|
||||
if ((layer = strstr(lv, "_mimagetmp")) ||
|
||||
(layer = strstr(lv, "_mlog")))
|
||||
*layer = '\0';
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#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 evmask __attribute__((unused)),
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
struct dso_state *state = *user;
|
||||
|
||||
@@ -84,7 +84,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
|
||||
*/
|
||||
if (!state->warned && status->insync_regions < status->total_regions) {
|
||||
state->warned = 1;
|
||||
log_warn("WARNING: Waiting for resynchronization to finish "
|
||||
log_warn("WARNING: waiting for resynchronization to finish "
|
||||
"before initiating repair on RAID device %s.", device);
|
||||
/* Fall through to allow lvconvert to run. */
|
||||
}
|
||||
@@ -114,7 +114,7 @@ out:
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
enum dm_event_mask event __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 evmask __attribute__((unused)),
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
struct dso_state *state = *user;
|
||||
|
||||
@@ -45,10 +45,10 @@
|
||||
|
||||
struct dso_state {
|
||||
struct dm_pool *mem;
|
||||
dm_percent_t metadata_percent_check;
|
||||
dm_percent_t metadata_percent;
|
||||
dm_percent_t data_percent_check;
|
||||
dm_percent_t data_percent;
|
||||
int metadata_percent_check;
|
||||
int metadata_percent;
|
||||
int data_percent_check;
|
||||
int data_percent;
|
||||
uint64_t known_metadata_size;
|
||||
uint64_t known_data_size;
|
||||
unsigned fails;
|
||||
@@ -155,7 +155,7 @@ static int _wait_for_pid(struct dso_state *state)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask evmask,
|
||||
enum dm_event_mask event __attribute__((unused)),
|
||||
void **user)
|
||||
{
|
||||
const char *device = dm_task_get_name(dmt);
|
||||
@@ -179,7 +179,7 @@ void process_event(struct dm_task *dmt,
|
||||
return;
|
||||
}
|
||||
|
||||
if (evmask & DM_EVENT_DEVICE_ERROR) {
|
||||
if (event & 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))
|
||||
@@ -223,12 +223,10 @@ void process_event(struct dm_task *dmt,
|
||||
}
|
||||
|
||||
#if THIN_DEBUG
|
||||
log_debug("Thin pool status " FMTu64 "/" FMTu64 " (" FMTu64 ") "
|
||||
FMTu64 "/" FMTu64 " (" FMTu64").",
|
||||
tps->used_data_blocks, tps->total_data_blocks,
|
||||
state->known_data_size,
|
||||
log_debug("Thin pool status " FMTu64 "/" FMTu64 " "
|
||||
FMTu64 "/" FMTu64 ".",
|
||||
tps->used_metadata_blocks, tps->total_metadata_blocks,
|
||||
state->known_metadata_size);
|
||||
tps->used_data_blocks, tps->total_data_blocks);
|
||||
#endif
|
||||
|
||||
/* Thin pool size had changed. Clear the threshold. */
|
||||
@@ -384,10 +382,11 @@ int register_device(const char *device,
|
||||
} else /* Unsupported command format */
|
||||
goto inval;
|
||||
|
||||
state->max_fails = 1;
|
||||
state->pid = -1;
|
||||
*user = state;
|
||||
|
||||
log_info("Monitoring thin pool %s.", device);
|
||||
|
||||
return 1;
|
||||
inval:
|
||||
log_error("Invalid command for monitoring: %s.", cmd_str);
|
||||
@@ -431,6 +430,7 @@ int unregister_device(const char *device,
|
||||
_restore_thread_signals(state);
|
||||
|
||||
dmeventd_lvm2_exit_with_pool(state);
|
||||
log_info("No longer monitoring thin pool %s.", device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ static int _wait_for_pid(struct dso_state *state)
|
||||
}
|
||||
|
||||
void process_event(struct dm_task *dmt,
|
||||
enum dm_event_mask evmask __attribute__((unused)),
|
||||
enum dm_event_mask event __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 (evmask & DM_EVENT_DEVICE_ERROR) {
|
||||
if (event & DM_EVENT_DEVICE_ERROR) {
|
||||
#if VDO_DEBUG
|
||||
log_debug("VDO event error.");
|
||||
#endif
|
||||
|
||||
@@ -160,8 +160,6 @@ 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))
|
||||
@@ -554,14 +552,6 @@ 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,39 +795,6 @@ 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')
|
||||
|
||||
@@ -272,7 +272,7 @@ class ObjectManager(AutomatedProperties):
|
||||
For a given lvm asset return the dbus object path registered for it.
|
||||
This method first looks up by uuid and then by lvm_id. You
|
||||
can search by just one by setting uuid == lvm_id (uuid or lvm_id).
|
||||
If the object is not found and path_create is not None, the
|
||||
If the object is not found and path_create is a not None, the
|
||||
path_create function will be called to create a new object path and
|
||||
register it with the object manager for the specified uuid & lvm_id.
|
||||
Note: If path create is not None, uuid and lvm_id cannot be equal
|
||||
@@ -295,7 +295,7 @@ class ObjectManager(AutomatedProperties):
|
||||
if uuid == lvm_id:
|
||||
path = self._id_lookup(lvm_id)
|
||||
else:
|
||||
# We have a uuid and an lvm_id we can do sanity checks to ensure
|
||||
# We have an uuid and a lvm_id we can do sanity checks to ensure
|
||||
# that they are consistent
|
||||
|
||||
# If a PV is missing its device path is '[unknown]' or some
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2015-2025 Red Hat, Inc. All rights reserved.
|
||||
# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use,
|
||||
# modify, copy, or redistribute it subject to the terms and conditions
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
import pyudev
|
||||
import threading
|
||||
import os
|
||||
from . import cfg
|
||||
from .request import RequestEntry
|
||||
from . import utils
|
||||
@@ -53,47 +52,10 @@ def filter_event(action, device):
|
||||
# when appropriate.
|
||||
refresh = False
|
||||
|
||||
# Debug: Uncomment to log all udev events
|
||||
#devlinks_str = device.get('DEVLINKS', '')
|
||||
#utils.log_debug("Udev event: action='%s', DEVNAME='%s', ID_FS_TYPE='%s', subsystem='%s', DEVLINKS='%s'" %
|
||||
# (action, device.get('DEVNAME', 'N/A'), device.get('ID_FS_TYPE', 'N/A'),
|
||||
# device.get('SUBSYSTEM', 'N/A'), devlinks_str[:100] if devlinks_str else 'N/A'))
|
||||
|
||||
# Ignore everything but change
|
||||
if action != 'change':
|
||||
return
|
||||
|
||||
# Helper to lookup device with automatic path translation for test environments
|
||||
dm_dev_dir = os.environ.get('DM_DEV_DIR', '/dev')
|
||||
|
||||
def lookup_with_translation(device):
|
||||
"""Lookup device by name, with fallback to translated path if needed.
|
||||
|
||||
Try direct lookup first (fast path for production).
|
||||
If not found and using test environment (DM_DEV_DIR != /dev):
|
||||
- Extract dm-name from DEVLINKS (/dev/disk/by-id/dm-name-XXX)
|
||||
- Construct path: $DM_DEV_DIR/mapper/XXX
|
||||
- Try lookup again
|
||||
|
||||
Returns the found object or None.
|
||||
"""
|
||||
devname = device.get('DEVNAME', '')
|
||||
obj = cfg.om.get_object_by_lvm_id(devname)
|
||||
if not obj and dm_dev_dir != '/dev' and devname.startswith('/dev/dm-'):
|
||||
devlinks = device.get('DEVLINKS', '')
|
||||
if devlinks:
|
||||
# Parse DEVLINKS to find dm-name-XXX
|
||||
for link in devlinks.split():
|
||||
if 'dm-name-' in link:
|
||||
# Extract device-mapper name from /dev/disk/by-id/dm-name-XXX
|
||||
dm_name = link.split('dm-name-', 1)[1]
|
||||
# Construct path in DM_DEV_DIR and try lookup
|
||||
mapped_path = os.path.join(dm_dev_dir, 'mapper', dm_name)
|
||||
#utils.log_debug("Translating %s to %s (via dm-name)" % (devname, mapped_path))
|
||||
obj = cfg.om.get_object_by_lvm_id(mapped_path)
|
||||
break
|
||||
return obj
|
||||
|
||||
if 'ID_FS_TYPE' in device:
|
||||
fs_type_new = device['ID_FS_TYPE']
|
||||
if 'LVM' in fs_type_new:
|
||||
@@ -102,29 +64,17 @@ def filter_event(action, device):
|
||||
# would handle with the dbus notification or something
|
||||
# copied a pv signature onto a block device, this is
|
||||
# required to catch the latter.
|
||||
if not lookup_with_translation(device):
|
||||
if not cfg.om.get_object_by_lvm_id(device['DEVNAME']):
|
||||
refresh = True
|
||||
elif fs_type_new == '':
|
||||
# Check to see if the device was one we knew about
|
||||
if 'DEVNAME' in device:
|
||||
if lookup_with_translation(device):
|
||||
if cfg.om.get_object_by_lvm_id(device['DEVNAME']):
|
||||
refresh = True
|
||||
else:
|
||||
# This handles the wipefs -a path
|
||||
if not refresh and 'DEVNAME' in device:
|
||||
found_obj = lookup_with_translation(device)
|
||||
|
||||
# Also check device symlinks - udev might report /dev/dm-X but
|
||||
# the PV is tracked under a different name
|
||||
if not found_obj:
|
||||
devlinks = device.get('DEVLINKS', '')
|
||||
if devlinks:
|
||||
for link in devlinks.split():
|
||||
found_obj = cfg.om.get_object_by_lvm_id(link)
|
||||
if found_obj:
|
||||
break
|
||||
|
||||
if found_obj:
|
||||
if cfg.om.get_object_by_lvm_id(device['DEVNAME']):
|
||||
refresh = True
|
||||
|
||||
if refresh:
|
||||
@@ -135,8 +85,7 @@ def add():
|
||||
with observer_lock:
|
||||
global observer
|
||||
context = pyudev.Context()
|
||||
# Use source='udev' to get processed udev events, not raw kernel events
|
||||
monitor = pyudev.Monitor.from_netlink(context, source='udev')
|
||||
monitor = pyudev.Monitor.from_netlink(context)
|
||||
monitor.filter_by('block')
|
||||
observer = pyudev.MonitorObserver(monitor, filter_event)
|
||||
observer.start()
|
||||
|
||||
@@ -406,12 +406,10 @@ def handler(signum):
|
||||
cfg.ignore_sigterm = False
|
||||
return True
|
||||
|
||||
# Set shutdown flag first so worker threads can detect shutdown
|
||||
# even if exit_shell() blocks on shell_lock
|
||||
cfg.run.value = 0
|
||||
# If lvm shell is in use, tell it to exit
|
||||
if cfg.SHELL_IN_USE is not None:
|
||||
cfg.SHELL_IN_USE.exit_shell()
|
||||
cfg.run.value = 0
|
||||
log_error('Exiting daemon with signal %d' % signum)
|
||||
if cfg.loop is not None:
|
||||
cfg.loop.quit()
|
||||
|
||||
@@ -15,7 +15,7 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SOURCES = lvmlockd-core.c lvmlockd-helper.c
|
||||
SOURCES = lvmlockd-core.c
|
||||
SOURCES2 = lvmlockctl.c
|
||||
|
||||
TARGETS = lvmlockd lvmlockctl
|
||||
@@ -50,7 +50,8 @@ INCLUDES += -I$(top_srcdir)/libdaemon/server
|
||||
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
|
||||
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
|
||||
|
||||
ifeq ("@SD_NOTIFY_SUPPORT@", "yes")
|
||||
ifneq (,$(firstword $(LIBSYSTEMD_LIBS)))
|
||||
DEFS += -DUSE_SD_NOTIFY
|
||||
CFLAGS += $(LIBSYSTEMD_CFLAGS)
|
||||
LIBS += $(LIBSYSTEMD_LIBS)
|
||||
endif
|
||||
|
||||
@@ -67,160 +67,6 @@ do { \
|
||||
syslog(LOG_WARNING, fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Like sscanf, but requires buffer size to be specified
|
||||
* for storing scanned strings, e.g.
|
||||
*
|
||||
* szscanf("%s", sizeof(buf), buf);
|
||||
*
|
||||
* Up to size-1 input bytes will be copied into buf.
|
||||
* A null byte will be written to buf following the
|
||||
* last copied byte. When nothing is copied to buf,
|
||||
* no terminating null byte is written.
|
||||
*
|
||||
* If an input string matching %s is too long for the
|
||||
* specified buffer size, the characters that would have
|
||||
* been copied are ignored.
|
||||
*
|
||||
* Only recognizes: %d, %u, %s.
|
||||
*/
|
||||
static int szscanf(const char *input, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
const char *fm;
|
||||
const char *in;
|
||||
int matched = 0;
|
||||
int n;
|
||||
|
||||
va_start(args, format);
|
||||
fm = format;
|
||||
in = input;
|
||||
|
||||
while (*fm != '\0') {
|
||||
|
||||
/*
|
||||
* format is a string containing:
|
||||
* 1. %d matching int from input
|
||||
* %u matching unsigned int from input
|
||||
* %s matching non-whitespace characters from input
|
||||
* 2. whitespace chars matching zero or more whitespace
|
||||
* characters from input
|
||||
* 3. non-whitespace chars matching the same input chars
|
||||
*/
|
||||
|
||||
if (*fm == '%') {
|
||||
/*
|
||||
* case 1: %u, %d, or %s
|
||||
*/
|
||||
|
||||
/* advance past '%' character, to look for 'u', 'd' or 's' */
|
||||
fm++;
|
||||
|
||||
if (*fm == 'd') {
|
||||
/*
|
||||
* read an int (%d)
|
||||
*/
|
||||
int *dest = va_arg(args, int *);
|
||||
|
||||
if (sscanf(in, "%d%n", dest, &n) == 1) {
|
||||
in += n;
|
||||
matched++;
|
||||
} else {
|
||||
/* matching failure: no input int */
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (*fm == 'u') {
|
||||
/*
|
||||
* read an unsigned int (%u)
|
||||
*/
|
||||
unsigned int *dest = va_arg(args, unsigned int *);
|
||||
|
||||
if (sscanf(in, "%u%n", dest, &n) == 1) {
|
||||
in += n;
|
||||
matched++;
|
||||
} else {
|
||||
/* matching failure: no input unsigned int */
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (*fm == 's') {
|
||||
/*
|
||||
* read a string (%s) into dest buffer with dest_size
|
||||
* copy up to dest_size-1 characters into dest buffer
|
||||
* write null byte into dest buffer following the last
|
||||
* character copied. When dest_size-1 bytes are copied,
|
||||
* the null byte is written into the final byte of the
|
||||
* dest buffer. input bytes that would have been copied
|
||||
* but did not fit in the dest buffer are skipped.
|
||||
*/
|
||||
size_t dest_size = va_arg(args, size_t);
|
||||
char *dest = va_arg(args, char *);
|
||||
char *out = dest;
|
||||
|
||||
/* don't copy leading input whitespace to dest */
|
||||
while (isspace((unsigned char)*in))
|
||||
in++;
|
||||
|
||||
/* copy non-whitespace characters from input to dest */
|
||||
n = 0;
|
||||
while (*in != '\0' && !isspace((unsigned char)*in) && (n < (int)dest_size-1)) {
|
||||
*out = *in;
|
||||
out++;
|
||||
in++;
|
||||
n++;
|
||||
}
|
||||
if (n) {
|
||||
dest[n] = '\0';
|
||||
matched++;
|
||||
} else {
|
||||
/* matching failure: no input string chars */
|
||||
break;
|
||||
}
|
||||
|
||||
/* ignore input bytes that would have been copied but didn't fit */
|
||||
while (*in != '\0' && !isspace((unsigned char)*in))
|
||||
in++;
|
||||
|
||||
} else {
|
||||
/* unsupported format specifier */
|
||||
matched = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* advance past 'd', 'u', or 's' character */
|
||||
fm++;
|
||||
|
||||
} else if (isspace((unsigned char)*fm)) {
|
||||
/*
|
||||
* case 2: format whitespace skips zero or more input
|
||||
* whitespace characters
|
||||
*/
|
||||
while (isspace((unsigned char)*in))
|
||||
in++;
|
||||
|
||||
/* advance past whitespace character */
|
||||
fm++;
|
||||
|
||||
} else if (*fm == *in) {
|
||||
/*
|
||||
* case 3: literal character match between format and input
|
||||
*/
|
||||
fm++;
|
||||
in++;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* matching failure: format and input don't match
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
return matched;
|
||||
}
|
||||
|
||||
#define MAX_LINE 512
|
||||
|
||||
/* copied from lvmlockd-internal.h */
|
||||
@@ -251,11 +97,8 @@ static void save_client_info(char *line)
|
||||
uint32_t client_id = 0;
|
||||
char name[MAX_NAME+1] = { 0 };
|
||||
|
||||
/* info=client pid=%u fd=%d pi=%d id=%u name=%s */
|
||||
|
||||
if (szscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
|
||||
&pid, &fd, &pi, &client_id, sizeof(name), name) < 0)
|
||||
return;
|
||||
(void) sscanf(line, "info=client pid=%u fd=%d pi=%d id=%u name=%s",
|
||||
&pid, &fd, &pi, &client_id, name);
|
||||
|
||||
clients[num_clients].client_id = client_id;
|
||||
clients[num_clients].pid = pid;
|
||||
@@ -283,26 +126,19 @@ static void format_info_ls(char *line)
|
||||
char ls_name[MAX_NAME+1] = { 0 };
|
||||
char vg_name[MAX_NAME+1] = { 0 };
|
||||
char vg_uuid[MAX_NAME+1] = { 0 };
|
||||
char vg_args[MAX_ARGS+1] = { 0 };
|
||||
char lm_type[MAX_NAME+1] = { 0 };
|
||||
char lock_args[MAX_ARGS+1] = { 0 };
|
||||
char lock_type[MAX_NAME+1] = { 0 };
|
||||
|
||||
/* info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s */
|
||||
|
||||
if (szscanf(line, "info=ls ls_name=%s vg_name=%s vg_uuid=%s vg_args=%s lm_type=%s",
|
||||
sizeof(ls_name), ls_name,
|
||||
sizeof(vg_name), vg_name,
|
||||
sizeof(vg_uuid), vg_uuid,
|
||||
sizeof(vg_args), vg_args,
|
||||
sizeof(lm_type), lm_type) < 0)
|
||||
return;
|
||||
(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);
|
||||
|
||||
if (!first_ls)
|
||||
printf("\n");
|
||||
first_ls = 0;
|
||||
|
||||
printf("VG %s lock_type=%s %s\n", vg_name, lm_type, vg_uuid);
|
||||
printf("VG %s lock_type=%s %s\n", vg_name, lock_type, vg_uuid);
|
||||
|
||||
printf("LS %s %s\n", lm_type, ls_name);
|
||||
printf("LS %s %s\n", lock_type, ls_name);
|
||||
}
|
||||
|
||||
static void format_info_ls_action(char *line)
|
||||
@@ -314,67 +150,24 @@ static void format_info_ls_action(char *line)
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
|
||||
/* info=ls_action client_id=%u flags=%s version=%u op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d owner_host_id=%u owner_generation=%u */
|
||||
|
||||
if (szscanf(line, "info=ls_action client_id=%u flags=%s version=%s op=%s",
|
||||
&client_id,
|
||||
sizeof(flags), flags,
|
||||
sizeof(version), version,
|
||||
sizeof(op), op) < 0)
|
||||
return;
|
||||
(void) sscanf(line, "info=ls_action client_id=%u %s %s op=%s",
|
||||
&client_id, flags, version, op);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
printf("OP %s pid %u (%s)\n", op, pid, cl_name);
|
||||
}
|
||||
|
||||
static void format_info_ls_fence_history(char *line)
|
||||
{
|
||||
char op[MAX_NAME+1] = { 0 };
|
||||
int result = 0;
|
||||
uint32_t msg_id = 0;
|
||||
uint32_t owner_host_id = 0;
|
||||
uint32_t owner_generation = 0;
|
||||
char ourkey_str[MAX_NAME+1] = { 0 };
|
||||
char remkey_str[MAX_NAME+1] = { 0 };
|
||||
|
||||
/* info=ls_fence_history op=%s result=%d msg_id=%u owner_host_id=%u owner_generation=%u ourkey=0x%llx remkey=0x%llx */
|
||||
|
||||
if (szscanf(line, "info=ls_fence_history op=%s result=%d msg_id=%u owner_host_id=%u owner_generation=%u ourkey=%s remkey=%s",
|
||||
sizeof(op), op,
|
||||
&result,
|
||||
&msg_id,
|
||||
&owner_host_id,
|
||||
&owner_generation,
|
||||
sizeof(ourkey_str), ourkey_str,
|
||||
sizeof(remkey_str), remkey_str) < 0)
|
||||
return;
|
||||
|
||||
if (!strcmp(op, "fence_result"))
|
||||
printf("PR host_id %u generation %u key %s %s\n",
|
||||
owner_host_id, owner_generation, remkey_str, result == 0 ? "removed" : "failed");
|
||||
else if (!strcmp(op, "fence"))
|
||||
printf("PR host_id %u generation %u key %s waiting\n",
|
||||
owner_host_id, owner_generation, remkey_str);
|
||||
}
|
||||
|
||||
static void format_info_r(char *line, char *r_name_out, char *r_type_out)
|
||||
{
|
||||
char r_name[MAX_NAME+1] = { 0 };
|
||||
char r_type[4] = { 0 };
|
||||
char mode[4] = { 0 };
|
||||
int sh_count = 0;
|
||||
unsigned int ver = 0;
|
||||
char sh_count[MAX_NAME+1] = { 0 };
|
||||
uint32_t ver = 0;
|
||||
|
||||
/* info=r name=%s type=%s mode=%s sh_count=%d version=%s */
|
||||
|
||||
if (szscanf(line, "info=r name=%s type=%s mode=%s sh_count=%d version=%u",
|
||||
sizeof(r_name), r_name,
|
||||
sizeof(r_type), r_type,
|
||||
sizeof(mode), mode,
|
||||
&sh_count,
|
||||
&ver) < 0)
|
||||
return;
|
||||
(void) sscanf(line, "info=r name=%s type=%s mode=%s %s version=%u",
|
||||
r_name, r_type, mode, sh_count, &ver);
|
||||
|
||||
strcpy(r_name_out, r_name);
|
||||
strcpy(r_type_out, r_type);
|
||||
@@ -399,8 +192,8 @@ static void format_info_r(char *line, char *r_name_out, char *r_type_out)
|
||||
static void format_info_lk(char *line, char *r_name, char *r_type)
|
||||
{
|
||||
char mode[4] = { 0 };
|
||||
char flags[MAX_NAME+1] = { 0 };
|
||||
uint32_t ver = 0;
|
||||
char flags[MAX_NAME+1] = { 0 };
|
||||
uint32_t client_id = 0;
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
@@ -411,14 +204,8 @@ static void format_info_lk(char *line, char *r_name, char *r_type)
|
||||
return;
|
||||
}
|
||||
|
||||
/* info=lk mode=%s version=%s flags=%s client_id=%u */
|
||||
|
||||
if (szscanf(line, "info=lk mode=%s version=%u flags=%s client_id=%u",
|
||||
sizeof(mode), mode,
|
||||
&ver,
|
||||
sizeof(flags), flags,
|
||||
&client_id) < 0)
|
||||
return;
|
||||
(void) sscanf(line, "info=lk mode=%s version=%u %s client_id=%u",
|
||||
mode, &ver, flags, &client_id);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
@@ -441,9 +228,9 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
char op[MAX_NAME+1] = { 0 };
|
||||
char rt[4] = { 0 };
|
||||
char mode[4] = { 0 };
|
||||
char lm_type[MAX_NAME+1] = { 0 };
|
||||
int result = 0;
|
||||
int lm_rv = 0;
|
||||
char lm[MAX_NAME+1] = { 0 };
|
||||
char result[MAX_NAME+1] = { 0 };
|
||||
char lm_rv[MAX_NAME+1] = { 0 };
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
|
||||
@@ -453,19 +240,8 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
return;
|
||||
}
|
||||
|
||||
/* info=r_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d owner_host_id=%u owner_generation=%u */
|
||||
|
||||
if (szscanf(line, "info=r_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d",
|
||||
&client_id,
|
||||
sizeof(flags), flags,
|
||||
sizeof(version), version,
|
||||
sizeof(op), op,
|
||||
sizeof(rt), rt,
|
||||
sizeof(mode), mode,
|
||||
sizeof(lm_type), lm_type,
|
||||
&result,
|
||||
&lm_rv) < 0)
|
||||
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);
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
@@ -485,62 +261,6 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
|
||||
}
|
||||
}
|
||||
|
||||
static void format_info_r_fence_wait_action(char *line, char *r_name, char *r_type)
|
||||
{
|
||||
uint32_t client_id = 0;
|
||||
char flags[MAX_NAME+1] = { 0 };
|
||||
char version[MAX_NAME+1] = { 0 };
|
||||
char op[MAX_NAME+1] = { 0 };
|
||||
char rt[4] = { 0 };
|
||||
char mode[4] = { 0 };
|
||||
char lm_type[MAX_NAME+1] = { 0 };
|
||||
int result = 0;
|
||||
int lm_rv = 0;
|
||||
uint32_t owner_host_id = 0;
|
||||
uint32_t owner_generation = 0;
|
||||
uint32_t pid = 0;
|
||||
char cl_name[MAX_NAME+1] = { 0 };
|
||||
|
||||
if (!r_name[0] || !r_type[0]) {
|
||||
printf("format_info_r_fence_wait_action error r_name %s r_type %s\n", r_name, r_type);
|
||||
printf("%s\n", line);
|
||||
return;
|
||||
}
|
||||
|
||||
/* info=r_fence_wait_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d owner_host_id=%u owner_generation=%u */
|
||||
|
||||
if (szscanf(line, "info=r_fence_wait_action client_id=%u flags=%s version=%s op=%s rt=%s mode=%s lm_type=%s result=%d lm_rv=%d owner_host_id=%u owner_generation=%u",
|
||||
&client_id,
|
||||
sizeof(flags), flags,
|
||||
sizeof(version), version,
|
||||
sizeof(op), op,
|
||||
sizeof(rt), rt,
|
||||
sizeof(mode), mode,
|
||||
sizeof(lm_type), lm_type,
|
||||
&result,
|
||||
&lm_rv,
|
||||
&owner_host_id,
|
||||
&owner_generation) < 0)
|
||||
return;
|
||||
|
||||
find_client_info(client_id, &pid, cl_name);
|
||||
|
||||
if (strcmp(op, "lock")) {
|
||||
printf("OP %s pid %u (%s)\n", op, pid, cl_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(r_type, "gl")) {
|
||||
printf("LW GL %s ver %u pid %u (%s) fence_owner %u.%u\n", mode, 0, pid, cl_name, owner_host_id, owner_generation);
|
||||
|
||||
} else if (!strcmp(r_type, "vg")) {
|
||||
printf("LW VG %s ver %u pid %u (%s) fence_owner %u.%u\n", mode, 0, pid, cl_name, owner_host_id, owner_generation);
|
||||
|
||||
} else if (!strcmp(r_type, "lv")) {
|
||||
printf("LW LV %s %s fence_owner %u.%u\n", mode, r_name, owner_host_id, owner_generation);
|
||||
}
|
||||
}
|
||||
|
||||
static void format_info_line(char *line, char *r_name, char *r_type)
|
||||
{
|
||||
if (!strncmp(line, "info=structs ", sizeof("info=structs ") - 1)) {
|
||||
@@ -555,9 +275,6 @@ static void format_info_line(char *line, char *r_name, char *r_type)
|
||||
} else if (!strncmp(line, "info=ls_action ", sizeof("info=ls_action ") - 1)) {
|
||||
format_info_ls_action(line);
|
||||
|
||||
} else if (!strncmp(line, "info=ls_fence_history ", sizeof("info=ls_fence_history ") - 1)) {
|
||||
format_info_ls_fence_history(line);
|
||||
|
||||
} else if (!strncmp(line, "info=r ", sizeof("info=r ") - 1)) {
|
||||
/*
|
||||
* r_name/r_type are reset when a new resource is found.
|
||||
@@ -575,11 +292,6 @@ static void format_info_line(char *line, char *r_name, char *r_type)
|
||||
} else if (!strncmp(line, "info=r_action ", sizeof("info=r_action ") - 1)) {
|
||||
/* will use info from previous r */
|
||||
format_info_r_action(line, r_name, r_type);
|
||||
|
||||
} else if (!strncmp(line, "info=r_fence_wait_action ", sizeof("info=r_fence_wait_action ") - 1)) {
|
||||
/* will use info from previous r */
|
||||
format_info_r_fence_wait_action(line, r_name, r_type);
|
||||
|
||||
} else {
|
||||
printf("UN %s\n", line);
|
||||
}
|
||||
|
||||
@@ -57,14 +57,5 @@ static inline void lvmlockd_close(daemon_handle h)
|
||||
#define EORPHAN 222
|
||||
#define EADOPT_NONE 223
|
||||
#define EADOPT_RETRY 224
|
||||
#define EIOTIMEOUT 225
|
||||
#define ELOCKREPAIR 226
|
||||
|
||||
#define LOCKARGS_VERSION 0x00000001 /* meta only */
|
||||
#define LOCKARGS_LVMLOCK 0x00000002 /* meta only */
|
||||
#define LOCKARGS_TIMEOUT 0x00000004 /* user only */
|
||||
#define LOCKARGS_NOTIMEOUT 0x00000008 /* meta or user */
|
||||
#define LOCKARGS_PERSIST 0x00000010 /* meta or user */
|
||||
#define LOCKARGS_NOPERSIST 0x00000020 /* user only */
|
||||
|
||||
#endif /* _LVM_LVMLOCKD_CLIENT_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "daemon-server.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <errno.h>
|
||||
#include <endian.h>
|
||||
#include <fcntl.h>
|
||||
#include <byteswap.h>
|
||||
#include <syslog.h>
|
||||
#include <dirent.h>
|
||||
|
||||
@@ -76,7 +77,7 @@ static int check_args_version(char *vg_args)
|
||||
unsigned int major = 0;
|
||||
int rv;
|
||||
|
||||
rv = lockd_lockargs_get_version(vg_args, &major, NULL, NULL);
|
||||
rv = version_from_args(vg_args, &major, NULL, NULL);
|
||||
if (rv < 0) {
|
||||
log_error("check_args_version %s error %d", vg_args, rv);
|
||||
return rv;
|
||||
@@ -168,10 +169,8 @@ int lm_prepare_lockspace_dlm(struct lockspace *ls)
|
||||
struct lm_dlm *lmd;
|
||||
int rv;
|
||||
|
||||
if (daemon_test) {
|
||||
log_debug("lm_prepare_lockspace_dlm test");
|
||||
if (daemon_test)
|
||||
goto skip_args;
|
||||
}
|
||||
|
||||
memset(sys_clustername, 0, sizeof(sys_clustername));
|
||||
memset(arg_clustername, 0, sizeof(arg_clustername));
|
||||
@@ -362,7 +361,7 @@ int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl)
|
||||
static 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;
|
||||
@@ -583,9 +582,9 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
|
||||
if (daemon_test) {
|
||||
if (rdd->vb) {
|
||||
vb_out->version = le16toh(rdd->vb->version);
|
||||
vb_out->flags = le16toh(rdd->vb->flags);
|
||||
vb_out->r_version = le32toh(rdd->vb->r_version);
|
||||
vb_out->version = le16_to_cpu(rdd->vb->version);
|
||||
vb_out->flags = le16_to_cpu(rdd->vb->flags);
|
||||
vb_out->r_version = le32_to_cpu(rdd->vb->r_version);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -637,9 +636,9 @@ lockrv:
|
||||
memcpy(&vb, lksb->sb_lvbptr, sizeof(struct val_blk));
|
||||
memcpy(rdd->vb, &vb, sizeof(vb));
|
||||
|
||||
vb_out->version = le16toh(vb.version);
|
||||
vb_out->flags = le16toh(vb.flags);
|
||||
vb_out->r_version = le32toh(vb.r_version);
|
||||
vb_out->version = le16_to_cpu(vb.version);
|
||||
vb_out->flags = le16_to_cpu(vb.flags);
|
||||
vb_out->r_version = le32_to_cpu(vb.r_version);
|
||||
}
|
||||
out:
|
||||
return 0;
|
||||
@@ -664,9 +663,9 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
|
||||
if (rdd->vb && r_version && (r->mode == LD_LK_EX)) {
|
||||
if (!rdd->vb->version) {
|
||||
/* first time vb has been written */
|
||||
rdd->vb->version = htole16(VAL_BLK_VERSION);
|
||||
rdd->vb->version = cpu_to_le16(VAL_BLK_VERSION);
|
||||
}
|
||||
rdd->vb->r_version = htole32(r_version);
|
||||
rdd->vb->r_version = cpu_to_le32(r_version);
|
||||
memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk));
|
||||
|
||||
log_debug("%s:%s convert_dlm set r_version %u",
|
||||
@@ -723,17 +722,17 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
memcpy(&vb_next, rdd->vb, sizeof(struct val_blk));
|
||||
|
||||
if (!vb_prev.version) {
|
||||
vb_next.version = htole16(VAL_BLK_VERSION);
|
||||
vb_next.version = cpu_to_le16(VAL_BLK_VERSION);
|
||||
new_vb = 1;
|
||||
}
|
||||
|
||||
if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) {
|
||||
vb_next.flags = htole16(VBF_REMOVED);
|
||||
vb_next.flags = cpu_to_le16(VBF_REMOVED);
|
||||
new_vb = 1;
|
||||
}
|
||||
|
||||
if (r_version) {
|
||||
vb_next.r_version = htole32(r_version);
|
||||
vb_next.r_version = cpu_to_le32(r_version);
|
||||
new_vb = 1;
|
||||
}
|
||||
|
||||
@@ -743,12 +742,12 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
|
||||
log_debug("%s:%s unlock_dlm vb old %x %x %u new %x %x %u",
|
||||
ls->name, r->name,
|
||||
le16toh(vb_prev.version),
|
||||
le16toh(vb_prev.flags),
|
||||
le32toh(vb_prev.r_version),
|
||||
le16toh(vb_next.version),
|
||||
le16toh(vb_next.flags),
|
||||
le32toh(vb_next.r_version));
|
||||
le16_to_cpu(vb_prev.version),
|
||||
le16_to_cpu(vb_prev.flags),
|
||||
le32_to_cpu(vb_prev.r_version),
|
||||
le16_to_cpu(vb_next.version),
|
||||
le16_to_cpu(vb_next.flags),
|
||||
le32_to_cpu(vb_next.r_version));
|
||||
} else {
|
||||
log_debug("%s:%s unlock_dlm vb unchanged", ls->name, r->name);
|
||||
}
|
||||
@@ -798,14 +797,6 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
|
||||
* the stale lockspaces on the others eventually.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* On error, returns < 0
|
||||
*
|
||||
* On success:
|
||||
* If other hosts are found, returns the number.
|
||||
* If no other hosts are found (only ourself), returns 0.
|
||||
*/
|
||||
|
||||
int lm_hosts_dlm(struct lockspace *ls, int notify)
|
||||
{
|
||||
char ls_nodes_path[PATH_MAX];
|
||||
|
||||
@@ -1,264 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 Red Hat, Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU General Public License v2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <grp.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
|
||||
struct list_head commands; /* helper_msg_list entries */
|
||||
|
||||
static int _log_stderr;
|
||||
|
||||
#define log_helper(fmt, args...) \
|
||||
do { \
|
||||
if (_log_stderr) \
|
||||
fprintf(stderr, fmt "\n", ##args); \
|
||||
} while (0)
|
||||
|
||||
static void _save_command(struct helper_msg *msg)
|
||||
{
|
||||
struct helper_msg_list *ml;
|
||||
|
||||
ml = malloc(sizeof(struct helper_msg_list));
|
||||
if (!ml)
|
||||
return;
|
||||
|
||||
memcpy(&ml->msg, msg, sizeof(struct helper_msg));
|
||||
list_add_tail(&ml->list, &commands);
|
||||
}
|
||||
|
||||
static struct helper_msg_list *_get_command(int pid)
|
||||
{
|
||||
struct helper_msg_list *ml;
|
||||
|
||||
list_for_each_entry(ml, &commands, list) {
|
||||
if (ml->msg.pid == pid)
|
||||
return ml;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int read_msg(int fd, struct helper_msg *msg)
|
||||
{
|
||||
int rv;
|
||||
retry:
|
||||
rv = read(fd, msg, sizeof(struct helper_msg));
|
||||
if (rv == -1 && errno == EINTR)
|
||||
goto retry;
|
||||
|
||||
if (rv != sizeof(struct helper_msg))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exec_command(char *cmd_str)
|
||||
{
|
||||
char arg[ONE_ARG_LEN];
|
||||
char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
|
||||
int av_count = 0;
|
||||
int i, arg_len, cmd_len;
|
||||
|
||||
for (i = 0; i < MAX_AV_COUNT + 1; i++)
|
||||
av[i] = NULL;
|
||||
|
||||
if (!cmd_str[0])
|
||||
return;
|
||||
|
||||
/* this should already be done, but make sure */
|
||||
cmd_str[RUN_COMMAND_LEN - 1] = '\0';
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg_len = 0;
|
||||
cmd_len = strlen(cmd_str);
|
||||
|
||||
for (i = 0; i < cmd_len; i++) {
|
||||
if (!cmd_str[i])
|
||||
break;
|
||||
|
||||
if (av_count == MAX_AV_COUNT)
|
||||
break;
|
||||
|
||||
if (cmd_str[i] == '\\') {
|
||||
if (i == (cmd_len - 1))
|
||||
break;
|
||||
i++;
|
||||
|
||||
if (cmd_str[i] == '\\') {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
continue;
|
||||
}
|
||||
if (isspace(cmd_str[i])) {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
|
||||
arg[arg_len++] = cmd_str[i];
|
||||
} else if (isspace(cmd_str[i])) {
|
||||
if (arg_len)
|
||||
av[av_count++] = strdup(arg);
|
||||
|
||||
memset(arg, 0, sizeof(arg));
|
||||
arg_len = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((av_count < MAX_AV_COUNT) && arg_len) {
|
||||
av[av_count++] = strdup(arg);
|
||||
}
|
||||
|
||||
execvp(av[0], av);
|
||||
}
|
||||
|
||||
static int send_result(struct helper_msg *msg, int fd)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = write(fd, msg, sizeof(struct helper_msg));
|
||||
|
||||
if (rv == sizeof(struct helper_msg))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define IDLE_TIMEOUT_MS (30 * 1000)
|
||||
#define ACTIVE_TIMEOUT_MS 500
|
||||
|
||||
__attribute__((noreturn)) void helper_main(int in_fd, int out_fd, int log_stderr)
|
||||
{
|
||||
struct pollfd pollfd;
|
||||
struct helper_msg msg;
|
||||
struct helper_msg_list *ml;
|
||||
siginfo_t info;
|
||||
unsigned int fork_count = 0;
|
||||
unsigned int done_count = 0;
|
||||
int timeout = IDLE_TIMEOUT_MS;
|
||||
int rv, pid;
|
||||
|
||||
INIT_LIST_HEAD(&commands);
|
||||
|
||||
_log_stderr = log_stderr;
|
||||
|
||||
rv = setgroups(0, NULL);
|
||||
if (rv < 0)
|
||||
log_helper("error clearing helper groups errno %i", errno);
|
||||
|
||||
memset(&pollfd, 0, sizeof(pollfd));
|
||||
pollfd.fd = in_fd;
|
||||
pollfd.events = POLLIN;
|
||||
|
||||
openlog("lvmlockd-helper", LOG_CONS | LOG_PID, LOG_LOCAL4);
|
||||
|
||||
while (1) {
|
||||
rv = poll(&pollfd, 1, timeout);
|
||||
if (rv == -1 && errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (rv < 0)
|
||||
exit(0);
|
||||
|
||||
if (pollfd.revents & POLLIN) {
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
rv = read_msg(in_fd, &msg);
|
||||
if (rv)
|
||||
continue;
|
||||
|
||||
if (msg.type == HELPER_COMMAND) {
|
||||
pid = fork();
|
||||
if (!pid) {
|
||||
exec_command(msg.command);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
msg.pid = pid;
|
||||
|
||||
_save_command(&msg);
|
||||
|
||||
fork_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL))
|
||||
exit(0);
|
||||
|
||||
/* collect child exits until no more children exist (ECHILD)
|
||||
or none are ready (WNOHANG) */
|
||||
|
||||
while (1) {
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
rv = waitid(P_ALL, 0, &info, WEXITED | WNOHANG);
|
||||
|
||||
if ((rv < 0) && (errno == ECHILD)) {
|
||||
/*
|
||||
log_helper("helper no children exist fork_count %d done_count %d", fork_count, done_count);
|
||||
*/
|
||||
timeout = IDLE_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
else if (!rv && !info.si_pid) {
|
||||
log_helper("helper no children ready fork_count %d done_count %d", fork_count, done_count);
|
||||
timeout = ACTIVE_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
else if (!rv && info.si_pid) {
|
||||
done_count++;
|
||||
|
||||
if (!(ml = _get_command(info.si_pid))) {
|
||||
log_helper("command for pid %d result %d not found",
|
||||
info.si_pid, info.si_status);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_helper("command for pid %d result %d done", info.si_pid, info.si_status);
|
||||
|
||||
ml->msg.type = HELPER_COMMAND_RESULT;
|
||||
ml->msg.result = info.si_status;
|
||||
|
||||
send_result(&ml->msg, out_fd);
|
||||
|
||||
list_del(&ml->list);
|
||||
free(ml);
|
||||
continue;
|
||||
}
|
||||
|
||||
else {
|
||||
log_helper("helper waitid rv %d errno %d fork_count %d done_count %d",
|
||||
rv, errno, fork_count, done_count);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "tools/tool.h"
|
||||
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "daemon-server.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
|
||||
#include "lvmlockd-internal.h"
|
||||
@@ -490,7 +490,7 @@ out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
static int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
|
||||
{
|
||||
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
|
||||
|
||||
@@ -556,9 +556,9 @@ int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
|
||||
|
||||
if (daemon_test) {
|
||||
if (rdi->vb) {
|
||||
vb_out->version = le16toh(rdi->vb->version);
|
||||
vb_out->flags = le16toh(rdi->vb->flags);
|
||||
vb_out->r_version = le32toh(rdi->vb->r_version);
|
||||
vb_out->version = le16_to_cpu(rdi->vb->version);
|
||||
vb_out->flags = le16_to_cpu(rdi->vb->flags);
|
||||
vb_out->r_version = le32_to_cpu(rdi->vb->r_version);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
|
||||
#include "base/memory/container_of.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_NAME 64
|
||||
#define MAX_ARGS 64
|
||||
|
||||
@@ -62,11 +59,6 @@ enum {
|
||||
LD_OP_BUSY,
|
||||
LD_OP_QUERY_LOCK,
|
||||
LD_OP_REFRESH_LV,
|
||||
LD_OP_VG_STATUS,
|
||||
LD_OP_FENCE,
|
||||
LD_OP_FENCE_RESULT,
|
||||
LD_OP_SETLOCKARGS_BEFORE,
|
||||
LD_OP_SETLOCKARGS_FINAL,
|
||||
};
|
||||
|
||||
/* resource types */
|
||||
@@ -122,9 +114,6 @@ struct client {
|
||||
#define LD_AF_SH_EXISTS 0x00100000
|
||||
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
|
||||
#define LD_AF_NODELAY 0x00400000
|
||||
#define LD_AF_REPAIR 0x00800000
|
||||
#define LD_AF_NO_TIMEOUT 0x01000000
|
||||
#define LD_AF_HOSTS_UNKNOWN 0x02000000
|
||||
|
||||
/*
|
||||
* Number of times to repeat a lock request after
|
||||
@@ -138,54 +127,13 @@ struct pvs {
|
||||
int num;
|
||||
};
|
||||
|
||||
#define RUN_COMMAND_LEN 1024
|
||||
#define MAX_AV_COUNT 32
|
||||
#define ONE_ARG_LEN 256
|
||||
|
||||
/* helper_msg types */
|
||||
#define HELPER_COMMAND 0x1
|
||||
#define HELPER_COMMAND_RESULT 0x2
|
||||
|
||||
struct helper_msg {
|
||||
uint8_t type;
|
||||
uint8_t act;
|
||||
uint16_t unused1;
|
||||
uint32_t msg_id;
|
||||
int pid;
|
||||
int result;
|
||||
char ls_name[MAX_NAME+1];
|
||||
uint8_t unused2;
|
||||
uint16_t unused3;
|
||||
char command[RUN_COMMAND_LEN];
|
||||
};
|
||||
|
||||
struct helper_msg_list {
|
||||
struct helper_msg msg;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define OWNER_NAME_SIZE 64
|
||||
#define OWNER_STATE_SIZE 32
|
||||
|
||||
struct owner {
|
||||
uint32_t host_id;
|
||||
uint32_t generation;
|
||||
uint32_t timestamp;
|
||||
char state[OWNER_STATE_SIZE];
|
||||
char name[OWNER_NAME_SIZE];
|
||||
};
|
||||
|
||||
struct action {
|
||||
struct list_head list;
|
||||
uint32_t client_id;
|
||||
uint32_t flags; /* LD_AF_ */
|
||||
uint32_t msg_id;
|
||||
uint32_t version;
|
||||
uint32_t host_id;
|
||||
uint64_t ourkey;
|
||||
uint64_t remkey;
|
||||
uint64_t host_id;
|
||||
uint64_t lv_size_bytes;
|
||||
uint64_t ls_generation;
|
||||
int8_t op; /* operation type LD_OP_ */
|
||||
int8_t rt; /* resource type LD_RT_ */
|
||||
int8_t mode; /* lock mode LD_LK_ */
|
||||
@@ -202,8 +150,7 @@ struct action {
|
||||
char lv_uuid[MAX_NAME+1];
|
||||
char vg_args[MAX_ARGS+1];
|
||||
char lv_args[MAX_ARGS+1];
|
||||
char other_args[MAX_ARGS+1];
|
||||
struct owner owner;
|
||||
char prev_lv_args[MAX_ARGS+1];
|
||||
struct pvs pvs; /* PV list for idm */
|
||||
};
|
||||
|
||||
@@ -216,14 +163,12 @@ 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;
|
||||
unsigned int use_vb : 1;
|
||||
struct list_head locks;
|
||||
struct list_head actions;
|
||||
struct list_head fence_wait_actions;
|
||||
char lv_args[MAX_ARGS+1];
|
||||
char lm_data[]; /* lock manager specific data */
|
||||
};
|
||||
@@ -246,9 +191,7 @@ struct lockspace {
|
||||
char vg_args[MAX_ARGS+1]; /* lock manager specific args */
|
||||
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
|
||||
void *lm_data;
|
||||
uint32_t lock_args_flags;
|
||||
uint32_t host_id;
|
||||
uint64_t generation;
|
||||
uint64_t host_id;
|
||||
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
|
||||
struct pvs pvs; /* for idm: PV list */
|
||||
|
||||
@@ -263,14 +206,12 @@ struct lockspace {
|
||||
unsigned int thread_done : 1;
|
||||
unsigned int sanlock_gl_enabled: 1;
|
||||
unsigned int sanlock_gl_dup: 1;
|
||||
unsigned int free_vg: 1;
|
||||
unsigned int kill_vg: 1;
|
||||
unsigned int fence_pr: 1;
|
||||
unsigned int no_timeout: 1;
|
||||
unsigned int drop_vg: 1;
|
||||
|
||||
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 */
|
||||
struct list_head fence_history; /* internally created actions for fencing */
|
||||
};
|
||||
|
||||
/* val_blk version */
|
||||
@@ -337,15 +278,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 */
|
||||
@@ -429,9 +370,7 @@ void log_level(int level, const char *fmt, ...) __attribute__((format(printf, 2
|
||||
struct lockspace *alloc_lockspace(void);
|
||||
int lockspaces_empty(void);
|
||||
int last_string_from_args(char *args_in, char *last);
|
||||
void helper_main(int in_fd, int out_fd, int log_stderr);
|
||||
int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags);
|
||||
int lockd_lockargs_get_version(char *str, unsigned int *major, unsigned int *minor, unsigned int *patch);
|
||||
int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsigned int *patch);
|
||||
|
||||
static inline const char *mode_str(int x)
|
||||
{
|
||||
@@ -458,7 +397,6 @@ 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,
|
||||
@@ -482,102 +420,69 @@ 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;
|
||||
}
|
||||
|
||||
@@ -600,34 +505,29 @@ static inline int lm_refresh_lv_check_dlm(struct action *act)
|
||||
|
||||
#ifdef LOCKDSANLOCK_SUPPORT
|
||||
|
||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args);
|
||||
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb);
|
||||
int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_args);
|
||||
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
|
||||
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
|
||||
int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair);
|
||||
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, struct owner *owner,
|
||||
int adopt_only, int adopt_ok, int repair);
|
||||
struct val_blk *vb_out, int *retry,
|
||||
int adopt_only, int adopt_ok);
|
||||
int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
|
||||
int ld_mode, uint32_t r_version);
|
||||
int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
|
||||
uint32_t r_version, uint32_t lmu_flags);
|
||||
int lm_able_gl_sanlock(struct lockspace *ls, int enable);
|
||||
int lm_ex_disable_gl_sanlock(struct lockspace *ls);
|
||||
int lm_hosts_sanlock(struct lockspace *ls, int notify, int *hosts_unknown);
|
||||
int lm_hosts_sanlock(struct lockspace *ls, int notify);
|
||||
int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r);
|
||||
int lm_gl_is_enabled(struct lockspace *ls);
|
||||
int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin);
|
||||
int lm_data_size_sanlock(void);
|
||||
int lm_is_running_sanlock(void);
|
||||
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
|
||||
int lm_vg_status_sanlock(struct lockspace *ls, struct action *act);
|
||||
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner);
|
||||
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act);
|
||||
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act);
|
||||
|
||||
static inline int lm_support_sanlock(void)
|
||||
{
|
||||
@@ -636,7 +536,7 @@ static inline int lm_support_sanlock(void)
|
||||
|
||||
#else
|
||||
|
||||
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args)
|
||||
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -656,7 +556,7 @@ static inline int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t fl
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation, int repair)
|
||||
static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -671,14 +571,9 @@ 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, struct owner *owner,
|
||||
int adopt_only, int adopt_ok, int repair)
|
||||
struct val_blk *vb_out, int *retry,
|
||||
int adopt_only, int adopt_ok)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -705,7 +600,7 @@ static inline int lm_ex_disable_gl_sanlock(struct lockspace *ls)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_hosts_sanlock(struct lockspace *ls, int notify, int *hosts_unknown)
|
||||
static inline int lm_hosts_sanlock(struct lockspace *ls, int notify)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -740,30 +635,11 @@ static inline int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_si
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_vg_status_sanlock(struct lockspace *ls, struct action *act)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int lm_support_sanlock(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* sanlock support */
|
||||
|
||||
#ifdef LOCKDIDM_SUPPORT
|
||||
@@ -773,7 +649,6 @@ 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);
|
||||
@@ -819,11 +694,6 @@ 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)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@
|
||||
#include "lvmpolld-common.h"
|
||||
|
||||
#include "lvm-version.h"
|
||||
#include "libdaemon/server/daemon-server.h"
|
||||
#include "libdaemon/server/daemon-log.h"
|
||||
#include "daemon-server.h"
|
||||
#include "daemon-log.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <poll.h>
|
||||
@@ -390,11 +390,6 @@ 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) + sizeof(LVM_SYSTEM_DIR): 1;
|
||||
size_t l = sysdir ? strlen(sysdir) + 16 : 1;
|
||||
char *env = (char *) malloc(l * sizeof(char));
|
||||
|
||||
if (!env)
|
||||
@@ -89,17 +89,6 @@ 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,
|
||||
@@ -107,26 +96,30 @@ 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 = 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),
|
||||
.lvmpolld_id = lvmpolld_id,
|
||||
.lvid = _get_lvid(lvmpolld_id, sysdir),
|
||||
.lvname = full_lvname,
|
||||
.devicesfile = devicesfile_dup,
|
||||
.lvm_system_dir_env = lvm_system_dir_env,
|
||||
.sinterval = strdup(sinterval), /* copy */
|
||||
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
|
||||
.cmd_state = { .retcode = -1, .signal = 0 },
|
||||
.pdst = pdst,
|
||||
.init_rq_count = 1
|
||||
}, *pdlv = (struct lvmpolld_lv *) malloc(sizeof(struct lvmpolld_lv));
|
||||
|
||||
if (!pdlv || !tmp.lvmpolld_id || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
|
||||
if (!pdlv || !tmp.lvid || !tmp.lvname || !tmp.lvm_system_dir_env || !tmp.sinterval)
|
||||
goto err;
|
||||
|
||||
tmp.lvid = _get_lvid(tmp.lvmpolld_id, sysdir),
|
||||
|
||||
*pdlv = tmp;
|
||||
memcpy(pdlv, &tmp, sizeof(*pdlv));
|
||||
|
||||
if (pthread_mutex_init(&pdlv->lock, NULL))
|
||||
goto err;
|
||||
@@ -134,20 +127,29 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
|
||||
return pdlv;
|
||||
|
||||
err:
|
||||
_free_lvmpolld_lv(&tmp);
|
||||
|
||||
free(pdlv);
|
||||
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);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pdlv_destroy(struct lvmpolld_lv *pdlv)
|
||||
{
|
||||
_free_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);
|
||||
|
||||
pthread_mutex_destroy(&pdlv->lock);
|
||||
|
||||
free(pdlv);
|
||||
free((void *)pdlv);
|
||||
}
|
||||
|
||||
unsigned pdlv_get_polling_finished(struct lvmpolld_lv *pdlv)
|
||||
|
||||
@@ -15,10 +15,7 @@
|
||||
#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;
|
||||
@@ -96,7 +93,7 @@ struct lvmpolld_thread_data {
|
||||
struct lvmpolld_lv *pdlv;
|
||||
};
|
||||
|
||||
char *construct_id(const char *sysdir, const char *uuid);
|
||||
char *construct_id(const char *sysdir, const char *lvid);
|
||||
|
||||
/* LVMPOLLD_LV_T section */
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ DEVICE_MAPPER_SOURCE=\
|
||||
device_mapper/libdm-targets.c \
|
||||
device_mapper/libdm-timestamp.c \
|
||||
device_mapper/mm/pool.c \
|
||||
device_mapper/raid/raid_parser.c \
|
||||
device_mapper/regex/matcher.c \
|
||||
device_mapper/regex/parse_rx.c \
|
||||
device_mapper/regex/ttree.c \
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "base/data-struct/list.h"
|
||||
#include "base/data-struct/hash.h"
|
||||
#include "raid/target.h"
|
||||
#include "vdo/target.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
@@ -192,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 *info);
|
||||
int dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi);
|
||||
|
||||
/*
|
||||
* This function returns dm device's UUID based on the value
|
||||
@@ -1052,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 *vtp);
|
||||
const struct dm_vdo_target_params *param);
|
||||
|
||||
/*
|
||||
* FIXME Add individual cache policy pairs <key> = value, like:
|
||||
@@ -1179,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 *uuid,
|
||||
uint64_t offset);
|
||||
const char *dev_name,
|
||||
const char *dlid,
|
||||
uint64_t offset);
|
||||
|
||||
/*
|
||||
* Only for temporarily-missing raid devices where changes are tracked.
|
||||
@@ -1591,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 **result, const char *format, ...)
|
||||
int dm_asprintf(char **buf, const char *format, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
int dm_vasprintf(char **result, const char *format, va_list aq)
|
||||
int dm_vasprintf(char **buf, const char *format, va_list ap)
|
||||
__attribute__ ((format(printf, 2, 0)));
|
||||
|
||||
/*
|
||||
@@ -1942,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 *output_field_name_prefix);
|
||||
const char *report_prefix);
|
||||
|
||||
int dm_report_set_selection(struct dm_report *rh, const char *selection);
|
||||
|
||||
@@ -2082,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 *rem_node);
|
||||
int dm_config_remove_node(struct dm_config_node *parent, struct dm_config_node *remove);
|
||||
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);
|
||||
@@ -2114,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 *cn, int siblings);
|
||||
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_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);
|
||||
|
||||
@@ -486,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);
|
||||
}
|
||||
}
|
||||
@@ -495,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);
|
||||
}
|
||||
}
|
||||
@@ -770,7 +770,7 @@ static size_t _align_val(size_t val)
|
||||
}
|
||||
static void *_align_ptr(void *ptr)
|
||||
{
|
||||
return (void *)(uintptr_t)_align_val((size_t)ptr);
|
||||
return (void *)_align_val((size_t)ptr);
|
||||
}
|
||||
|
||||
static int _check_has_event_nr(void) {
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#ifndef LIB_DMTARGETS_H
|
||||
#define LIB_DMTARGETS_H
|
||||
|
||||
#include "device_mapper/all.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2025 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
@@ -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 + 1];
|
||||
char str_rest[DM_NAME_LEN];
|
||||
size_t i, j;
|
||||
unsigned int code;
|
||||
int r = 0;
|
||||
@@ -1044,19 +1044,12 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct stat info;
|
||||
struct stat linfo;
|
||||
dev_t dev = MKDEV(major, minor);
|
||||
mode_t old_mask;
|
||||
|
||||
if (!_build_dev_path(path, sizeof(path), dev_name))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* Check if the device node already exists.
|
||||
* Note: stat() follows symlinks, so this checks the target device,
|
||||
* not the symlink itself. This works correctly for both real nodes
|
||||
* and symlinks pointing to the right device.
|
||||
*/
|
||||
if (stat(path, &info) >= 0) {
|
||||
if (!S_ISBLK(info.st_mode)) {
|
||||
log_error("A non-block device file at '%s' "
|
||||
@@ -1065,71 +1058,16 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
|
||||
}
|
||||
|
||||
/* If right inode already exists we don't touch uid etc. */
|
||||
if (info.st_rdev == dev) {
|
||||
/*
|
||||
* Correct device exists (either as real node or symlink).
|
||||
* Use lstat() to distinguish between them for logging.
|
||||
*/
|
||||
if (lstat(path, &linfo) >= 0 && S_ISLNK(linfo.st_mode))
|
||||
log_debug_activation("Symlink %s to correct device already exists", path);
|
||||
if (info.st_rdev == dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlink(path) && (errno != ENOENT)) {
|
||||
log_sys_error("unlink", path);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* stat() failed. Check for dangling symlinks (where lstat succeeds
|
||||
* but stat fails with ENOENT because the symlink target doesn't exist).
|
||||
* Remove the dangling symlink before attempting to create a new node.
|
||||
*/
|
||||
if (errno == ENOENT && lstat(path, &linfo) >= 0 && S_ISLNK(linfo.st_mode)) {
|
||||
log_debug_activation("Removing dangling symlink %s", path);
|
||||
if (unlink(path) && (errno != ENOENT)) {
|
||||
log_sys_error("unlink", path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (_warn_if_op_needed(warn_if_udev_failed))
|
||||
log_warn("%s not set up by udev: Falling back to direct "
|
||||
"node creation.", path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test environment optimization: If using alternative dev dir (e.g., /tmp/LVMTEST/dev)
|
||||
* and the real /dev node already exists, create a symlink instead of a duplicate node.
|
||||
* This ensures operations trigger udev events which only monitors /dev.
|
||||
*/
|
||||
if (strcmp(_dm_dir, DEV_DIR) != 0) {
|
||||
char real_path[PATH_MAX];
|
||||
struct stat real_stat;
|
||||
|
||||
/* Build path to real /dev node (kernel always creates /dev/dm-N) */
|
||||
if (dm_snprintf(real_path, sizeof(real_path), DEV_DIR "dm-%u", minor) >= 0) {
|
||||
/* Check if real node exists with matching dev */
|
||||
if (stat(real_path, &real_stat) >= 0 &&
|
||||
S_ISBLK(real_stat.st_mode) &&
|
||||
real_stat.st_rdev == dev) {
|
||||
/*
|
||||
* Real /dev/dm-N exists. Create symlink from alternative location.
|
||||
* This allows operations to work through the symlink and trigger
|
||||
* udev events on the real device.
|
||||
*/
|
||||
log_debug_activation("Creating symlink %s -> %s", path, real_path);
|
||||
(void) dm_prepare_selinux_context(path, S_IFLNK);
|
||||
if (symlink(real_path, path) < 0) {
|
||||
log_sys_error("symlink", path);
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
(void) dm_prepare_selinux_context(NULL, 0);
|
||||
log_debug_activation("Created symlink %s -> %s", path, real_path);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_warn_if_op_needed(warn_if_udev_failed))
|
||||
log_warn("%s not set up by udev: Falling back to direct "
|
||||
"node creation.", path);
|
||||
|
||||
(void) dm_prepare_selinux_context(path, S_IFBLK);
|
||||
old_mask = umask(0);
|
||||
@@ -1894,27 +1832,32 @@ int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
|
||||
|
||||
static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t buf_size)
|
||||
{
|
||||
char sysfs_path[PATH_MAX], temp_buf[2 * DM_NAME_LEN];
|
||||
char *sysfs_path, *temp_buf = NULL;
|
||||
FILE *fp = NULL;
|
||||
int r = 0;
|
||||
size_t len;
|
||||
|
||||
if (dm_snprintf(sysfs_path, sizeof(sysfs_path),
|
||||
"%sdev/block/%" PRIu32 ":%" PRIu32
|
||||
if (!(sysfs_path = malloc(PATH_MAX)) ||
|
||||
!(temp_buf = malloc(PATH_MAX))) {
|
||||
log_error("_sysfs_get_dm_name: failed to allocate temporary buffers");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (dm_snprintf(sysfs_path, PATH_MAX, "%sdev/block/%" PRIu32 ":%" PRIu32
|
||||
"/dm/name", _sysfs_dir, major, minor) < 0) {
|
||||
log_error("_sysfs_get_dm_name: dm_snprintf failed.");
|
||||
log_error("_sysfs_get_dm_name: dm_snprintf failed");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(fp = fopen(sysfs_path, "r"))) {
|
||||
if (errno == ENOENT)
|
||||
log_sys_debug("fopen", sysfs_path);
|
||||
else
|
||||
if (errno != ENOENT)
|
||||
log_sys_error("fopen", sysfs_path);
|
||||
else
|
||||
log_sys_debug("fopen", sysfs_path);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!fgets(temp_buf, sizeof(temp_buf), fp)) {
|
||||
if (!fgets(temp_buf, PATH_MAX, fp)) {
|
||||
log_sys_error("fgets", sysfs_path);
|
||||
goto bad;
|
||||
}
|
||||
@@ -1922,21 +1865,20 @@ static int _sysfs_get_dm_name(uint32_t major, uint32_t minor, char *buf, size_t
|
||||
len = strlen(temp_buf);
|
||||
|
||||
if (len > buf_size) {
|
||||
log_error("_sysfs_get_dm_name: supplied buffer too small.");
|
||||
log_error("_sysfs_get_dm_name: supplied buffer too small");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (len)
|
||||
--len; /* strip \n */
|
||||
|
||||
memcpy(buf, temp_buf, len);
|
||||
buf[len] = '\0';
|
||||
|
||||
temp_buf[len ? len - 1 : 0] = '\0'; /* \n */
|
||||
strcpy(buf, temp_buf);
|
||||
r = 1;
|
||||
bad:
|
||||
if (fp && fclose(fp))
|
||||
log_sys_error("fclose", sysfs_path);
|
||||
|
||||
free(temp_buf);
|
||||
free(sysfs_path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 major, uint32_t minor,
|
||||
int add_dev_node(const char *dev_name, uint32_t minor, uint32_t major,
|
||||
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,
|
||||
|
||||
@@ -1069,6 +1069,9 @@ static const char *_find_config_str(const void *start, node_lookup_fn find_fn,
|
||||
log_warn("WARNING: Ignoring unsupported value for %s.", path);
|
||||
}
|
||||
|
||||
if (fail)
|
||||
log_very_verbose("%s not found in config: defaulting to \"%s\"",
|
||||
path, fail);
|
||||
return fail;
|
||||
}
|
||||
|
||||
@@ -1094,6 +1097,8 @@ static int64_t _find_config_int64(const void *start, node_lookup_fn find,
|
||||
return n->v->v.i;
|
||||
}
|
||||
|
||||
log_very_verbose("%s not found in config: defaulting to %" PRId64,
|
||||
path, fail);
|
||||
return fail;
|
||||
}
|
||||
|
||||
@@ -1107,6 +1112,9 @@ static float _find_config_float(const void *start, node_lookup_fn find,
|
||||
return n->v->v.f;
|
||||
}
|
||||
|
||||
log_very_verbose("%s not found in config: defaulting to %f",
|
||||
path, fail);
|
||||
|
||||
return fail;
|
||||
|
||||
}
|
||||
@@ -1161,6 +1169,9 @@ static int _find_config_bool(const void *start, node_lookup_fn find,
|
||||
}
|
||||
}
|
||||
|
||||
log_very_verbose("%s not found in config: defaulting to %d",
|
||||
path, fail);
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
@@ -1450,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 *cn, int sib)
|
||||
struct dm_config_node *dm_config_clone_node(struct dm_config_tree *cft, const struct dm_config_node *node, int sib)
|
||||
{
|
||||
return dm_config_clone_node_with_mem(cft->mem, cn, sib);
|
||||
return dm_config_clone_node_with_mem(cft->mem, node, sib);
|
||||
}
|
||||
|
||||
struct dm_config_node *dm_config_create_node(struct dm_config_tree *cft, const char *key)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "misc/dm-ioctl.h"
|
||||
#include "vdo/target.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
@@ -151,17 +152,15 @@ struct thin_message {
|
||||
struct load_segment {
|
||||
struct dm_list list;
|
||||
|
||||
uint64_t size;
|
||||
|
||||
unsigned type;
|
||||
|
||||
uint64_t size;
|
||||
|
||||
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 */
|
||||
@@ -169,6 +168,7 @@ 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,8 +540,7 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
|
||||
struct dm_tree_node *node;
|
||||
dev_t dev;
|
||||
|
||||
if (!dtree || !dtree->mem ||
|
||||
!(node = dm_pool_zalloc(dtree->mem, sizeof(*node))) ||
|
||||
if (!(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.");
|
||||
@@ -3362,26 +3361,9 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
|
||||
|
||||
/* Preload children first */
|
||||
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
|
||||
/* When a parent node (other than root) is inactive, we cannot delay
|
||||
* the resume of a new device.
|
||||
* For example, preloading a RAID table with a pvmoved leg requires the
|
||||
* leg LV to be active before loading the RAID LV, so the pvmove device must
|
||||
* be resumed immediately.
|
||||
* This scenario only occurs when neither the RAID nor pvmove device has
|
||||
* been instantiated yet. In this case, starting the pvmove device does
|
||||
* not leak access to the PV device without going through the mirror target.
|
||||
* However, if the RAID is already active and running, we can only preload
|
||||
* the new pvmove device, and a full suspend must occur before resuming
|
||||
* the new table with the running pvmove. So until the resume point
|
||||
* any IO is going through the existing table line and not via pvmove target.
|
||||
*/
|
||||
if ((child->props.delay_resume_if_new > 1) &&
|
||||
!dnode->info.exists &&
|
||||
(dnode != &dnode->dtree->root)) { /* Ignore when parent is root node */
|
||||
log_debug("%s with inactive parent cancels delay_resume_if_new.",
|
||||
_node_name(child));
|
||||
child->props.delay_resume_if_new = 0;
|
||||
}
|
||||
/* Propagate delay of resume from parent node */
|
||||
if (dnode->props.delay_resume_if_new > 1)
|
||||
child->props.delay_resume_if_new = dnode->props.delay_resume_if_new;
|
||||
|
||||
/* Skip existing non-device-mapper devices */
|
||||
if (!child->info.exists && child->info.major)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "base/memory/zalloc.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <langinfo.h>
|
||||
#include <math.h> /* fabs() */
|
||||
#include <float.h> /* DBL_EPSILON */
|
||||
#include <time.h>
|
||||
@@ -32,7 +31,6 @@
|
||||
|
||||
struct selection {
|
||||
struct dm_pool *mem;
|
||||
struct dm_pool *regex_mem;
|
||||
struct selection_node *selection_root;
|
||||
int add_new_fields;
|
||||
};
|
||||
@@ -206,9 +204,7 @@ static const struct op_def _op_log[] = {
|
||||
|
||||
struct selection_str_list {
|
||||
struct dm_str_list str_list;
|
||||
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 */
|
||||
unsigned type; /* either SEL_AND or SEL_OR */
|
||||
};
|
||||
|
||||
struct field_selection_value {
|
||||
@@ -551,7 +547,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 = zalloc(list_size * sizeof(struct str_pos_len)))) {
|
||||
if (!(arr = malloc(list_size * sizeof(struct str_pos_len)))) {
|
||||
log_error("%s failed to allocate temporary array for processing", _error_msg_prefix);
|
||||
goto out;
|
||||
}
|
||||
@@ -593,8 +589,7 @@ static int _report_field_string_list(struct dm_report *rh,
|
||||
for (i = 0, pos = 0; i < list_size; i++) {
|
||||
arr[i].item.pos = pos;
|
||||
|
||||
if (arr[i].str)
|
||||
memcpy(repstr + pos, arr[i].str, arr[i].item.len);
|
||||
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;
|
||||
@@ -1416,11 +1411,8 @@ 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);
|
||||
@@ -1759,74 +1751,8 @@ 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_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,
|
||||
static int _cmp_field_string_list_strict_all(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);
|
||||
@@ -1858,36 +1784,7 @@ static int _cmp_field_string_list_strict_all(const struct dm_report *rh,
|
||||
}
|
||||
|
||||
/* Matches if all items from selection string list match a subset of list value. */
|
||||
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,
|
||||
static int _cmp_field_string_list_subset_all(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);
|
||||
@@ -1922,26 +1819,8 @@ static int _cmp_field_string_list_subset_all(const struct dm_report *rh __attrib
|
||||
}
|
||||
|
||||
/* Matches if any item from selection string list matches list value. */
|
||||
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)
|
||||
static int _cmp_field_string_list_any(const struct str_list_sort_value *val,
|
||||
const struct selection_str_list *sel)
|
||||
{
|
||||
struct dm_str_list *sel_item;
|
||||
unsigned int i;
|
||||
@@ -1970,59 +1849,7 @@ static int _cmp_field_string_list_subset_any(const struct dm_report *rh __attrib
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
static int _cmp_field_string_list(struct dm_report *rh __attribute__((unused)),
|
||||
uint32_t field_num, const char *field_id,
|
||||
const struct str_list_sort_value *val,
|
||||
struct field_selection *fs)
|
||||
@@ -2044,16 +1871,11 @@ static int _cmp_field_string_list(struct dm_report *rh,
|
||||
|
||||
switch (sel->type & SEL_MASK) {
|
||||
case SEL_AND:
|
||||
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);
|
||||
r = subset ? _cmp_field_string_list_subset_all(val, sel)
|
||||
: _cmp_field_string_list_strict_all(val, sel);
|
||||
break;
|
||||
case SEL_OR:
|
||||
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);
|
||||
r = _cmp_field_string_list_any(val, sel);
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_cmp_field_string_list: unsupported string "
|
||||
@@ -2087,17 +1909,7 @@ static int _compare_selection_field(struct dm_report *rh,
|
||||
}
|
||||
|
||||
if (fs->flags & FLD_CMP_REGEX)
|
||||
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);
|
||||
}
|
||||
r = _cmp_field_regex((const char *) f->sort_value, fs);
|
||||
else {
|
||||
switch(f->props->flags & DM_REPORT_FIELD_TYPE_MASK) {
|
||||
case DM_REPORT_FIELD_TYPE_PERCENT:
|
||||
@@ -2124,8 +1936,7 @@ 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: incorrect type %" PRIu32 " for field %s",
|
||||
f->props->flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
log_error(INTERNAL_ERROR "_compare_selection_field: unknown field type for field %s", field_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2817,9 +2628,11 @@ 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)
|
||||
const char **end, uint32_t *flags,
|
||||
struct reserved_value_wrapper *rvw)
|
||||
{
|
||||
char c;
|
||||
rvw->reserved = NULL;
|
||||
|
||||
s = _skip_space(s);
|
||||
|
||||
@@ -2882,8 +2695,7 @@ 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,
|
||||
uint32_t *flags)
|
||||
struct selection_str_list **sel_str_list)
|
||||
{
|
||||
static const char _str_list_item_parsing_failed[] = "Failed to parse string list value "
|
||||
"for selection field %s.";
|
||||
@@ -2897,11 +2709,12 @@ static const char *_tok_value_string_list(const struct dm_report_field_type *ft,
|
||||
int list_end = 0;
|
||||
char c;
|
||||
|
||||
if (!(ssl = dm_pool_zalloc(mem, sizeof(*ssl)))) {
|
||||
log_error("_tok_value_string_list: memory allocation failed for selection list.");
|
||||
if (!(ssl = dm_pool_alloc(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))) {
|
||||
@@ -2913,7 +2726,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_SUBSET_LS;
|
||||
ssl->type = SEL_OR | SEL_LIST_LS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2988,17 +2801,12 @@ 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;
|
||||
@@ -3327,9 +3135,7 @@ static int _local_tz_offset(time_t t_local)
|
||||
time_t t_gmt;
|
||||
|
||||
gmtime_r(&t_local, &tm_gmt);
|
||||
|
||||
if ((t_gmt = mktime(&tm_gmt)) < 0)
|
||||
return 0;
|
||||
t_gmt = mktime(&tm_gmt);
|
||||
|
||||
/*
|
||||
* gmtime returns time that is adjusted
|
||||
@@ -3340,7 +3146,7 @@ static int _local_tz_offset(time_t t_local)
|
||||
if (tm_gmt.tm_isdst)
|
||||
t_gmt -= 3600;
|
||||
|
||||
return (int)(t_local - t_gmt);
|
||||
return t_local - t_gmt;
|
||||
}
|
||||
|
||||
static void _get_final_time(time_range_t range, struct tm *tm,
|
||||
@@ -3516,10 +3322,7 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
|
||||
s = _skip_space(s);
|
||||
|
||||
/* 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);
|
||||
|
||||
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,
|
||||
@@ -3530,24 +3333,17 @@ 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:
|
||||
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;
|
||||
}
|
||||
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;
|
||||
@@ -3556,7 +3352,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, flags);
|
||||
s = _tok_value_string_list(ft, mem, s, begin, end, str_list);
|
||||
if (!(*str_list)) {
|
||||
log_error("Failed to parse string list value "
|
||||
"for selection field %s.", ft->id);
|
||||
@@ -3640,7 +3436,7 @@ static const char *_tok_value(struct dm_report *rh,
|
||||
|
||||
return s;
|
||||
bad:
|
||||
log_error(INTERNAL_ERROR "_tok_value: Forbidden NULL custom parameter detected.");
|
||||
log_error(INTERNAL_ERROR "Forbidden NULL custom detected.");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -3711,19 +3507,6 @@ 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,
|
||||
@@ -3741,11 +3524,6 @@ 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)) {
|
||||
@@ -3810,55 +3588,20 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
/* store comparison operand */
|
||||
if (flags & FLD_CMP_REGEX) {
|
||||
/* REGEX */
|
||||
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;
|
||||
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';
|
||||
|
||||
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);
|
||||
|
||||
if (!(s_arr_size = dm_list_size(&fs->value->v.l->str_list.list)))
|
||||
break;
|
||||
|
||||
if (!(s_arr = calloc(s_arr_size, sizeof(char *)))) {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
/* STRING, NUMBER, SIZE, PERCENT, STRING_LIST, TIME */
|
||||
@@ -3972,8 +3715,8 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: incorrect type %" PRIu32 " for field %s",
|
||||
flags & DM_REPORT_FIELD_TYPE_MASK, field_id);
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: "
|
||||
"unknown type of selection field %s", field_id);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
@@ -3984,7 +3727,7 @@ error_field_id:
|
||||
field_id);
|
||||
goto error;
|
||||
bad:
|
||||
log_error(INTERNAL_ERROR "_create_field_selection: Forbidden NULL custom detected.");
|
||||
log_error(INTERNAL_ERROR "Forbidden NULL custom detected.");
|
||||
error:
|
||||
dm_pool_free(rh->selection->mem, fs);
|
||||
|
||||
@@ -4078,11 +3821,8 @@ out_reserved_values:
|
||||
log_warn(" ");
|
||||
}
|
||||
|
||||
static void _parse_syntax_error(const char *s)
|
||||
{
|
||||
log_error("Selection syntax error at '%s'.", s);
|
||||
log_error("Use \'help\' for selection to get more help.");
|
||||
}
|
||||
static const char _sel_syntax_error_at_msg[] = "Selection syntax error at '%s'.";
|
||||
static const char _sel_help_ref_msg[] = "Use \'help\' for selection to get more help.";
|
||||
|
||||
/*
|
||||
* Selection parser
|
||||
@@ -4123,7 +3863,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
char *tmp;
|
||||
char c;
|
||||
|
||||
/* get field name */
|
||||
/* field name */
|
||||
if (!(last = _tok_field_name(s, &ws, &we))) {
|
||||
log_error("Expecting field name");
|
||||
goto bad;
|
||||
@@ -4156,7 +3896,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
} else
|
||||
ft = &rh->fields[field_num];
|
||||
|
||||
/* get comparison operator */
|
||||
/* comparison operator */
|
||||
if (!(flags = _tok_op_cmp(we, &last))) {
|
||||
_display_selection_help(rh);
|
||||
log_error("Unrecognised comparison operator: %s", we);
|
||||
@@ -4168,49 +3908,50 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* check we can use the operator with the field */
|
||||
/* comparison value */
|
||||
if (flags & FLD_CMP_REGEX) {
|
||||
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;
|
||||
/*
|
||||
* 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_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 */
|
||||
@@ -4226,7 +3967,8 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
|
||||
|
||||
return sn;
|
||||
bad:
|
||||
_parse_syntax_error(s);
|
||||
log_error(_sel_syntax_error_at_msg, s);
|
||||
log_error(_sel_help_ref_msg);
|
||||
*next = s;
|
||||
return NULL;
|
||||
}
|
||||
@@ -4350,7 +4092,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", 1024))) {
|
||||
!(rh->selection->mem = dm_pool_create("report selection", 10 * 1024))) {
|
||||
log_error("Failed to allocate report selection structure.");
|
||||
if (rh->selection)
|
||||
dm_pool_free(rh->mem, rh->selection);
|
||||
@@ -4391,7 +4133,8 @@ static int _report_set_selection(struct dm_report *rh, const char *selection, in
|
||||
next = _skip_space(fin);
|
||||
if (*next) {
|
||||
log_error("Expecting logical operator");
|
||||
_parse_syntax_error(next);
|
||||
log_error(_sel_syntax_error_at_msg, next);
|
||||
log_error(_sel_help_ref_msg);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@@ -4671,12 +4414,9 @@ static int _sort_rows(struct dm_report *rh)
|
||||
struct row *(*rows)[];
|
||||
uint32_t count = 0;
|
||||
struct row *row;
|
||||
size_t cnt_rows;
|
||||
|
||||
if (!(cnt_rows = dm_list_size(&rh->rows)))
|
||||
return 1; /* nothing to sort */
|
||||
|
||||
if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) * cnt_rows))) {
|
||||
if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) *
|
||||
dm_list_size(&rh->rows)))) {
|
||||
log_error("dm_report: sort array allocation failed");
|
||||
return 0;
|
||||
}
|
||||
@@ -4851,39 +4591,31 @@ bad:
|
||||
|
||||
static int _safe_repstr_output(struct dm_report *rh, const char *repstr, size_t len)
|
||||
{
|
||||
const char *repstr_next_write = repstr;
|
||||
const char *repstr_current = repstr;
|
||||
const char *p_repstr;
|
||||
const char *repstr_end = len ? repstr + len : repstr + strlen(repstr);
|
||||
|
||||
/* Escape any JSON_ESCAPE_CHAR and JSON_QUOTE that may appear in reported string. */
|
||||
while (repstr_current < repstr_end) {
|
||||
if (repstr_current[0] == JSON_ESCAPE_CHAR[0] || repstr_current[0] == JSON_QUOTE[0]) {
|
||||
// Write out all "sanitized" chars so far
|
||||
if (repstr_next_write < repstr_current) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr_next_write, repstr_current - repstr_next_write)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
/* Escape any JSON_QUOTE that may appear in reported string. */
|
||||
while (1) {
|
||||
if (!(p_repstr = memchr(repstr, JSON_QUOTE[0], repstr_end - repstr)))
|
||||
break;
|
||||
|
||||
repstr_next_write = repstr_current;
|
||||
}
|
||||
|
||||
// Add an escape
|
||||
if (!dm_pool_grow_object(rh->mem, JSON_ESCAPE_CHAR, 1)) {
|
||||
if (p_repstr > repstr) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr, p_repstr - repstr)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
++repstr_current;
|
||||
}
|
||||
|
||||
// Write out all remaining "sanitized" chars
|
||||
if (repstr_next_write < repstr_end) {
|
||||
if (!dm_pool_grow_object(rh->mem, repstr_next_write, repstr_end - repstr_next_write)) {
|
||||
if (!dm_pool_grow_object(rh->mem, JSON_ESCAPE_CHAR, 1) ||
|
||||
!dm_pool_grow_object(rh->mem, JSON_QUOTE, 1)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
repstr = p_repstr + 1;
|
||||
}
|
||||
|
||||
if (!dm_pool_grow_object(rh->mem, repstr, repstr_end - repstr)) {
|
||||
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -5367,15 +5099,6 @@ struct dm_report_group *dm_report_group_create(dm_report_group_type_t type, void
|
||||
struct dm_pool *mem;
|
||||
struct report_group_item *item;
|
||||
|
||||
if (type == DM_REPORT_GROUP_JSON_STD) {
|
||||
const char * radixchar = nl_langinfo(RADIXCHAR);
|
||||
if (radixchar && strcmp(radixchar, ".")) {
|
||||
log_error("dm_report: incompatible locale used for DM_REPORT_GROUP_JSON_STD, "
|
||||
"radix character is '%s', expected '.'", radixchar);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mem = dm_pool_create("report_group", 1024))) {
|
||||
log_error("dm_report: dm_report_init_group: failed to allocate mem pool");
|
||||
return NULL;
|
||||
|
||||
@@ -169,7 +169,7 @@ int dm_vasprintf(char **result, const char *format, va_list aq)
|
||||
}
|
||||
|
||||
if (i > 1) {
|
||||
/* Reallocating more than once? */
|
||||
/* Reallocating more then 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 than 1.9949G prints <2.00G
|
||||
* i.e. 2043M is more then 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 than real number of legs in a case
|
||||
/* Raid target can actually report more then 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;
|
||||
@@ -335,19 +335,11 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
|
||||
|
||||
/* Read in policy args */
|
||||
pp = p;
|
||||
if (!(p = _skip_fields(p, 1)))
|
||||
goto_bad;
|
||||
|
||||
i = p - pp;
|
||||
if ((i < 1) ||
|
||||
!(s->policy_name = dm_pool_zalloc(mem, i)))
|
||||
goto_bad;
|
||||
|
||||
dm_strncpy(s->policy_name, pp, i);
|
||||
|
||||
if (sscanf(p, "%d", &s->policy_argc) != 1)
|
||||
if (!(p = _skip_fields(p, 1)) ||
|
||||
!(s->policy_name = dm_pool_zalloc(mem, (p - pp))))
|
||||
goto bad;
|
||||
if (sscanf(pp, "%s %d", s->policy_name, &s->policy_argc) != 2)
|
||||
goto bad;
|
||||
|
||||
if (s->policy_argc &&
|
||||
(!(s->policy_argv = dm_pool_zalloc(mem, sizeof(char *) * s->policy_argc)) ||
|
||||
!(p = _skip_fields(p, 1)) ||
|
||||
@@ -409,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 %15s",
|
||||
if (sscanf(params, "%llu %llu %s",
|
||||
(unsigned long long *)&s->number_of_mismatches,
|
||||
(unsigned long long *)&s->provided_data_sectors,
|
||||
recalc_str) != 3) {
|
||||
@@ -579,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 than " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
|
||||
log_error(INTERNAL_ERROR "More then " DM_TO_STRING(DM_MIRROR_MAX_IMAGES)
|
||||
" reported in mirror status.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
# 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,8 +13,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "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"
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support counting number of failed device bits in dm-raid superblock bit arrays or clear them out.
|
||||
*/
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "device_mapper/all.h"
|
||||
#include "device_mapper/raid/target.h"
|
||||
#include "lib/mm/xlate.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Copied/derived from kernel's drivers/md/dm-raid.c so this is prone to out-of-sync (factor out to header file?). */
|
||||
#define MAX_RAID_DEVICES 253 /* md-raid kernel limit? */
|
||||
#define UINT64_BITS (sizeof(uint64_t) * 8)
|
||||
#define DISKS_ARRAY_ELEMS ((MAX_RAID_DEVICES + (UINT64_BITS - 1)) / UINT64_BITS)
|
||||
#define DM_RAID_SB_MAGIC 0x446D5264 /* "DmRd" */
|
||||
#define FEATURE_FLAG_SUPPORTS_V190 0x1 /* Supports extended superblock */
|
||||
|
||||
/* RAID superblock at beginning of rmeta SubLVs trimmed down to mandatory members. */
|
||||
struct dm_raid_superblock {
|
||||
__le32 magic; /* "DmRd" */
|
||||
__le32 compat_features; /* Used to indicate compatible features (like 1.9.0 ondisk metadata extension) */
|
||||
__le32 dummy[4];
|
||||
__le64 failed_devices; /* Pre 1.9.0 part of bit field of devices to */
|
||||
/* indicate device failures (see extension below) */
|
||||
__le32 dummy1[7];
|
||||
|
||||
/********************************************************************
|
||||
* BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
|
||||
*
|
||||
* FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
|
||||
*/
|
||||
__le32 flags; /* Flags defining array states for reshaping */
|
||||
__le32 dummy2[14];
|
||||
__le64 extended_failed_devices[DISKS_ARRAY_ELEMS - 1];
|
||||
|
||||
__le32 dummy3;
|
||||
/* Always set rest up to logical block size to 0 when writing ... */
|
||||
} __packed;
|
||||
/* END: Copied from ... */
|
||||
|
||||
/* Superblock I/O buffer size to be able to Cope with 4K native devices... */
|
||||
#define SB_BUFSZ 4096
|
||||
|
||||
static size_t _get_sb_size(const struct dm_raid_superblock *sb)
|
||||
{
|
||||
return (FEATURE_FLAG_SUPPORTS_V190 & le32toh(sb->compat_features)) ?
|
||||
sizeof(*sb) : ((char *) &sb->flags - (char *) sb);
|
||||
}
|
||||
|
||||
static uint32_t _hweight64(__le64 v)
|
||||
{
|
||||
uint32_t r = 0;
|
||||
|
||||
while (v) {
|
||||
r += v & 1;
|
||||
v >>= 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint32_t _hweight_failed(struct dm_raid_superblock *sb)
|
||||
{
|
||||
uint32_t r = _hweight64(sb->failed_devices);
|
||||
|
||||
if (_get_sb_size(sb) == sizeof(*sb)) {
|
||||
int i = (int)DM_ARRAY_SIZE(sb->extended_failed_devices);
|
||||
|
||||
while (i--)
|
||||
r = max(r, _hweight64(sb->extended_failed_devices[i]));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void _clear_failed_devices(struct dm_raid_superblock *sb)
|
||||
{
|
||||
|
||||
sb->failed_devices = 0;
|
||||
|
||||
if (_get_sb_size(sb) == sizeof(*sb))
|
||||
memset(sb->extended_failed_devices, 0, sizeof(sb->extended_failed_devices));
|
||||
}
|
||||
|
||||
static int _count_or_clear_failed_devices(const char *dev_path, bool clear, uint32_t *nr_failed)
|
||||
{
|
||||
struct dm_raid_superblock *sb = NULL;
|
||||
size_t sz;
|
||||
int fd, r = 0;
|
||||
|
||||
if (posix_memalign((void *) &sb, SB_BUFSZ, SB_BUFSZ)) {
|
||||
log_sys_error("Failed to allocate RAID superblock buffer", dev_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open(dev_path, O_EXCL | ((clear) ? O_RDWR : O_RDONLY) | O_DIRECT);
|
||||
if (fd < 0) {
|
||||
log_sys_error("Failed to open RAID metadata volume", dev_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (read(fd, sb, SB_BUFSZ) != SB_BUFSZ) {
|
||||
log_sys_error("Failed to read RAID metadata volume", dev_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* FIXME: big endian??? */
|
||||
if (sb->magic != htobe32(DM_RAID_SB_MAGIC)) {
|
||||
log_error("No RAID signature on %s.", dev_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nr_failed)
|
||||
*nr_failed = _hweight_failed(sb);
|
||||
|
||||
if (clear) {
|
||||
if (lseek(fd, 0, SEEK_SET) < 0) {
|
||||
log_sys_error("Failed to seek RAID metadata volume", dev_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sz = _get_sb_size(sb);
|
||||
memset((void *)((char *) sb + sz), 0, SB_BUFSZ - sz);
|
||||
_clear_failed_devices(sb);
|
||||
if (write(fd, sb, SB_BUFSZ) != SB_BUFSZ) {
|
||||
log_sys_error("Failed to clear RAID metadata volume", dev_path);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
if ((fd >= 0) && close(fd))
|
||||
log_sys_debug("close", dev_path);
|
||||
|
||||
free(sb);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_raid_count_failed_devices(const char *dev_path, uint32_t *nr_failed)
|
||||
{
|
||||
return _count_or_clear_failed_devices(dev_path, false, nr_failed);
|
||||
}
|
||||
|
||||
int dm_raid_clear_failed_devices(const char *dev_path, uint32_t *nr_failed)
|
||||
{
|
||||
return _count_or_clear_failed_devices(dev_path, true, nr_failed);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use,
|
||||
* modify, copy, or redistribute it subject to the terms and conditions
|
||||
* of the GNU Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef DEVICE_MAPPER_RAID_TARGET_H
|
||||
#define DEVICE_MAPPER_RAID_TARGET_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int dm_raid_count_failed_devices(const char *dev_path, uint32_t *nr_failed);
|
||||
int dm_raid_clear_failed_devices(const char *dev_path, uint32_t *nr_failed);
|
||||
|
||||
#endif
|
||||
@@ -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 + 1) < num_patterns)
|
||||
if (i < (num_patterns - 1))
|
||||
*ptr++ = '|';
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "parse_rx.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#ifndef _DM_PARSE_REGEX_H
|
||||
#define _DM_PARSE_REGEX_H
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
|
||||
enum {
|
||||
CAT,
|
||||
STAR,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "device_mapper/misc/dmlib.h"
|
||||
#include "ttree.h"
|
||||
|
||||
struct node {
|
||||
@@ -83,7 +84,9 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
|
||||
} while (*c && count);
|
||||
|
||||
if (!*c) {
|
||||
do {
|
||||
count++;
|
||||
|
||||
while (count--) {
|
||||
if (!(*c = _tree_node(tt->mem, k)))
|
||||
return_0;
|
||||
|
||||
@@ -91,7 +94,7 @@ int ttree_insert(struct ttree *tt, unsigned int *key, void *data)
|
||||
k = *key++;
|
||||
c = &((*c)->m);
|
||||
}
|
||||
} while (count--);
|
||||
}
|
||||
}
|
||||
(*c)->data = data;
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#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);
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
#include "target.h"
|
||||
|
||||
#include "lib/mm/xlate.h"
|
||||
//#include "linux/byteorder/big_endian.h"
|
||||
//#include "linux/byteorder/little_endian.h"
|
||||
//#define le32_to_cpu __le32_to_cpu
|
||||
//#define le64_to_cpu __le64_to_cpu
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -67,7 +72,7 @@ enum {
|
||||
struct vdo_header {
|
||||
uint32_t id; /* The component this is a header for */
|
||||
struct vdo_version_number version; /* The version of the data format */
|
||||
uint64_t size; /* The size of the data following this header */
|
||||
size_t size; /* The size of the data following this header */
|
||||
} __packed;
|
||||
|
||||
struct vdo_geometry_block {
|
||||
@@ -135,36 +140,36 @@ struct vdo_volume_geometry_4 {
|
||||
|
||||
static void _vdo_decode_version(struct vdo_version_number *v)
|
||||
{
|
||||
v->major_version = le32toh(v->major_version);
|
||||
v->minor_version = le32toh(v->minor_version);
|
||||
v->major_version = le32_to_cpu(v->major_version);
|
||||
v->minor_version = le32_to_cpu(v->minor_version);
|
||||
}
|
||||
|
||||
static void _vdo_decode_header(struct vdo_header *h)
|
||||
{
|
||||
h->id = le32toh(h->id);
|
||||
h->id = le32_to_cpu(h->id);
|
||||
_vdo_decode_version(&h->version);
|
||||
h->size = le64toh(h->size);
|
||||
h->size = le64_to_cpu(h->size);
|
||||
}
|
||||
|
||||
static void _vdo_decode_geometry_region(struct vdo_volume_region *vr)
|
||||
{
|
||||
vr->id = (enum vdo_volume_region_id) le32toh(vr->id);
|
||||
vr->start_block = le64toh(vr->start_block);
|
||||
vr->id = le32_to_cpu(vr->id);
|
||||
vr->start_block = le64_to_cpu(vr->start_block);
|
||||
}
|
||||
|
||||
static void _vdo_decode_volume_geometry(struct vdo_volume_geometry *vg)
|
||||
{
|
||||
vg->release_version = le32toh(vg->release_version);
|
||||
vg->nonce = le64toh(vg->nonce);
|
||||
vg->bio_offset = le64toh(vg->bio_offset);
|
||||
vg->release_version = le32_to_cpu(vg->release_version);
|
||||
vg->nonce = le64_to_cpu(vg->nonce);
|
||||
vg->bio_offset = le64_to_cpu(vg->bio_offset);
|
||||
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
|
||||
}
|
||||
|
||||
static void _vdo_decode_volume_geometry_4(struct vdo_volume_geometry *vg,
|
||||
struct vdo_volume_geometry_4 *vg_4)
|
||||
{
|
||||
vg->release_version = le32toh(vg_4->release_version);
|
||||
vg->nonce = le64toh(vg_4->nonce);
|
||||
vg->release_version = le32_to_cpu(vg_4->release_version);
|
||||
vg->nonce = le64_to_cpu(vg_4->nonce);
|
||||
vg->bio_offset = 0;
|
||||
vg->regions[VDO_DATA_REGION] = vg_4->regions[VDO_DATA_REGION];
|
||||
_vdo_decode_geometry_region(&vg->regions[VDO_DATA_REGION]);
|
||||
@@ -172,17 +177,17 @@ static void _vdo_decode_volume_geometry_4(struct vdo_volume_geometry *vg,
|
||||
|
||||
static void _vdo_decode_config(struct vdo_config *vc)
|
||||
{
|
||||
vc->logical_blocks = le64toh(vc->logical_blocks);
|
||||
vc->physical_blocks = le64toh(vc->physical_blocks);
|
||||
vc->slab_size = le64toh(vc->slab_size);
|
||||
vc->recovery_journal_size = le64toh(vc->recovery_journal_size);
|
||||
vc->slab_journal_blocks = le64toh(vc->slab_journal_blocks);
|
||||
vc->logical_blocks = le64_to_cpu(vc->logical_blocks);
|
||||
vc->physical_blocks = le64_to_cpu(vc->physical_blocks);
|
||||
vc->slab_size = le64_to_cpu(vc->slab_size);
|
||||
vc->recovery_journal_size = le64_to_cpu(vc->recovery_journal_size);
|
||||
vc->slab_journal_blocks = le64_to_cpu(vc->slab_journal_blocks);
|
||||
}
|
||||
|
||||
static void _vdo_decode_pvc(struct vdo_component_41_0 *pvc)
|
||||
{
|
||||
_vdo_decode_config(&pvc->config);
|
||||
pvc->nonce = le64toh(pvc->nonce);
|
||||
pvc->nonce = le64_to_cpu(pvc->nonce);
|
||||
}
|
||||
|
||||
bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
|
||||
|
||||
@@ -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" show="2" rootpage="release-notes"]]
|
||||
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
|
||||
|
||||
[[More releases|release-notes/index]]
|
||||
|
||||
@@ -72,7 +72,6 @@ incorrectly!
|
||||
|
||||
Make one by running `pvcreate /dev/sdX`.
|
||||
See [pvcreate(8)](https://man7.org/linux/man-pages/man8/pvcreate.8.html). This step is optional.
|
||||
|
||||
* Volume Group (VG) consisting of one or more PVs is used as a pool from which LVs are allocated.
|
||||
List VGs using [vgs(8)](https://man7.org/linux/man-pages/man8/vgs.8.html) or
|
||||
[vgdisplay(8)](https://man7.org/linux/man-pages/man8/vgdisplay.8.html).
|
||||
@@ -81,34 +80,27 @@ incorrectly!
|
||||
To use LVM at least one Volume Group must be present on the system.
|
||||
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html), and
|
||||
[vgextend(8)](https://man7.org/linux/man-pages/man8/vgextend.8.html).
|
||||
|
||||
* Logical Volume (LV) is the block device usually visible to user to be used for file system.
|
||||
List LVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
|
||||
List PVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
|
||||
[lvdisplay(8)](https://man7.org/linux/man-pages/man8/lvdisplay.8.html).
|
||||
|
||||
Make one by running `lvcreate [-n LVNAME] -L SIZE VGNAME`, and you are done!
|
||||
See [lvcreate(8)](https://man7.org/linux/man-pages/man8/lvcreate.8.html).
|
||||
|
||||
To change size of LV it is recommended to use [lvresize(8)](https://man7.org/linux/man-pages/man8/lvresize.8.html) with `--resizefs` option.
|
||||
|
||||
To change properties of LV (e.g. to activate/deactivate a volume, or change it to read only) use [lvchange(8)](https://man7.org/linux/man-pages/man8/lvchange.8.html).
|
||||
|
||||
To change the type of LV (e.g. change a linear volume to a RAID) use [lvconvert(8)](https://man7.org/linux/man-pages/man8/lvconvert.8.html).
|
||||
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html).
|
||||
|
||||
## Avoiding Problems
|
||||
|
||||
Good start is to **avoid using `{--force|-f}` and `{--yes|-y}` options** which are
|
||||
Good start is to avoid using `{--force|-f}` and `{--yes|-y}` options which are
|
||||
often seen on internet discussions.
|
||||
there is a possibility of data loss, LVM tools usually ask, so read the prompts
|
||||
carefully! Using `--yes` removes these safety.
|
||||
Also in some cases where it is too dangerous to proceed, e.g. device is used,
|
||||
LVM refuses to do so, which can be overridden by `--force`.
|
||||
|
||||
Second, when **resizing** and especially when shrinking LVs it is always a good
|
||||
idea to **use `--resizefs` option** which ensures the devices are resized in
|
||||
Second, when resizing and especially when shrinking LVs it is always a good
|
||||
idea to use `--resizefs` option which ensures the devices are resized in
|
||||
correct order.
|
||||
|
||||
Third, if you still make a mess, **never ever run fsck on damaged LV/FS**, this is
|
||||
Third, if you still make a mess, never ever run fsck on damaged LV/FS, this is
|
||||
usually the final blow to your data. It is always better to ask first!
|
||||
|
||||
|
||||
|
||||
208
doc/lvmetad_design.txt
Normal file
208
doc/lvmetad_design.txt
Normal file
@@ -0,0 +1,208 @@
|
||||
The design of LVMetaD
|
||||
=====================
|
||||
|
||||
Invocation and setup
|
||||
--------------------
|
||||
|
||||
The daemon should be started automatically by the first LVM command issued on
|
||||
the system, when needed. The usage of the daemon should be configurable in
|
||||
lvm.conf, probably with its own section. Say
|
||||
|
||||
lvmetad {
|
||||
enabled = 1 # default
|
||||
autostart = 1 # default
|
||||
socket = "/path/to/socket" # defaults to /var/run/lvmetad or such
|
||||
}
|
||||
|
||||
Library integration
|
||||
-------------------
|
||||
|
||||
When a command needs to access metadata, it currently needs to perform a scan
|
||||
of the physical devices available in the system. This is a possibly quite
|
||||
expensive operation, especially if many devices are attached to the system. In
|
||||
most cases, LVM needs a complete image of the system's PVs to operate
|
||||
correctly, so all devices need to be read, to at least determine presence (and
|
||||
content) of a PV label. Additional IO is done to obtain or write metadata
|
||||
areas, but this is only marginally related and addressed by Dave's
|
||||
metadata-balancing work.
|
||||
|
||||
In the existing scanning code, a cache layer exists, under
|
||||
lib/cache/lvmcache.[hc]. This layer is keeping a textual copy of the metadata
|
||||
for a given volume group, in a format_text form, as a character string. We can
|
||||
plug the lvmetad interface at this level: in lvmcache_get_vg, which is
|
||||
responsible for looking up metadata in a local cache, we can, if the metadata
|
||||
is not available in the local cache, query lvmetad. Under normal circumstances,
|
||||
when a VG is not cached yet, this operation fails and prompts the caller to
|
||||
perform a scan. Under the lvmetad enabled scenario, this would never happen and
|
||||
the fall-through would only be activated when lvmetad is disabled, which would
|
||||
lead to local cache being populated as usual through a locally executed scan.
|
||||
|
||||
Therefore, existing stand-alone (i.e. no lvmetad) functionality of the tools
|
||||
would be not compromised by adding lvmetad. With lvmetad enabled, however,
|
||||
significant portions of the code would be short-circuited.
|
||||
|
||||
Scanning
|
||||
--------
|
||||
|
||||
Initially (at least), the lvmetad will be not allowed to read disks: it will
|
||||
rely on an external program to provide the metadata. In the ideal case, this
|
||||
will be triggered by udev. The role of lvmetad is then to collect and maintain
|
||||
an accurate (up to the data it has received) image of the VGs available in the
|
||||
system. I imagine we could extend the pvscan command (or add a new one, say
|
||||
lvmetad_client, if pvscan is found to be inappropriate):
|
||||
|
||||
$ pvscan --cache /dev/foo
|
||||
$ pvscan --cache --remove /dev/foo
|
||||
|
||||
These commands would simply read the label and the MDA (if applicable) from the
|
||||
given PV and feed that data to the running lvmetad, using
|
||||
lvmetad_{add,remove}_pv (see lvmetad_client.h).
|
||||
|
||||
We however need to ensure a couple of things here:
|
||||
|
||||
1) only LVM commands ever touch PV labels and VG metadata
|
||||
2) when a device is added or removed, udev fires a rule to notify lvmetad
|
||||
|
||||
While the latter is straightforward, there are issues with the first. We
|
||||
*might* want to invoke the dreaded "watch" udev rule in this case, however it
|
||||
ends up being implemented. Of course, we can also rely on the sysadmin to be
|
||||
reasonable and not write over existing LVM metadata without first telling LVM
|
||||
to let go of the respective device(s).
|
||||
|
||||
Even if we simply ignore the problem, metadata write should fail in these
|
||||
cases, so the admin should be unable to do substantial damage to the system. If
|
||||
there were active LVs on top of the vanished PV, they are in trouble no matter
|
||||
what happens there.
|
||||
|
||||
Incremental scan
|
||||
----------------
|
||||
|
||||
There are some new issues arising with the "udev" scan mode. Namely, the
|
||||
devices of a volume group will be appearing one by one. The behaviour in this
|
||||
case will be very similar to the current behaviour when devices are missing:
|
||||
the volume group, until *all* its physical volumes have been discovered and
|
||||
announced by udev, will be in a state with some of its devices flagged as
|
||||
MISSING_PV. This means that the volume group will be, for most purposes,
|
||||
read-only until it is complete and LVs residing on yet-unknown PVs won't
|
||||
activate without --partial. Under usual circumstances, this is not a problem
|
||||
and the current code for dealing with MISSING_PVs should be adequate.
|
||||
|
||||
However, the code for reading volume groups from disks will need to be adapted,
|
||||
since it currently does not work incrementally. Such support will need to track
|
||||
metadata-less PVs that have been encountered so far and to provide a way to
|
||||
update an existing volume group. When the first PV with metadata of a given VG
|
||||
is encountered, the VG is created in lvmetad (probably in the form of "struct
|
||||
volume_group") and it is assigned any previously cached metadata-less PVs it is
|
||||
referencing. Any PVs that were not yet encountered will be marked as MISSING_PV
|
||||
in the "struct volume_group". Upon scanning a new PV, if it belongs to any
|
||||
already-known volume group, this PV is checked for consistency with the already
|
||||
cached metadata (in a case of mismatch, the VG needs to be recovered or
|
||||
declared conflicted), and is subsequently unmarked MISSING_PV. Care need be
|
||||
taken not to unmark MISSING_PV on PVs that have this flag in their persistent
|
||||
metadata, though.
|
||||
|
||||
The most problematic aspect of the whole design may be orphan PVs. At any given
|
||||
point, a metadata-less PV may appear orphaned, if a PV of its VG with metadata
|
||||
has not been scanned yet. Eventually, we will have to decide that this PV is
|
||||
really an orphan and enable its usage for creating or extending VGs. In
|
||||
practice, the decision might be governed by a timeout or assumed immediately --
|
||||
the former case is a little safer, the latter is probably more transparent. I
|
||||
am not very keen on using timeouts and we can probably assume that the admin
|
||||
won't blindly try to reuse devices in a way that would trip up LVM in this
|
||||
respect. I would be in favour of just assuming that metadata-less VGs with no
|
||||
known referencing VGs are orphans -- after all, this is the same approach as we
|
||||
use today. The metadata balancing support may stress this a bit more than the
|
||||
usual contemporary setups do, though.
|
||||
|
||||
Automatic activation
|
||||
--------------------
|
||||
|
||||
It may also be prudent to provide a command that will block until a volume
|
||||
group is complete, so that scripts can reliably activate/mount LVs and such. Of
|
||||
course, some PVs may never appear, so a timeout is necessary. Again, this is
|
||||
something not handled by current tools, but may become more important in
|
||||
future. It probably does not need to be implemented right away though.
|
||||
|
||||
The other aspect of the progressive VG assembly is automatic activation. The
|
||||
currently only problem with that is that we would like to avoid having
|
||||
activation code in lvmetad, so we would prefer to fire up an event of some sort
|
||||
and let someone else handle the activation and whatnot.
|
||||
|
||||
Cluster support
|
||||
---------------
|
||||
|
||||
When working in a cluster, clvmd integration will be necessary: clvmd will need
|
||||
to instruct lvmetad to re-read metadata as appropriate due to writes on remote
|
||||
hosts. Overall, this is not hard, but the devil is in the details. I would
|
||||
possibly disable lvmetad for clustered volume groups in the first phase and
|
||||
only proceed when the local mode is robust and well tested.
|
||||
|
||||
With lvmlockd, lvmetad state is kept up to date by flagging either an
|
||||
individual VG as "invalid", or the global state as "invalid". When either
|
||||
the VG or the global state are read, this invalid flag is returned along
|
||||
with the data. The client command can check for this invalid state and
|
||||
decide to read the information from disk rather than use the stale cached
|
||||
data. After the latest data is read from disk, the command may choose to
|
||||
send it to lvmetad to update the cache. lvmlockd uses version numbers
|
||||
embedded in its VG and global locks to detect when cached data becomes
|
||||
invalid, and it then tells lvmetad to set the related invalid flag.
|
||||
dct, 2015-06-23
|
||||
|
||||
Protocol & co.
|
||||
--------------
|
||||
|
||||
I expect a simple text-based protocol executed on top of an Unix Domain Socket
|
||||
to be the communication interface for lvmetad. Ideally, the requests and
|
||||
replies will be well-formed "config file" style strings, so we can reuse
|
||||
existing parsing infrastructure.
|
||||
|
||||
Since we already have two daemons, I would probably look into factoring some
|
||||
common code for daemon-y things, like sockets, communication (including thread
|
||||
management) and maybe logging and re-using it in all the daemons (clvmd,
|
||||
dmeventd and lvmetad). This shared infrastructure should live under
|
||||
daemons/common, and the existing daemons shall be gradually migrated to the
|
||||
shared code.
|
||||
|
||||
Future extensions
|
||||
-----------------
|
||||
|
||||
The above should basically cover the use of lvmetad as a cache-only
|
||||
daemon. Writes could still be executed locally, and the new metadata version
|
||||
can be provided to lvmetad through the socket the usual way. This is fairly
|
||||
natural and in my opinion reasonable. The lvmetad acts like a cache that will
|
||||
hold metadata, no more no less.
|
||||
|
||||
Above this, there is a couple of things that could be worked on later, when the
|
||||
above basic design is finished and implemented.
|
||||
|
||||
_Metadata writing_: We may want to support writing new metadata through
|
||||
lvmetad. This may or may not be a better design, but the write itself should be
|
||||
more or less orthogonal to the rest of the story outlined above.
|
||||
|
||||
_Locking_: Other than directing metadata writes through lvmetad, one could
|
||||
conceivably also track VG/LV locking through the same.
|
||||
|
||||
_Clustering_: A deeper integration of lvmetad with clvmd might be possible and
|
||||
maybe desirable. Since clvmd communicates over the network with other clvmd
|
||||
instances, this could be extended to metadata exchange between lvmetad's,
|
||||
further cutting down scanning costs. This would combine well with the
|
||||
write-through-lvmetad approach.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Since (at least bare-bones) lvmetad has no disk interaction and is fed metadata
|
||||
externally, it should be very amenable to automated testing. We need to provide
|
||||
a client that can feed arbitrary, synthetic metadata to the daemon and request
|
||||
the data back, providing reasonable (nearly unit-level) testing infrastructure.
|
||||
|
||||
Battle plan & code layout
|
||||
=========================
|
||||
|
||||
- config_tree from lib/config needs to move to libdm/
|
||||
- daemon/common *client* code can go to libdm/ as well (say
|
||||
libdm/libdm-daemon.{h,c} or such)
|
||||
- daemon/common *server* code stays, is built in daemon/ toplevel as a static
|
||||
library, say libdaemon-common.a
|
||||
- daemon/lvmetad *client* code goes to lib/lvmetad
|
||||
- daemon/lvmetad *server* code stays (links in daemon/libdaemon_common.a)
|
||||
@@ -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="Wed Oct 2 14:19:23 2024 +0200"]]
|
||||
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
|
||||
-->
|
||||
|
||||
|
||||
@@ -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="Mon Nov 4 16:42:12 2024 +0100"]]
|
||||
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
|
||||
-->
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<!-- 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"]]
|
||||
-->
|
||||
@@ -1,24 +0,0 @@
|
||||
<!-- 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"]]
|
||||
-->
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<!-- 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"]]
|
||||
-->
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.32 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.32
|
||||
===============
|
||||
|
||||
Mostly bugfix release:
|
||||
|
||||
* Add support for using regex in selection criteria for string lists.
|
||||
* Accept thin pool data LV as cacheable LV.
|
||||
* Accept `--autobackup` option in pvresize.
|
||||
* Allow using zram block devices (likely for testing).
|
||||
* Lvconvert vdopool conversion properly validates acceptable LVs.
|
||||
* 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.
|
||||
* Ignore PV claims from old metadata when then PV belongs to a new VG.
|
||||
* Fix integrity metadata rounding.
|
||||
* Fix string list selection when using `[<item> || <item> ...]`.
|
||||
|
||||
<!-- 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 May 05 17:02:00 2025 +0200"]]
|
||||
-->
|
||||
@@ -1,19 +0,0 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.33 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.33
|
||||
===============
|
||||
|
||||
Mostly bugfix release:
|
||||
|
||||
* Use `lvconvert --repair` to repair raid arrays with transiently lost devices.
|
||||
* Override `LC_NUMERIC` locale if unsuitable for `json_std` report format.
|
||||
* Fail `dm_report_group_create` if radix char from locale unsuitable for `json_std`.
|
||||
* Escape the escape character itself on JSON report format output.
|
||||
|
||||
<!-- 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="Fri Jun 27 10:14:00 2025 +0200"]]
|
||||
-->
|
||||
@@ -1,30 +0,0 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.34 - Bug Fix Release"]]
|
||||
|
||||
Version 2.03.34
|
||||
===============
|
||||
|
||||
Add *Persistent Reservations* and many mostly small fixes.
|
||||
|
||||
* **NEW** Add support for **persistent reservations** controlling access to shared PVs.
|
||||
* See [lvmpersist(8)](https://man7.org/linux/man-pages/man8/lvmpersist.8.html) for more details.
|
||||
* Add `lvmlockd --lockopt repair` to reinitialize corrupted sanlock leases.
|
||||
* Add *lvm.conf* `global/lvresize_fs_helper_executable`.
|
||||
* Fix lvresize corruption in LV->crypt->FS stack if near crypt min size limit.
|
||||
* Support dmeventd restart when there are no monitored devices.
|
||||
* Dmeventd no longer calls 'action commands' on removed devices.
|
||||
* Enhanced `lvresize -r` support for btrfs.
|
||||
* Fix reader of VDO metadata on 32bit architecture.
|
||||
* Fix `lvmdevices --deldev/--delpvid` to error out if devices file not writeable.
|
||||
* Use glibc standard functions htoX, Xtoh functions for endian conversion.
|
||||
* Fix structure copying within sanlock's `release_rename()`.
|
||||
* Fix autoactivation on top of loop dev PVs to trigger once for change uevents.
|
||||
* Fix support for `lvcreate -T --setautoactivation`.
|
||||
* Fix many issues found by coverity static analysis, gcc warnings, typos, tests, and other clean ups.
|
||||
|
||||
<!-- 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="Wed Jul 30 15:35:00 2025 +0200"]]
|
||||
-->
|
||||
@@ -1,53 +0,0 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.35 - Feature and Bug Fix Release"]]
|
||||
|
||||
Version 2.03.35
|
||||
===============
|
||||
|
||||
* Optimize dmeventd when remonitoring active devices.
|
||||
* Allow report options for `(pv|vg|lv)display` only if used with `-C|--columns`.
|
||||
* And [[!toggle text="more"]]
|
||||
|
||||
[[!toggleable text="""
|
||||
Features
|
||||
-----------------------
|
||||
|
||||
### Optimize dmeventd when remonitoring active devices.
|
||||
|
||||
Add grace period (controlled by `-g SECONDS` option) to [dmeventd(8)](https://man7.org/linux/man-pages/man8/dmeventd.8.html) to reuse threads.
|
||||
|
||||
This change help to reduce overhead and unnecessary `lvextend` calls.
|
||||
|
||||
|
||||
<!--
|
||||
TODO: It would be nice if we could use a real session output, so we could test the examples
|
||||
- During tests, save some outputs
|
||||
-->
|
||||
|
||||
Changes in command line
|
||||
-----------------------
|
||||
|
||||
* Report options (`--select STRING`, `--configreport CONFIG_REPORT`, `--logonly`)
|
||||
are allowed only with `(pv|vg|lv)display -C|--columns`.
|
||||
These **no longer work** without `-C|--columns` and were removed as they were not working properly anyway.
|
||||
|
||||
Other Changes
|
||||
-------------
|
||||
|
||||
* Fix unlocking devices file only after all PVs are processed.
|
||||
* Avoid creating system.devices when deleting entries.
|
||||
* Fix existing issues with persistent reservations.
|
||||
* Fix possible report output format inconsistencies while processing PVs.
|
||||
* Allow report options for pv/vg/lvdisplay only if used with -C|--columns.
|
||||
* Fix vgsplit failing to split a VG with RAID+integrity or cache with cachevol.
|
||||
* Fix --lockopt handling in lvmlockd when --nolocking is used.
|
||||
* Optimize dmeventd when remonitoring active devices.
|
||||
|
||||
"""]]
|
||||
|
||||
<!-- 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 Sep 09 14:19:37 2025 +0200"]]
|
||||
-->
|
||||
@@ -1,39 +0,0 @@
|
||||
<!-- Page title -->
|
||||
[[!meta title="Version 2.03.36 - Feature and Bug Fix Release"]]
|
||||
|
||||
Version 2.03.36
|
||||
===============
|
||||
|
||||
* Support splitting large pvmove into segments, controlled by
|
||||
`allocation/pvmove_max_segment_size_mb` configuration option.
|
||||
* Add cache promotions/demotions to reports.
|
||||
* Handle XFS quota when resizing.
|
||||
* Allow creating `_imeta` with multiple segments.
|
||||
* Fix race in dmeventd remonitoring optimization (2.03.35).
|
||||
* And [[!toggle text="more"]]
|
||||
|
||||
[[!toggleable text="""
|
||||
|
||||
Other Changes
|
||||
-------------
|
||||
|
||||
* Support `--setpersist` in vgcreate.
|
||||
* Use only hostid-based PR keys for sanlock VGs.
|
||||
* Update lvmlockd(8) man page.
|
||||
* Consistent sorting of command options in help and man pages.
|
||||
* Use `-real` UUID suffix to keep internal volumes hidden from udev. This is
|
||||
implemented for RAID, mirror, integrity, and internal pvmove volumes. This
|
||||
should handle corner cases where where operations were not finishing cleanly.
|
||||
* Fix adding and removing integrity to RAID volumes.
|
||||
* Deactivate internal lvmlock LV if lock start fails.
|
||||
* Detect insufficient space for RAID with split metadata.
|
||||
|
||||
"""]]
|
||||
|
||||
<!-- 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="Fri Oct 24 18:22:00 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)" rootpage="release-notes"]]
|
||||
[[!inline pages="release-notes/2.02.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]
|
||||
|
||||
|
||||
@@ -579,7 +579,7 @@
|
||||
/* Define to 1 to include code that uses lvmlockd IDM option. */
|
||||
#undef LOCKDIDM_SUPPORT
|
||||
|
||||
/* Define version of sanlock. */
|
||||
/* Define to 1 to include code that uses lvmlockd sanlock option. */
|
||||
#undef LOCKDSANLOCK_SUPPORT
|
||||
|
||||
/* Define to 1 if 'lstat' dereferences a symlink specified with a trailing
|
||||
@@ -598,9 +598,6 @@
|
||||
/* Define to 1 to include code that uses lvmlockd. */
|
||||
#undef LVMLOCKD_SUPPORT
|
||||
|
||||
/* Path to lvmpersist script. */
|
||||
#undef LVMPERSIST_PATH
|
||||
|
||||
/* Path to lvmpolld pidfile. */
|
||||
#undef LVMPOLLD_PIDFILE
|
||||
|
||||
@@ -636,9 +633,6 @@
|
||||
/* 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
|
||||
|
||||
@@ -666,9 +660,6 @@
|
||||
/* 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,8 +43,6 @@ SOURCES =\
|
||||
device/filesystem.c \
|
||||
device/online.c \
|
||||
device/parse_vpd.c \
|
||||
device/persist.c \
|
||||
device/nvme.c \
|
||||
device/dev_util.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
@@ -144,7 +142,7 @@ LIB_STATIC = $(LIB_NAME).a
|
||||
CFLOW_LIST = $(SOURCES)
|
||||
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
|
||||
|
||||
PROGS_CFLAGS = $(BLKID_CFLAGS) $(LIBNVME_CFLAGS) $(UDEV_CFLAGS)
|
||||
PROGS_CFLAGS = $(BLKID_CFLAGS) $(UDEV_CFLAGS)
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/metadata/segtype.h"
|
||||
#include "lib/misc/sharedlib.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/misc/lvm-signal.h"
|
||||
|
||||
#include <limits.h>
|
||||
@@ -501,9 +502,7 @@ int driver_version(char *version, size_t size)
|
||||
!dm_driver_version(_vsn, sizeof(_vsn)))
|
||||
return_0;
|
||||
|
||||
if (version &&
|
||||
!_dm_strncpy(version, _vsn, size))
|
||||
return_0;
|
||||
dm_strncpy(version, _vsn, size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -682,55 +681,6 @@ int get_dm_active_devices(const struct volume_group *vg, struct dm_list **devs,
|
||||
return dev_manager_get_dm_active_devices(NULL, devs, devs_features);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for active devices with private "-real" UUID suffix
|
||||
* when public device doesn't exist.
|
||||
*
|
||||
* This function extends _lv_info() functionality to handle edge cases
|
||||
* where a visible LV has no active device with its public UUID,
|
||||
* but there might be an active device using a private "-real" suffixed UUID.
|
||||
* This situation typically occurs during RAID/mirror operations
|
||||
* where internal LV components transition to public LVs but retain their
|
||||
* private device mapper UUIDs.
|
||||
*
|
||||
* The function:
|
||||
* - Skips LVs that already have "-real" in their UUID (likely internal components)
|
||||
* - Queries device mapper for a device using the LV name with "real" layer
|
||||
* - Populates dminfo structure if such device exists
|
||||
*
|
||||
* These 'orphan' LVs with private UUIDs need explicit activation to be
|
||||
* properly managed before they can be deactivated with their correct
|
||||
* public UUIDs.
|
||||
*
|
||||
* TODO: automate removal of orphan LVs with -real suffix
|
||||
* using LV_PENDING_DELETE to reduce this workaround code.
|
||||
*/
|
||||
static int _lv_info_real(const struct logical_volume *lv,
|
||||
struct dm_info *dminfo)
|
||||
{
|
||||
const char *dlid;
|
||||
|
||||
if (lv_is_origin(lv) ||
|
||||
lv_is_external_origin(lv) ||
|
||||
lv_is_integrity_origin(lv) ||
|
||||
lv_is_cow(lv))
|
||||
return 1;
|
||||
|
||||
if (!(dlid = build_dm_uuid(lv->vg->cmd->mem, lv, NULL)))
|
||||
return_0;
|
||||
|
||||
if (strstr(dlid, "-real")) {
|
||||
/* UUID has "-real" suffix (likely MIRROR_SYNC_LAYER), skip */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!dev_manager_info(lv->vg->cmd, lv, "real", 0, 0, 0,
|
||||
dminfo, NULL, NULL))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* When '*info' is NULL, returns 1 only when LV is active.
|
||||
* When '*info' != NULL, returns 1 when info structure is populated.
|
||||
@@ -776,10 +726,6 @@ static int _lv_info(struct cmd_context *cmd, const struct logical_volume *lv,
|
||||
seg_status))
|
||||
return_0;
|
||||
|
||||
if (!dminfo.exists && !use_layer && lv_is_visible(lv) &&
|
||||
!_lv_info_real(lv, &dminfo))
|
||||
return_0;
|
||||
|
||||
if (!info)
|
||||
return dminfo.exists;
|
||||
|
||||
@@ -1694,7 +1640,7 @@ bad:
|
||||
char *get_monitor_dso_path(struct cmd_context *cmd, int id)
|
||||
{
|
||||
const char *libpath = find_config_tree_str(cmd, id, NULL);
|
||||
char path[PATH_MAX] = { 0 };
|
||||
char path[PATH_MAX];
|
||||
|
||||
get_shared_library_path(cmd, libpath, path, sizeof(path));
|
||||
|
||||
@@ -1814,8 +1760,7 @@ int target_register_events(struct cmd_context *cmd, const char *dso, const struc
|
||||
return_0;
|
||||
|
||||
if (!(dmevh = _create_dm_event_handler(cmd, uuid, dso, timeout,
|
||||
timeout ? DM_EVENT_ERROR_AND_TIMEOUT_MASK :
|
||||
DM_EVENT_ALL_ERRORS)))
|
||||
DM_EVENT_ALL_ERRORS | (timeout ? DM_EVENT_TIMEOUT : 0))))
|
||||
return_0;
|
||||
|
||||
r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
|
||||
@@ -2213,7 +2158,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
|
||||
goto_out;
|
||||
|
||||
/* Suspending 1st. LV above PVMOVE suspends whole tree */
|
||||
/* coverity[unreachable] intentional single iteration to get first item */
|
||||
dm_list_iterate_items(sl, &pvmove_lv->segs_using_this_lv) {
|
||||
lv = sl->seg->lv;
|
||||
break;
|
||||
|
||||
@@ -197,8 +197,6 @@ int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
|
||||
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
|
||||
int lv_raid_message(const struct logical_volume *lv, const char *msg);
|
||||
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status);
|
||||
int lv_raid_clear_failed_devices(const struct logical_volume *lv);
|
||||
int lv_raid_count_failed_devices(const struct logical_volume *lv, uint32_t *failed_cnt);
|
||||
int lv_writecache_message(const struct logical_volume *lv, const char *msg);
|
||||
int lv_cache_status(const struct logical_volume *cache_lv,
|
||||
struct lv_status_cache **status);
|
||||
|
||||
@@ -47,18 +47,7 @@ typedef enum {
|
||||
} action_t;
|
||||
|
||||
/* This list must match lib/misc/lvm-string.c:build_dm_uuid(). */
|
||||
static const char * const _uuid_suffix_list[] = {
|
||||
"cdata",
|
||||
"cmeta",
|
||||
"cvol",
|
||||
"imeta",
|
||||
"pool",
|
||||
"tdata",
|
||||
"tmeta",
|
||||
"vdata",
|
||||
"vpool",
|
||||
NULL
|
||||
};
|
||||
static const char * const _uuid_suffix_list[] = { "pool", "cdata", "cmeta", "cvol", "tdata", "tmeta", "vdata", "vpool", "imeta", NULL};
|
||||
|
||||
struct dlid_list {
|
||||
struct dm_list list;
|
||||
@@ -701,7 +690,7 @@ static int _ignore_frozen_raid(struct device *dev, const char *params)
|
||||
|
||||
static int _is_usable_uuid(const struct device *dev, const char *name, const char *uuid, int check_reserved, int check_lv, int *is_lv)
|
||||
{
|
||||
char *vgname = NULL, *lvname = NULL, *layer = NULL;
|
||||
char *vgname, *lvname, *layer;
|
||||
char vg_name[NAME_LEN];
|
||||
|
||||
if (!check_reserved && !check_lv)
|
||||
@@ -913,7 +902,7 @@ int devno_dm_uuid(struct cmd_context *cmd, int major, int minor,
|
||||
const char *uuid;
|
||||
int r = 0;
|
||||
|
||||
if (major != (int) cmd->dev_types->device_mapper_major)
|
||||
if (major != cmd->dev_types->device_mapper_major)
|
||||
return 0;
|
||||
|
||||
if (dm_devs_cache_use()) {
|
||||
@@ -2025,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 than one table line found for %s.",
|
||||
log_error("More then one table line found for %s.",
|
||||
display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
@@ -2078,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 than one table line found for %s.",
|
||||
log_error("More then one table line found for %s.",
|
||||
display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
@@ -2132,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 than one table line found for %s.",
|
||||
log_error("More then one table line found for %s.",
|
||||
display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
@@ -2784,10 +2773,9 @@ 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 = { .id = { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
|
||||
lvid.s[sizeof(lvid.id)] = 0;
|
||||
union lvid lvid = { { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
|
||||
|
||||
if (!(dlid = dm_build_dm_uuid(mem, UUID_PREFIX, lvid.s, layer)))
|
||||
if (!(dlid = dm_build_dm_uuid(mem, UUID_PREFIX, (const char *)&lvid.s, layer)))
|
||||
return_0;
|
||||
|
||||
/* Name is actually not really needed here, but aids debugging... */
|
||||
@@ -3032,11 +3020,6 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _set_optional_uuid_suffixes(struct dm_tree *dtree)
|
||||
{
|
||||
dm_tree_set_optional_uuid_suffixes(dtree, (const char**)_uuid_suffix_list);
|
||||
}
|
||||
|
||||
static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, const struct logical_volume *lv, int origin_only)
|
||||
{
|
||||
struct dm_tree *dtree;
|
||||
@@ -3047,7 +3030,7 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm, const struc
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_set_optional_uuid_suffixes(dtree);
|
||||
dm_tree_set_optional_uuid_suffixes(dtree, (const char**)_uuid_suffix_list);
|
||||
|
||||
if (!_add_lv_to_dtree(dm, dtree, lv, (lv_is_origin(lv) || lv_is_thin_volume(lv) || lv_is_thin_pool(lv)) ? origin_only : 0))
|
||||
goto_bad;
|
||||
@@ -3443,10 +3426,9 @@ 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 = { .id = { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
|
||||
lvid.s[sizeof(lvid.id)] = 0;
|
||||
union lvid lvid = { { lv->vg->id, _get_id_for_meta_or_data(lvseg, meta_or_data) } };
|
||||
|
||||
if (!(dlid = dm_build_dm_uuid(dm->mem, UUID_PREFIX, lvid.s, layer)))
|
||||
if (!(dlid = dm_build_dm_uuid(dm->mem, UUID_PREFIX, (const char *)&lvid.s, layer)))
|
||||
return_0;
|
||||
|
||||
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, pool_lv->name, layer)))
|
||||
@@ -3578,70 +3560,6 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a visible LV is active but still uses a private "-real" UUID suffix.
|
||||
*
|
||||
* This situation occurs during certain operations like RAID leg splits,
|
||||
* where an LV transitions from being an internal component (with "-real" suffix)
|
||||
* to a public LV, but the device mapper device retains the old private UUID.
|
||||
*
|
||||
* This function detects such inconsistencies by:
|
||||
* 1. Constructing a potential "-real" suffixed UUID for the given LV
|
||||
* 2. Searching for an active device with that UUID but without "-real" in its name
|
||||
* 3. If found, updating UUID parameter to use the private UUID
|
||||
*
|
||||
* Note: Such LVs should be deactivated and reactivated to use the correct public UUID.
|
||||
*/
|
||||
static int _lv_adjust_real_uuid(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
const struct logical_volume *lv,
|
||||
char **dlid)
|
||||
{
|
||||
struct dm_tree_node *dnode;
|
||||
const struct dm_info *dinfo;
|
||||
const char *s;
|
||||
char *uuid;
|
||||
|
||||
/* Only check visible LVs that are neither origin nor snapshot */
|
||||
if (!lv_is_visible(lv) ||
|
||||
lv_is_origin(lv) ||
|
||||
lv_is_external_origin(lv) ||
|
||||
lv_is_integrity_origin(lv) ||
|
||||
lv_is_cow(lv))
|
||||
return 1;
|
||||
|
||||
/* Currently only a few LV types can be RAID/mirror orphans, for example:
|
||||
* legs cannot be cached, however old mirror log can be mirrored */
|
||||
if (!lv_is_linear(lv) &&
|
||||
!lv_is_striped(lv) &&
|
||||
!lv_is_mirrored(lv) &&
|
||||
!lv_is_error(lv) &&
|
||||
!lv_is_zero(lv))
|
||||
return 1;
|
||||
|
||||
if (!(uuid = build_dm_uuid(dm->mem, lv, "real")))
|
||||
return_0;
|
||||
|
||||
/* Temporarily disable suffix masking. Exact match is required. */
|
||||
dm_tree_set_optional_uuid_suffixes(dtree, NULL);
|
||||
|
||||
if ((dnode = dm_tree_find_node_by_uuid(dtree, uuid)) &&
|
||||
(dinfo = dm_tree_node_get_info(dnode)) && dinfo->exists) {
|
||||
s = strstr(dm_tree_node_get_name(dnode), "-real");
|
||||
/* Ignore devices whose names end with "-real" suffix */
|
||||
if (!s || s[5]) {
|
||||
log_debug("Adjusting UUID to %s for LV %s active as %s.",
|
||||
uuid, display_lvname(lv),
|
||||
dm_tree_node_get_name(dnode));
|
||||
*dlid = uuid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore suffix handling. */
|
||||
_set_optional_uuid_suffixes(dtree);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
const struct logical_volume *lv, struct lv_activate_opts *laopts,
|
||||
const char *layer)
|
||||
@@ -3766,9 +3684,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
|
||||
dm_tree_node_get_context(dnode))
|
||||
return 1;
|
||||
|
||||
/* Use UUID with -real private suffix for such active LV. */
|
||||
if (!layer && !_lv_adjust_real_uuid(dm, dtree, lv, &dlid))
|
||||
return_0;
|
||||
/*
|
||||
* Add LV to dtree.
|
||||
* If we're working with precommitted metadata, clear any
|
||||
@@ -4252,7 +4167,7 @@ int dev_manager_device_uses_vg(struct device *dev,
|
||||
return r;
|
||||
}
|
||||
|
||||
_set_optional_uuid_suffixes(dtree);
|
||||
dm_tree_set_optional_uuid_suffixes(dtree, (const char**)_uuid_suffix_list);
|
||||
|
||||
if (!dm_tree_add_dev(dtree, MAJOR(dev->dev), MINOR(dev->dev))) {
|
||||
log_error("Failed to add device %s (%u:%u) to dtree.",
|
||||
|
||||
@@ -490,11 +490,7 @@ void fs_unlock(void)
|
||||
{
|
||||
/* Do not allow syncing device name with suspended devices */
|
||||
if (!dm_get_suspended_counter()) {
|
||||
if (!dm_udev_get_sync_support())
|
||||
log_debug_activation("Not syncing device names (--noudevsync ? %d).",
|
||||
dm_udev_get_checking());
|
||||
else
|
||||
log_debug_activation("Syncing device names");
|
||||
log_debug_activation("Syncing device names");
|
||||
/* Wait for all processed udev devices */
|
||||
if (!dm_udev_wait(_fs_cookie))
|
||||
stack;
|
||||
|
||||
@@ -16,12 +16,8 @@
|
||||
#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,
|
||||
|
||||
141
lib/cache/lvmcache.c
vendored
141
lib/cache/lvmcache.c
vendored
@@ -21,6 +21,7 @@
|
||||
#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"
|
||||
@@ -314,7 +315,7 @@ static struct lvmcache_vginfo *_vginfo_lookup(const char *vgname, const char *vg
|
||||
if (vgid_arg) {
|
||||
if ((vginfo = dm_hash_lookup(_vgid_hash, vgid))) {
|
||||
if (vgname && strcmp(vginfo->vgname, vgname)) {
|
||||
log_warn("WARNING: Lookup found duplicate VGID %s for VGs %s and %s.", vgid, vginfo->vgname, vgname);
|
||||
log_warn("WARNING: lookup found duplicate VGID %s for VGs %s and %s.", vgid, vginfo->vgname, vgname);
|
||||
if ((vginfo = dm_hash_lookup(_vgname_hash, vgname))) {
|
||||
if (!memcmp(vginfo->vgid, vgid, ID_LEN))
|
||||
return vginfo;
|
||||
@@ -1890,7 +1891,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
|
||||
|
||||
vginfo = lvmcache_vginfo_from_vgid(vgid);
|
||||
if (vginfo && strcmp(vginfo->vgname, vgname)) {
|
||||
log_warn("WARNING: Fix duplicate VGID %s for VGs %s and %s (see vgchange -u).", vgid_dashed, vgname, vginfo->vgname);
|
||||
log_warn("WARNING: fix duplicate VGID %s for VGs %s and %s (see vgchange -u).", vgid_dashed, vgname, vginfo->vgname);
|
||||
vginfo = lvmcache_vginfo_from_vgname(vgname, NULL);
|
||||
if (vginfo && memcmp(vginfo->vgid, vgid, ID_LEN)) {
|
||||
log_error("Ignoring %s with conflicting VG info %s %s.", dev_name(info->dev), vgid_dashed, vgname);
|
||||
@@ -1953,7 +1954,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("WARNING: Fix duplicate VG names with vgrename uuid, or vgrename --devices.");
|
||||
log_warn("Fix duplicate VG names with vgrename uuid, a device filter, or system IDs.");
|
||||
}
|
||||
|
||||
if (!vginfo_is_allowed && !other_is_allowed) {
|
||||
@@ -2096,17 +2097,12 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
|
||||
vgid = vgname;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
/* 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())
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new vginfo struct for this vgname/vgid if none exists,
|
||||
@@ -2227,7 +2223,7 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
|
||||
*/
|
||||
|
||||
if ((vginfo->mda_size != vgsummary->mda_size) || (vginfo->mda_checksum != vgsummary->mda_checksum)) {
|
||||
log_warn("WARNING: Scan of VG %s from %s mda%d found mda_checksum %x mda_size %zu vs %x %zu.",
|
||||
log_warn("WARNING: scan of VG %s from %s mda%d found mda_checksum %x mda_size %zu vs %x %zu",
|
||||
vgname, dev_name(info->dev), vgsummary->mda_num,
|
||||
vgsummary->mda_checksum, vgsummary->mda_size,
|
||||
vginfo->mda_checksum, vginfo->mda_size);
|
||||
@@ -2269,7 +2265,7 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
|
||||
* using the 'vg'.
|
||||
*/
|
||||
|
||||
void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_claim)
|
||||
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
|
||||
{
|
||||
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
|
||||
@@ -2289,11 +2285,9 @@ void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_cla
|
||||
|
||||
if (!(vginfo = lvmcache_vginfo_from_vgname(vg->name, vgid))) {
|
||||
log_error(INTERNAL_ERROR "lvmcache_update_vg %s no vginfo", vg->name);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -2312,7 +2306,7 @@ void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_cla
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
log_warn("WARNING: Outdated PV %s seqno %u has been removed in current VG %s seqno %u.",
|
||||
log_warn("WARNING: outdated PV %s seqno %u has been removed in current VG %s seqno %u.",
|
||||
dev_name(info->dev), info->summary_seqno, vg->name, vginfo->seqno);
|
||||
|
||||
if (!_outdated_warning++)
|
||||
@@ -2332,32 +2326,8 @@ void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_cla
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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));
|
||||
log_debug_cache("lvmcache_update_vg %s for info %s",
|
||||
vg->name, dev_name(info->dev));
|
||||
|
||||
/*
|
||||
* FIXME: use a different function that just attaches info's that
|
||||
@@ -2379,7 +2349,7 @@ void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_cla
|
||||
* (since label_scan didn't know this without metadata.)
|
||||
*/
|
||||
dm_list_iterate_items(mda, &info->mdas) {
|
||||
if (!_mda_is_ignored(mda))
|
||||
if (!mda_is_ignored(mda))
|
||||
continue;
|
||||
log_debug("lvmcache_update_vg %s copy ignored mdas for %s", vg->name, dev_name(info->dev));
|
||||
if (!lvmcache_fid_add_mdas_pv(info, vg->fid)) {
|
||||
@@ -2389,6 +2359,8 @@ void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_cla
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3145,16 +3117,6 @@ bool lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, cons
|
||||
if (info->summary_seqno_mismatch)
|
||||
return true;
|
||||
|
||||
/* shouldn't happen? */
|
||||
if (!info->vginfo)
|
||||
return false;
|
||||
|
||||
/* PV moved to a different VG between label_scan and this vg_write */
|
||||
if (memcmp(info->vginfo->vgid, vgid, ID_LEN)) {
|
||||
log_debug("lvmcache_has_old_metadata: PV in new VG %s", dev_name(dev));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* one or both mdas on this dev has older metadata than another dev */
|
||||
if (vginfo->seqno > info->summary_seqno)
|
||||
return true;
|
||||
@@ -3241,73 +3203,6 @@ 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);
|
||||
void lvmcache_update_vg_from_read(struct volume_group *vg, int *incorrect_pv_claim);
|
||||
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted);
|
||||
|
||||
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 *pvid, uint64_t *label_sector);
|
||||
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pv_id, 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,9 +190,6 @@ 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);
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/metadata/metadata.h"
|
||||
#include "lib/config/defaults.h"
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/misc/lvm-string.h"
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/filters/filter.h"
|
||||
@@ -34,7 +33,6 @@
|
||||
#include "lib/format_text/archiver.h"
|
||||
#include "lib/lvmpolld/lvmpolld-client.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "include/lvm-version.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -84,7 +82,7 @@ const char *system_id_from_string(struct cmd_context *cmd, const char *str)
|
||||
}
|
||||
|
||||
if (!strncmp(system_id, "localhost", 9)) {
|
||||
log_warn("WARNING: System ID may not begin with the string \"localhost\".");
|
||||
log_warn("WARNING: system ID may not begin with the string \"localhost\".");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -656,43 +654,6 @@ static void _init_device_ids_refresh(struct cmd_context *cmd)
|
||||
cmd->device_ids_check_hostname = 1;
|
||||
}
|
||||
|
||||
void log_debug_config(struct cmd_context *cmd)
|
||||
{
|
||||
struct config_def_tree_spec tree_spec = {0};
|
||||
struct cft_check_handle *handle = NULL;
|
||||
unsigned int major, minor, patchlevel;
|
||||
|
||||
/* Parse version from LVM_VERSION string */
|
||||
if (sscanf(LVM_VERSION, "%u.%u.%u", &major, &minor, &patchlevel) != 3) {
|
||||
major = 0;
|
||||
minor = 0;
|
||||
patchlevel = 0;
|
||||
}
|
||||
|
||||
tree_spec.cmd = cmd;
|
||||
tree_spec.type = CFG_DEF_TREE_CURRENT;
|
||||
tree_spec.current_cft = cmd->cft;
|
||||
tree_spec.version = vsn(major, minor, patchlevel);
|
||||
tree_spec.log_debug = 1;
|
||||
|
||||
/* Check config to mark differences from defaults */
|
||||
if (!(handle = get_config_tree_check_handle(cmd, cmd->cft)))
|
||||
return;
|
||||
|
||||
handle->force_check = 1;
|
||||
handle->suppress_messages = 1;
|
||||
handle->skip_if_checked = 0;
|
||||
handle->check_diff = 1;
|
||||
|
||||
if (!config_def_check(handle))
|
||||
return;
|
||||
|
||||
tree_spec.check_status = handle->status;
|
||||
|
||||
/* Write config via log_debug */
|
||||
config_write(cmd->cft, &tree_spec, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static int _process_config(struct cmd_context *cmd)
|
||||
{
|
||||
mode_t old_umask;
|
||||
@@ -735,7 +696,7 @@ static int _process_config(struct cmd_context *cmd)
|
||||
if (dev_ext_info_src &&
|
||||
strcmp(dev_ext_info_src, "none") &&
|
||||
strcmp(dev_ext_info_src, "udev")) {
|
||||
log_warn("WARNING: Unknown external device info source, using none.");
|
||||
log_warn("WARNING: unknown external device info source, using none.");
|
||||
dev_ext_info_src = NULL;
|
||||
}
|
||||
|
||||
@@ -743,7 +704,7 @@ static int _process_config(struct cmd_context *cmd)
|
||||
if (udev_init_library_context()) {
|
||||
init_external_device_info_source(DEV_EXT_UDEV);
|
||||
} else {
|
||||
log_warn("WARNING: Failed to init udev for external device info, using none.");
|
||||
log_warn("WARNING: failed to init udev for external device info, using none.");
|
||||
dev_ext_info_src = NULL;
|
||||
}
|
||||
}
|
||||
@@ -759,7 +720,7 @@ static int _process_config(struct cmd_context *cmd)
|
||||
}
|
||||
|
||||
if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
|
||||
log_warn("WARNING: proc dir %s not found - some checks will be bypassed.",
|
||||
log_warn("WARNING: proc dir %s not found - some checks will be bypassed",
|
||||
cmd->proc_dir);
|
||||
cmd->proc_dir[0] = '\0';
|
||||
}
|
||||
@@ -832,13 +793,13 @@ static int _process_config(struct cmd_context *cmd)
|
||||
else if (strcmp(cmd->stripe_filler, "error") &&
|
||||
strcmp(cmd->stripe_filler, "zero")) {
|
||||
if (stat(cmd->stripe_filler, &st)) {
|
||||
log_warn("WARNING: activation/missing_stripe_filler = \"%s\"."
|
||||
log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
|
||||
"is invalid,", cmd->stripe_filler);
|
||||
log_warn(" stat failed: %s", strerror(errno));
|
||||
log_warn("Falling back to \"error\" missing_stripe_filler.");
|
||||
cmd->stripe_filler = "error";
|
||||
} else if (!S_ISBLK(st.st_mode)) {
|
||||
log_warn("WARNING: activation/missing_stripe_filler = \"%s\"."
|
||||
log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
|
||||
"is not a block device.", cmd->stripe_filler);
|
||||
log_warn("Falling back to \"error\" missing_stripe_filler.");
|
||||
cmd->stripe_filler = "error";
|
||||
@@ -1225,7 +1186,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_FILTERS 20
|
||||
#define MAX_FILTERS 10
|
||||
|
||||
static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
|
||||
{
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
#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>
|
||||
|
||||
@@ -73,8 +71,7 @@ struct cmd_context_initialized_parts {
|
||||
};
|
||||
|
||||
struct cmd_report {
|
||||
unsigned log_only:1;
|
||||
unsigned lc_numeric_override:1;
|
||||
int log_only;
|
||||
dm_report_group_type_t report_group_type;
|
||||
struct dm_report_group *report_group;
|
||||
struct dm_report *log_rh;
|
||||
@@ -166,10 +163,6 @@ 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;
|
||||
@@ -226,7 +219,6 @@ struct cmd_context {
|
||||
unsigned device_ids_auto_import:1;
|
||||
unsigned get_vgname_from_options:1; /* used by lvconvert */
|
||||
unsigned vg_write_validates_vg:1;
|
||||
unsigned disable_pr_required:1;
|
||||
|
||||
/*
|
||||
* Devices and filtering.
|
||||
@@ -316,8 +308,6 @@ int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache);
|
||||
int init_connections(struct cmd_context *cmd);
|
||||
int init_run_by_dmeventd(struct cmd_context *cmd);
|
||||
|
||||
void log_debug_config(struct cmd_context *cmd);
|
||||
|
||||
/*
|
||||
* A config context is a very light weight cmd struct that
|
||||
* is only used for reading config settings from lvm.conf,
|
||||
|
||||
@@ -66,16 +66,11 @@ 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, (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},
|
||||
#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},
|
||||
#include "lib/config/config_settings.h"
|
||||
#undef cfg_section
|
||||
#undef cfg
|
||||
@@ -108,7 +103,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 keep_open __attribute__((unused)))
|
||||
int unused)
|
||||
{
|
||||
struct dm_config_tree *cft = dm_config_create();
|
||||
struct config_source *cs;
|
||||
@@ -522,11 +517,10 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
|
||||
/* Note: also used for lvm.conf to read all settings */
|
||||
for (rsize = 0; rsize < size; rsize += sz) {
|
||||
do {
|
||||
/* coverity[overflow_sink] - only positive 'sz' is used */
|
||||
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;
|
||||
}
|
||||
@@ -933,7 +927,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 = fabsf(f - v->v.f) < FLT_EPSILON;
|
||||
diff = fabs(f - v->v.f) < FLT_EPSILON;
|
||||
break;
|
||||
case DM_CFG_STRING:
|
||||
/* string value can be a real string but it can also represent bool */
|
||||
@@ -1693,57 +1687,6 @@ struct out_baton {
|
||||
|
||||
#define MAX_COMMENT_LINE 512
|
||||
|
||||
static void _out_line(struct out_baton *out, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
static void _out_line(struct out_baton *out, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[4096];
|
||||
const char *p;
|
||||
size_t len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (out->tree_spec->log_debug) {
|
||||
if (vsnprintf(buf, sizeof(buf), fmt, ap) >= 0) {
|
||||
/* Skip section headers and brackets for log_debug output */
|
||||
p = buf;
|
||||
/* Skip leading whitespace */
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
|
||||
/* Skip empty lines */
|
||||
if (*p == '\0' || *p == '\n')
|
||||
goto out;
|
||||
|
||||
/* Skip closing brackets */
|
||||
if (*p == '}') {
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Skip lines ending with opening bracket (section headers) */
|
||||
len = strlen(p);
|
||||
if (len > 0 && p[len - 1] == '\n')
|
||||
len--;
|
||||
while (len > 0 && (p[len - 1] == ' ' || p[len - 1] == '\t'))
|
||||
len--;
|
||||
if (len > 1 && p[len - 1] == '{')
|
||||
goto out;
|
||||
|
||||
/* Print without leading whitespace and without trailing newline */
|
||||
if (len > 0 && p[len] == '\n')
|
||||
log_debug("%.*s", (int)len, p);
|
||||
else
|
||||
log_debug("%s", p);
|
||||
}
|
||||
} else {
|
||||
vfprintf(out->fp, fmt, ap);
|
||||
}
|
||||
out:
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static int _copy_one_line(const char *comment, char *line, int *pos, int len)
|
||||
{
|
||||
int p;
|
||||
@@ -1817,11 +1760,11 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
|
||||
if (out->tree_spec->withsummary || out->tree_spec->withcomments) {
|
||||
_cfg_def_make_path(path, sizeof(path), cfg_def->id, cfg_def, 1);
|
||||
_out_line(out, "\n");
|
||||
_out_line(out, "%s# Configuration %s %s.\n", line, node_type_name, path);
|
||||
fprintf(out->fp, "\n");
|
||||
fprintf(out->fp, "%s# Configuration %s %s.\n", line, node_type_name, path);
|
||||
|
||||
if (out->tree_spec->withcomments && is_deprecated && cfg_def->deprecation_comment)
|
||||
_out_line(out, "%s# %s", line, cfg_def->deprecation_comment);
|
||||
fprintf(out->fp, "%s# %s", line, cfg_def->deprecation_comment);
|
||||
|
||||
if (cfg_def->comment) {
|
||||
int pos = 0;
|
||||
@@ -1831,7 +1774,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
continue;
|
||||
commentline[0] = '\0';
|
||||
}
|
||||
_out_line(out, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
|
||||
fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
|
||||
/* withsummary prints only the first comment line. */
|
||||
if (!out->tree_spec->withcomments)
|
||||
break;
|
||||
@@ -1839,37 +1782,37 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
|
||||
}
|
||||
|
||||
if (is_deprecated)
|
||||
_out_line(out, "%s# This configuration %s is deprecated.\n", line, node_type_name);
|
||||
fprintf(out->fp, "%s# This configuration %s is deprecated.\n", line, node_type_name);
|
||||
|
||||
if (cfg_def->flags & CFG_ADVANCED)
|
||||
_out_line(out, "%s# This configuration %s is advanced.\n", line, node_type_name);
|
||||
fprintf(out->fp, "%s# This configuration %s is advanced.\n", line, node_type_name);
|
||||
|
||||
if (cfg_def->flags & CFG_UNSUPPORTED)
|
||||
_out_line(out, "%s# This configuration %s is not officially supported.\n", line, node_type_name);
|
||||
fprintf(out->fp, "%s# This configuration %s is not officially supported.\n", line, node_type_name);
|
||||
|
||||
if (cfg_def->flags & CFG_NAME_VARIABLE)
|
||||
_out_line(out, "%s# This configuration %s has variable name.\n", line, node_type_name);
|
||||
fprintf(out->fp, "%s# This configuration %s has variable name.\n", line, node_type_name);
|
||||
|
||||
if (cfg_def->flags & CFG_DEFAULT_UNDEFINED)
|
||||
_out_line(out, "%s# This configuration %s does not have a default value defined.\n", line, node_type_name);
|
||||
fprintf(out->fp, "%s# This configuration %s does not have a default value defined.\n", line, node_type_name);
|
||||
|
||||
if (cfg_def->flags & CFG_DEFAULT_COMMENTED)
|
||||
_out_line(out, "%s# This configuration %s has an automatic default value.\n", line, node_type_name);
|
||||
fprintf(out->fp, "%s# This configuration %s has an automatic default value.\n", line, node_type_name);
|
||||
|
||||
if ((out->tree_spec->type == CFG_DEF_TREE_FULL) &&
|
||||
(out->tree_spec->check_status[cn->id] & CFG_USED))
|
||||
_out_line(out, "%s# Value defined in existing configuration has been used for this setting.\n", line);
|
||||
fprintf(out->fp, "%s# Value defined in existing configuration has been used for this setting.\n", line);
|
||||
}
|
||||
|
||||
if (out->tree_spec->withversions) {
|
||||
if (!_get_config_node_version(cfg_def->since_version, version))
|
||||
return_0;
|
||||
_out_line(out, "%s# Available since version %s.\n", line, version);
|
||||
fprintf(out->fp, "%s# Available since version %s.\n", line, version);
|
||||
|
||||
if (is_deprecated) {
|
||||
if (!_get_config_node_version(cfg_def->deprecated_since_version, version))
|
||||
return_0;
|
||||
_out_line(out, "%s# Deprecated since version %s.\n", line, version);
|
||||
fprintf(out->fp, "%s# Deprecated since version %s.\n", line, version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1917,7 +1860,7 @@ static int _out_line_fn(const struct dm_config_node *cn, const char *line, void
|
||||
if (out->tree_spec->withsummary && cfg_def->comment)
|
||||
_copy_one_line(cfg_def->comment, summary, &pos, strlen(cfg_def->comment));
|
||||
|
||||
_out_line(out, "%s%s%s%s%s%s%s\n", config_path,
|
||||
fprintf(out->fp, "%s%s%s%s%s%s%s\n", config_path,
|
||||
*summary || out->tree_spec->withversions ? " - ": "",
|
||||
*summary ? summary : "",
|
||||
*summary ? " " : "",
|
||||
@@ -1958,7 +1901,7 @@ static int _out_line_fn(const struct dm_config_node *cn, const char *line, void
|
||||
/* print with # at the front to comment out the line */
|
||||
if (_should_print_cfg_with_undef_def_val(out, cfg_def, cn)) {
|
||||
space_prefix_len = strspn(line, "\t ");
|
||||
_out_line(out, "%.*s%s%s\n", space_prefix_len, line, "# ",
|
||||
fprintf(out->fp, "%.*s%s%s\n", space_prefix_len, line, "# ",
|
||||
line + space_prefix_len);
|
||||
}
|
||||
return 1;
|
||||
@@ -1966,7 +1909,7 @@ static int _out_line_fn(const struct dm_config_node *cn, const char *line, void
|
||||
|
||||
/* print the line as it is */
|
||||
if (_should_print_cfg_with_undef_def_val(out, cfg_def, cn))
|
||||
_out_line(out, "%s\n", line);
|
||||
fprintf(out->fp, "%s\n", line);
|
||||
|
||||
if (out->tree_spec->valuesonly && !(cfg_def->type & CFG_TYPE_SECTION) && space_prefix_len)
|
||||
dm_pool_free(out->mem, (char *) line);
|
||||
@@ -1993,29 +1936,22 @@ int config_write(struct dm_config_tree *cft,
|
||||
.tree_spec = tree_spec,
|
||||
.mem = cft->mem
|
||||
};
|
||||
int free_fp = 1;
|
||||
int r = 1;
|
||||
|
||||
if (tree_spec->log_debug) {
|
||||
/* When using log_debug, we don't need a file pointer */
|
||||
baton.fp = NULL;
|
||||
free_fp = 0;
|
||||
} else if (!file) {
|
||||
if (!file) {
|
||||
baton.fp = stdout;
|
||||
file = "stdout";
|
||||
free_fp = 0;
|
||||
} else if (!(baton.fp = fopen(file, "w"))) {
|
||||
log_sys_error("open", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!tree_spec->log_debug)
|
||||
log_verbose("Dumping configuration to %s", file);
|
||||
log_verbose("Dumping configuration to %s", file);
|
||||
|
||||
if (tree_spec->withgeneralpreamble)
|
||||
_out_line(&baton, CFG_PREAMBLE_GENERAL);
|
||||
fprintf(baton.fp, CFG_PREAMBLE_GENERAL);
|
||||
if (tree_spec->withlocalpreamble)
|
||||
_out_line(&baton, CFG_PREAMBLE_LOCAL);
|
||||
fprintf(baton.fp, CFG_PREAMBLE_LOCAL);
|
||||
|
||||
if (!argc) {
|
||||
if (!dm_config_write_node_out(cft->root, &_out_spec, &baton)) {
|
||||
@@ -2035,7 +1971,7 @@ int config_write(struct dm_config_tree *cft,
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (free_fp && baton.fp && dm_fclose(baton.fp)) {
|
||||
if (baton.fp && baton.fp != stdout && dm_fclose(baton.fp)) {
|
||||
stack;
|
||||
r = 0;
|
||||
}
|
||||
@@ -2588,10 +2524,10 @@ const char *get_default_activation_mirror_image_fault_policy_CFG(struct cmd_cont
|
||||
int get_default_allocation_thin_pool_chunk_size_CFG(struct cmd_context *cmd, struct profile *profile)
|
||||
{
|
||||
uint32_t chunk_size;
|
||||
unsigned chunk_size_calc_policy;
|
||||
int chunk_size_calc_method;
|
||||
|
||||
if (!get_default_allocation_thin_pool_chunk_size(cmd, profile, &chunk_size,
|
||||
&chunk_size_calc_policy)) {
|
||||
&chunk_size_calc_method)) {
|
||||
stack; /* Ignore this error, never happens... */
|
||||
chunk_size = DEFAULT_THIN_POOL_CHUNK_SIZE * 2;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
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) */
|
||||
uint16_t deprecated_since_version; /* version since this item is deprecated */
|
||||
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 */
|
||||
@@ -177,7 +177,6 @@ struct config_def_tree_spec {
|
||||
unsigned withgeneralpreamble:1; /* include preamble for a general config file */
|
||||
unsigned withlocalpreamble:1; /* include preamble for a local config file */
|
||||
unsigned valuesonly:1; /* print only values without keys */
|
||||
unsigned log_debug:1; /* use log_debug() instead of file output */
|
||||
uint8_t *check_status; /* status of last tree check (currently needed for CFG_DEF_TREE_MISSING only) */
|
||||
};
|
||||
|
||||
@@ -244,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 checksum_only, int no_dup_node_check, int only_pv_summary);
|
||||
int skip_parse, 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);
|
||||
|
||||
@@ -215,7 +215,7 @@ cfg(config_checks_CFG, "checks", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
|
||||
"found is issued in verbose mode only).\n")
|
||||
|
||||
cfg(config_validate_metadata_CFG, "validate_metadata", config_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_VALIDATE_METADATA, vsn(2, 3, 28), NULL, 0, NULL,
|
||||
"Allows selecting the level of validation after metadata transformation.\n"
|
||||
"Allows to select the level of validation after metadata transformation.\n"
|
||||
"Validation takes extra CPU time to verify internal consistency.\n"
|
||||
"Accepted values:\n"
|
||||
" full\n"
|
||||
@@ -235,7 +235,7 @@ cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADV
|
||||
"Commands also accept this as a prefix on volume group names.\n")
|
||||
|
||||
cfg(devices_device_id_sysfs_dir_CFG, "device_id_sysfs_dir", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_UNSUPPORTED, CFG_TYPE_STRING, DEFAULT_DEVICE_ID_SYSFS_DIR, vsn(2, 3, 17), NULL, 0, NULL,
|
||||
"Location of sysfs for finding device ids (for testing).\n")
|
||||
"Location of sysfs for finding device ids (for testing.)\n")
|
||||
|
||||
cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL,
|
||||
"Directories containing device nodes to use with LVM.\n")
|
||||
@@ -353,7 +353,7 @@ cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENT
|
||||
"device is rejected. Unmatching path names do not affect the accept\n"
|
||||
"or reject decision. If no path names for a device match a pattern,\n"
|
||||
"then the device is accepted. Be careful mixing 'a' and 'r' patterns,\n"
|
||||
"as the combination might produce unexpected results (test changes).\n"
|
||||
"as the combination might produce unexpected results (test changes.)\n"
|
||||
"Run vgscan after changing the filter to regenerate the cache.\n"
|
||||
"#\n"
|
||||
"Example\n"
|
||||
@@ -401,7 +401,7 @@ cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED
|
||||
cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SYSFS_SCAN, vsn(1, 0, 8), NULL, 0, NULL,
|
||||
"Restrict device scanning to block devices appearing in sysfs.\n"
|
||||
"This is a quick way of filtering out block devices that are not\n"
|
||||
"present on the system. sysfs must be part of the kernel and mounted.\n")
|
||||
"present on the system. sysfs must be part of the kernel and mounted.)\n")
|
||||
|
||||
cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SCAN_LVS, vsn(2, 2, 182), NULL, 0, NULL,
|
||||
"Allow LVM LVs to be used as PVs. When enabled, LVM commands will\n"
|
||||
@@ -409,7 +409,7 @@ cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED
|
||||
"avoid using PVs that belong to guest images stored on LVs.\n"
|
||||
"When enabled, the LVs scanned should be restricted using the\n"
|
||||
"devices file or the filter. This option does not enable autoactivation\n"
|
||||
"of layered VGs, which requires editing LVM udev rules (see LVM_PVSCAN_ON_LVS).\n")
|
||||
"of layered VGs, which requires editing LVM udev rules (see LVM_PVSCAN_ON_LVS.)\n")
|
||||
|
||||
cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL,
|
||||
"Ignore devices that are components of DM multipath devices.\n")
|
||||
@@ -471,7 +471,7 @@ cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CF
|
||||
"penalty, e.g. MD chunk size. optimal_io_size is the device's\n"
|
||||
"preferred unit of receiving I/O, e.g. MD stripe width.\n"
|
||||
"minimum_io_size is used if optimal_io_size is undefined (0).\n"
|
||||
"If md_chunk_alignment is enabled, it will detect the optimal_io_size.\n"
|
||||
"If md_chunk_alignment is enabled, that detects the optimal_io_size.\n"
|
||||
"default_data_alignment and md_chunk_alignment will be overridden\n"
|
||||
"if they are not aligned with the value detected for this setting.\n"
|
||||
"This setting is overridden by data_alignment and the --dataalignment\n"
|
||||
@@ -604,7 +604,7 @@ cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_z
|
||||
"is not claimed incorrectly by other tools because of old signatures\n"
|
||||
"from previous use. The number of signatures that LVM can detect\n"
|
||||
"depends on the detection code that is selected (see\n"
|
||||
"use_blkid_wiping). Wiping each detected signature must be confirmed.\n"
|
||||
"use_blkid_wiping.) Wiping each detected signature must be confirmed.\n"
|
||||
"When this setting is disabled, signatures on new LVs are not detected\n"
|
||||
"or erased unless the --wipesignatures option is used directly.\n")
|
||||
|
||||
@@ -632,7 +632,7 @@ cfg(allocation_cache_metadata_format_CFG, "cache_metadata_format", allocation_CF
|
||||
"Accepted values:\n"
|
||||
" 0 Automatically detected best available format\n"
|
||||
" 1 Original format\n"
|
||||
" 2 Improved second-generation format\n"
|
||||
" 2 Improved 2nd. generation format\n"
|
||||
"#\n")
|
||||
|
||||
cfg(allocation_cache_mode_CFG, "cache_mode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 128), NULL, 0, NULL,
|
||||
@@ -676,22 +676,13 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
|
||||
"For cache target v1.9 the recommended maximum is 1000000 chunks.\n"
|
||||
"Using cache pool with more chunks may degrade cache performance.\n")
|
||||
|
||||
cfg(allocation_pvmove_max_segment_size_mb_CFG, "pvmove_max_segment_size_mb", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PVMOVE_MAX_SEGMENT_SIZE_MB, vsn(2, 3, 36), NULL, 0, NULL,
|
||||
"Maximum size in MiB of segments to mirror at once during pvmove.\n"
|
||||
"When pvmove needs to move large segments, it will split them into\n"
|
||||
"smaller chunks of this size, mirror each chunk, and update metadata\n"
|
||||
"between chunks. This prevents mirroring excessively large amounts\n"
|
||||
"of data at once. A value of 0 (default) means no limit - the entire\n"
|
||||
"segment will be mirrored at once. Setting this to e.g. 10240 will\n"
|
||||
"limit each mirroring operation to 10GiB chunks.\n")
|
||||
|
||||
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
|
||||
"Thin pool metadata and data will always use different PVs.\n")
|
||||
|
||||
cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
|
||||
"Older versions of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
|
||||
"This is slightly less than the actual maximum 15.88 GiB.\n"
|
||||
"For compatibility with older versions and to use the cropped size, set to 1.\n")
|
||||
"Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
|
||||
"This is slightly less then the actual maximum 15.88 GiB.\n"
|
||||
"For compatibility with older version and use of cropped size set to 1.\n")
|
||||
|
||||
cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
|
||||
"Thin pool data chunks are zeroed before they are first used.\n"
|
||||
@@ -957,7 +948,7 @@ cfg(log_prefix_CFG, "prefix", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW
|
||||
|
||||
cfg(log_activation_CFG, "activation", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
|
||||
"Log messages during activation.\n"
|
||||
"Do not use this in low memory situations (can deadlock).\n")
|
||||
"Don't use this in low memory situations (can deadlock).\n")
|
||||
|
||||
cfg(log_activate_file_CFG, "activate_file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL)
|
||||
|
||||
@@ -1092,7 +1083,7 @@ cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, CFG
|
||||
"Additionally, read-only commands that encounter metadata in need of\n"
|
||||
"repair will still be allowed to proceed exactly as if the repair had\n"
|
||||
"been performed (except for the unchanged vg_seqno). Inappropriate\n"
|
||||
"use could corrupt your system, so seek advice first!\n")
|
||||
"use could mess up your system, so seek advice first!\n")
|
||||
|
||||
cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_SEGTYPE, vsn(2, 2, 87), "@DEFAULT_MIRROR_SEGTYPE@", 0, NULL,
|
||||
"The segment type used by the short mirroring option -m.\n"
|
||||
@@ -1122,7 +1113,7 @@ cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECT
|
||||
cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 3, 2), NULL, 0, NULL,
|
||||
"Enable mirrored 'mirror' log type for testing.\n"
|
||||
"#\n"
|
||||
"This type is deprecated for creation or conversion but can\n"
|
||||
"This type is deprecated to create or convert to but can\n"
|
||||
"be enabled to test that activation of existing mirrored\n"
|
||||
"logs and conversion to disk/core works.\n"
|
||||
"#\n"
|
||||
@@ -1211,7 +1202,7 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D
|
||||
cfg(global_sanlock_align_size_CFG, "sanlock_align_size", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SANLOCK_ALIGN_SIZE, vsn(2, 3, 27), NULL, 0, NULL,
|
||||
"The sanlock lease size in MiB to use on disks with a 4K sector size.\n"
|
||||
"Possible values are 1,2,4,8. The default is 8, which supports up to\n"
|
||||
"2000 hosts (and max host_id 2000). Smaller values support smaller\n"
|
||||
"2000 hosts (and max host_id 2000.) Smaller values support smaller\n"
|
||||
"numbers of max hosts (and max host_ids): 250, 500, 1000, 2000 for\n"
|
||||
"lease sizes 1,2,4,8. Disks with 512 byte sectors always use 1MiB\n"
|
||||
"leases and support 2000 hosts, and are not affected by this setting.\n")
|
||||
@@ -1219,7 +1210,7 @@ cfg(global_sanlock_align_size_CFG, "sanlock_align_size", global_CFG_SECTION, CFG
|
||||
cfg(global_lvmlockctl_kill_command_CFG, "lvmlockctl_kill_command", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "", vsn(2, 3, 12), NULL, 0, NULL,
|
||||
"The command that lvmlockctl --kill should use to force LVs offline.\n"
|
||||
"The lvmlockctl --kill command is run when a shared VG has lost\n"
|
||||
"access to locks (e.g. when sanlock has lost access to storage).\n"
|
||||
"access to locks (e.g. when sanlock has lost access to storage.)\n"
|
||||
"An empty string means that there will be no automatic attempt by\n"
|
||||
"lvmlockctl --kill to forcibly shut down LVs in the VG, and the user\n"
|
||||
"can manually intervene as described in lvmlockd(8).\n"
|
||||
@@ -1341,14 +1332,10 @@ cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEF
|
||||
"The full path to the fsadm command.\n"
|
||||
"LVM uses this command to help with lvresize -r operations.\n")
|
||||
|
||||
cfg(global_lvresize_fs_helper_executable_CFG, "lvresize_fs_helper_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LVRESIZE_FS_HELPER_PATH, vsn(2, 3, 33), "@LVRESIZE_FS_HELPER_PATH@", 0, NULL,
|
||||
"The full path to the lvresize_fs_helper command.\n"
|
||||
"LVM uses this command to help with filesystem operations during lvresize.\n")
|
||||
|
||||
cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SYSTEM_ID_SOURCE, vsn(2, 2, 117), NULL, 0, NULL,
|
||||
"The method LVM uses to set the local system ID.\n"
|
||||
"Volume Groups can also be given a system ID (by vgcreate, vgchange,\n"
|
||||
"or vgimport). A VG on shared storage devices is accessible only to\n"
|
||||
"or vgimport.) A VG on shared storage devices is accessible only to\n"
|
||||
"the host with a matching system ID. See 'man lvmsystemid' for\n"
|
||||
"information on limitations and correct usage.\n"
|
||||
"#\n"
|
||||
@@ -1652,7 +1639,7 @@ cfg(activation_mirror_device_fault_policy_CFG, "mirror_device_fault_policy", act
|
||||
cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD, vsn(2, 2, 75), NULL, 0, NULL,
|
||||
"Auto-extend a snapshot when its usage exceeds this percent.\n"
|
||||
"Setting this to 100 disables automatic extension.\n"
|
||||
"The minimum value is 50 (a smaller value is treated as 50).\n"
|
||||
"The minimum value is 50 (a smaller value is treated as 50.)\n"
|
||||
"Also see snapshot_autoextend_percent.\n"
|
||||
"Automatic extension requires dmeventd to be monitoring the LV.\n"
|
||||
"#\n"
|
||||
@@ -1678,7 +1665,7 @@ cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", a
|
||||
cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_threshold", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD, vsn(2, 2, 89), NULL, 0, NULL,
|
||||
"Auto-extend a thin pool when its usage exceeds this percent.\n"
|
||||
"Setting this to 100 disables automatic extension.\n"
|
||||
"The minimum value is 50 (a smaller value is treated as 50).\n"
|
||||
"The minimum value is 50 (a smaller value is treated as 50.)\n"
|
||||
"Also see thin_pool_autoextend_percent.\n"
|
||||
"Automatic extension requires dmeventd to be monitoring the LV.\n"
|
||||
"#\n"
|
||||
@@ -1704,7 +1691,7 @@ cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent",
|
||||
cfg(activation_vdo_pool_autoextend_threshold_CFG, "vdo_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_AUTOEXTEND_THRESHOLD, VDO_1ST_VSN, NULL, 0, NULL,
|
||||
"Auto-extend a VDO pool when its usage exceeds this percent.\n"
|
||||
"Setting this to 100 disables automatic extension.\n"
|
||||
"The minimum value is 50 (a smaller value is treated as 50).\n"
|
||||
"The minimum value is 50 (a smaller value is treated as 50.)\n"
|
||||
"Also see vdo_pool_autoextend_percent.\n"
|
||||
"Automatic extension requires dmeventd to be monitoring the LV.\n"
|
||||
"#\n"
|
||||
@@ -1896,7 +1883,7 @@ cfg(report_output_format_CFG, "output_format", report_CFG_SECTION, CFG_PROFILABL
|
||||
|
||||
cfg(report_compact_output_CFG, "compact_output", report_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REP_COMPACT_OUTPUT, vsn(2, 2, 115), NULL, 0, NULL,
|
||||
"Do not print empty values for all report fields.\n"
|
||||
"If enabled, all fields that do not have a value set for any of the\n"
|
||||
"If enabled, all fields that don't have a value set for any of the\n"
|
||||
"rows reported are skipped and not printed. Compact output is\n"
|
||||
"applicable only if report/buffered is enabled. If you need to\n"
|
||||
"compact only specified fields, use compact_output=0 and define\n"
|
||||
@@ -1904,7 +1891,7 @@ cfg(report_compact_output_CFG, "compact_output", report_CFG_SECTION, CFG_PROFILA
|
||||
|
||||
cfg(report_compact_output_cols_CFG, "compact_output_cols", report_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_PROFILABLE | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_COMPACT_OUTPUT_COLS, vsn(2, 2, 133), NULL, 0, NULL,
|
||||
"Do not print empty values for specified report fields.\n"
|
||||
"If defined, specified fields that do not have a value set for any\n"
|
||||
"If defined, specified fields that don't have a value set for any\n"
|
||||
"of the rows reported are skipped and not printed. Compact output\n"
|
||||
"is applicable only if report/buffered is enabled. If you need to\n"
|
||||
"compact all fields, use compact_output=1 instead in which case\n"
|
||||
@@ -2288,12 +2275,6 @@ cfg(local_system_id_CFG, "system_id", local_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_D
|
||||
"system_id = \"host1\"\n"
|
||||
"#\n")
|
||||
|
||||
cfg(local_pr_key_CFG, "pr_key", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, 0, vsn(2, 3, 32), NULL, 0, NULL,
|
||||
"The local persistent reservation key in hexadecimal.\n"
|
||||
"The value must be unique among all hosts using the same VG.\n"
|
||||
"The max length is 16 hex characters (8 bytes), plus an optional\n"
|
||||
"0x prefix. If pr_key is not set, host_id will be used to create a key.\n")
|
||||
|
||||
cfg_array(local_extra_system_ids_CFG, "extra_system_ids", local_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 117), NULL, 0, NULL,
|
||||
"A list of extra VG system IDs the local host can access.\n"
|
||||
"VGs with the system IDs listed here (in addition to the host's own\n"
|
||||
@@ -2307,8 +2288,6 @@ cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
|
||||
"The sanlock host_id used by lvmlockd. This must be unique among all the hosts\n"
|
||||
"using shared VGs with sanlock. Accepted values are 1-2000, except when sanlock_align_size\n"
|
||||
"is configured to 1, 2 or 4, which correspond to max host_id values of 250, 500, or 1000.\n"
|
||||
"When using persistent reservations, lvm will generate a PR key from the host_id\n"
|
||||
"if pr_key is not defined. All hosts using a sanlock shared VG with PR must use\n"
|
||||
"the same approach for configuring their PR key (pr_key or host_id.)\n")
|
||||
"Applicable only if LVM is compiled with support for lvmlockd+sanlock.\n")
|
||||
|
||||
cfg(CFG_COUNT, NULL, root_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)
|
||||
|
||||
@@ -161,8 +161,6 @@
|
||||
#define DEFAULT_CACHE_METADATA_FORMAT CACHE_METADATA_FORMAT_UNSELECTED /* Autodetect */
|
||||
#define DEFAULT_CACHE_MODE "writethrough"
|
||||
|
||||
#define DEFAULT_PVMOVE_MAX_SEGMENT_SIZE_MB 0
|
||||
|
||||
|
||||
/* VDO defaults */
|
||||
#define DEFAULT_VDO_USE_COMPRESSION (true)
|
||||
@@ -194,7 +192,6 @@
|
||||
|
||||
|
||||
#define DEFAULT_FSADM_PATH FSADM_PATH
|
||||
#define DEFAULT_LVRESIZE_FS_HELPER_PATH LVRESIZE_FS_HELPER_PATH
|
||||
|
||||
#define DEFAULT_UMASK 0077
|
||||
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
#ifndef _LVM_BTREE_H
|
||||
#define _LVM_BTREE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct btree;
|
||||
struct dm_pool;
|
||||
|
||||
struct btree *btree_create(struct dm_pool *mem);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user