1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-11-15 00:23:51 +03:00

Compare commits

..

5 Commits

Author SHA1 Message Date
Zdenek Kabelac
d63165de4b generate 2024-11-20 13:10:48 +01:00
Zdenek Kabelac
7c88012ded command: use aliases for colon and columns
pvdisplay, vgdisplay, lvdisplay command can have an individual
descrption of  --colon and --columns option.
2024-11-20 13:10:40 +01:00
Zdenek Kabelac
8d2cb42166 man: add ARG_MAN_ALIAS_OPT alias support
For some options we need specific specialization for certain commands.
To make the solution 'generic' let's introduce ARG_MAN_ALIAS_OPT flag.
Such an option then can be used  in command-lines.in file
to reference the specific instance of a common option.

Original option is stored as _ARG within short_opt field
(so we do not add new field to every arg for this)
Then command is supposed to accepted only original option.
However with the man page creation we can have individual
versions of such an option.
2024-11-20 13:10:40 +01:00
Zdenek Kabelac
bee8c1b921 man: refactor variant check
Remove unnecessary checks and move the comment to the 1st. check.
2024-11-20 13:00:29 +01:00
Zdenek Kabelac
e9605bacde man: refactor printing option
When generating man pages, use a single function to print
option with its short & long name.
2024-11-20 13:00:27 +01:00
818 changed files with 23803 additions and 49662 deletions

View File

@@ -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

View File

@@ -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
View File

@@ -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

View File

@@ -1 +1 @@
2.03.37(2)-git (2025-10-24)
2.03.29(2)-git (2024-11-04)

View File

@@ -1 +1 @@
1.02.211-git (2025-10-24)
1.02.203-git (2024-11-04)

111
WHATS_NEW
View File

@@ -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).

View File

@@ -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
View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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
View File

@@ -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

View File

@@ -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!])])

View File

@@ -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;
}
*/

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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.");

View File

@@ -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

View File

@@ -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"

View File

@@ -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" */

View File

@@ -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);

View File

@@ -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';

View File

@@ -25,8 +25,6 @@
#ifndef _DMEVENTD_LVMWRAP_H
#define _DMEVENTD_LVMWRAP_H
#include <stddef.h>
struct dm_pool;
int dmeventd_lvm2_init(void);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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')

View File

@@ -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

View File

@@ -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()

View File

@@ -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()

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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];

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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---");

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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 \

View File

@@ -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);

View File

@@ -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) {

View File

@@ -16,8 +16,6 @@
#ifndef LIB_DMTARGETS_H
#define LIB_DMTARGETS_H
#include "device_mapper/all.h"
#include <inttypes.h>
#include <sys/types.h>

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -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)))

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -14,7 +14,7 @@
*/
#ifdef VALGRIND_POOL
#include <memcheck.h>
#include "memcheck.h"
#endif
#include "base/memory/zalloc.h"

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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++ = '|';
}

View File

@@ -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

View File

@@ -16,8 +16,6 @@
#ifndef _DM_PARSE_REGEX_H
#define _DM_PARSE_REGEX_H
#include "device_mapper/misc/dmlib.h"
enum {
CAT,
STAR,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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)

View File

@@ -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
View 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)

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]
-->

View File

@@ -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"]]

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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, &params)) {
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, &params)) {
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, &params)) {
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.",

View File

@@ -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;

View File

@@ -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
View File

@@ -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)

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -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