1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-08-23 05:49:28 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
f59cb6632b pvscan: use alternate device names from DEVLINKS to check filter
The filter may contains a symlink for the device, and that symlink
may not yet be created when our udev rule runs pvscan --cache using
the kernel dev name.  The kernel dev name does not match the symlink
name in the filter, so pvscan will ignore the device.  udev sets
the DEVLINKS env variable to a list of link names for the device
that will be created, so check the filter with that set of names.
2023-01-19 17:37:31 -06:00
519 changed files with 17644 additions and 30000 deletions

5
.gitignore vendored
View File

@ -14,8 +14,6 @@
*.so
*.so.*
*.sw*
*.su
*.patch
*~
# gcov files:
@ -52,6 +50,7 @@ daemons/dmfilemapd
daemons/lvmetad/
tools/man-generator
tools/man-generator.c
test/.lib-dir-stamp
test/.tests-stamp
@ -145,8 +144,6 @@ test/lib/lvmchange
test/lib/lvmdbusd.profile
test/lib/lvmdevices
test/lib/lvmetad
test/lib/lvmlockctl
test/lib/lvmlockd
test/lib/lvmpolld
test/lib/lvm_import_vdo
test/lib/lvm_vdo_wrapper

View File

@ -1,104 +0,0 @@
stages:
- approve
- test
approve1:
stage: approve
script:
- echo "Approved..."
rules:
# TODO: Filter only safe repositories, or user in developers
- if: $CI_PROJECT_PATH != "csonto/lvm2" && $CI_PROJECT_PATH != "lvmteam/lvm2"
when: manual
# TODO: for other branches than main/rhel: run pipeline only when requested:
- if: $CI_COMMIT_BRANCH != "main" && $CI_COMMIT_BRANCH !~ "^rhel.*"
when: manual
- when: on_success
allow_failure: false
pages:
image: elecnix/ikiwiki
stage: test
script:
- ikiwiki --setup ikiwiki.setup --libdir themes/ikistrap/lib
artifacts:
paths:
- public
only:
refs:
- main
changes:
- doc/**/*
- ikiwiki.setup
# TODO:
# - check results of autoreconf and make generate - may need additional commit
# - we need a particular setup (rawhide OR latest supported fedora?)
# - do make rpm and publish results as artifacts - we will use packit/COPR for this eventually
# Run on any commits to main (master), rhel8, rhel9 branches
test-job:
stage: test
parallel:
matrix:
- TAG: rhel8
CONFIGURE: >
--with-cluster=internal
--enable-cmirrord
- TAG: rhel9
CONFIGURE: >
--with-default-use-devices-file=1
--enable-app-machineid
--enable-editline
--disable-readline
artifacts:
paths:
- test/results/
expire_in: 1 week
tags:
- ${TAG}
timeout: 2h
script:
# Common options go here, diffs to the above matrix
- >
./configure ${CONFIGURE}
--enable-fsadm
--enable-write_install
--enable-pkgconfig
--enable-cmdlib
--enable-dmeventd
--enable-blkid_wiping
--enable-udev_sync
--with-thin=internal
--with-cache=internal
--enable-lvmpolld
--enable-lvmlockd-dlm --enable-lvmlockd-dlmcontrol
--enable-lvmlockd-sanlock
--enable-dbus-service --enable-notify-dbus
--enable-dmfilemapd
--with-writecache=internal
--with-vdo=internal --with-vdo-format=/usr/bin/vdoformat
--with-integrity=internal
--disable-silent-rules
- make
- rm -rf test/results
- mkdir -p /dev/shm/lvm2-test
- mount -o remount,dev /dev/shm
# TODO: Need to distinguish failed test from failed harness
# TODO: Also need a way to find if run is incomplete, e.g. full disk resulting in many skipped tests
- VERBOSE=0 BATCH=1 LVM_TEST_DIR=/dev/shm/lvm2-test make check || true
- 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|')
# 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
rules:
# Filter only safe repositories, or user in developers:
# NOTE: Already done in approve stage, may be more caution than necessary
- if: $CI_PROJECT_PATH != "csonto/lvm2" && $CI_PROJECT_PATH != "lvmteam/lvm2"
when: manual
- when: on_success

View File

@ -38,7 +38,7 @@ ifeq ($(MAKECMDGOALS),distclean)
udev po
tools.distclean: test.distclean
endif
DISTCLEAN_DIRS += lcov_reports* autom4te.cache
DISTCLEAN_DIRS += lcov_reports*
DISTCLEAN_TARGETS += config.cache config.log config.status make.tmpl
include make.tmpl
@ -55,7 +55,7 @@ po: tools daemons
man: tools
all_man: tools
test: tools daemons
unit-test run-unit-test: test libdm
unit-test run-unit-test: test
daemons.device-mapper: libdm.device-mapper
tools.device-mapper: libdm.device-mapper
@ -127,7 +127,6 @@ all_man:
install_system_dirs:
$(INSTALL_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_SYS_DIR)/devices
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_ARCHIVE_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_BACKUP_DIR)
$(INSTALL_ROOT_DIR) $(DESTDIR)$(DEFAULT_CACHE_DIR)
@ -172,7 +171,6 @@ 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 " rpm Build rpm."
@echo " run-unit-test Run unit tests."
@echo " tags Generate c/etags."

29
README
View File

@ -1,5 +1,7 @@
This tree contains the LVM2 and device-mapper tools and libraries.
This is development branch, for stable 2.02 release see stable-2.02 branch.
For more information about LVM2 read the changelog in the WHATS_NEW file.
Installation instructions are in INSTALL.
@ -10,30 +12,20 @@ Tarballs are available from:
https://github.com/lvmteam/lvm2/releases
The source code is stored in git:
https://gitlab.com/lvmteam/lvm2
Clone:
git clone git@gitlab.com:lvmteam/lvm2.git
Anonymous access:
git clone https://gitlab.com/lvmteam/lvm2.git
Mirrored to:
* https://github.com/lvmteam/lvm2
https://sourceware.org/git/?p=lvm2.git
git clone git://sourceware.org/git/lvm2.git
mirrored to:
https://github.com/lvmteam/lvm2
git clone https://github.com/lvmteam/lvm2.git
git clone git@github.com:lvmteam/lvm2.git
* https://sourceware.org/git/?p=lvm2.git
git clone https://sourceware.org/git/lvm2.git
git clone git://sourceware.org/git/lvm2.git
Mailing list for general discussion related to LVM2:
linux-lvm@lists.linux.dev
Subscribe via email to: linux-lvm+subscribe@lists.linux.dev
Archive https://lore.kernel.org/linux-lvm/
Older archive https://listman.redhat.com/archives/linux-lvm/
linux-lvm@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/linux-lvm
Mailing lists for LVM2 development, patches and commits:
lvm-devel@lists.linux.dev
Subscribe via email to: lvm-devel+subscribe@lists.linux.dev
Archive https://lore.kernel.org/lvm-devel/
Older archive https://listman.redhat.com/archives/lvm-devel/
lvm-devel@redhat.com
Subscribe from https://www.redhat.com/mailman/listinfo/lvm-devel
lvm2-commits@lists.fedorahosted.org (Read-only archive of commits)
Subscribe from https://fedorahosted.org/mailman/listinfo/lvm2-commits
@ -49,7 +41,6 @@ Website:
Report upstream bugs at:
https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper
or open issues at:
https://gitlab.com/groups/lvmteam/-/issues
https://github.com/lvmteam/lvm2/issues
The source code repository used until 7th June 2012 is accessible using CVS:

View File

@ -21,11 +21,6 @@ You MUST disable (or mask) any LVM daemons:
- clvmd
- cmirrord
Some lvm.conf options should be set:
- global/event_activation = 0
- activation/monitoring = 0
For running cluster tests, we are using singlenode locking. Pass
`--with-clvmd=singlenode` to configure.

View File

@ -1 +1 @@
2.03.25(2)-git (2024-05-16)
2.03.19(2)-git (2022-12-22)

View File

@ -1 +1 @@
1.02.199-git (2024-05-16)
1.02.191-git (2022-12-22)

125
WHATS_NEW
View File

@ -1,123 +1,8 @@
Version 2.03.25 -
==================
Utilize more radix_tree instead of dm_hash and btree.
Refactor DM uuid caching from device_mapper directory.
Enhance checking for DM uuid device.
Fix lvm shell command completion on tab key (2.03.24).
Avoid lockd_vg call to lvmlockd for local VGs.
Allow forced change of locktype from none.
Handle OPTIONS defined in /etc/sysconfig/lvmlockd.
Version 2.03.24 - 16th May 2024
===============================
Lvconvert supports VDO options for thin-pool with vdo conversion.
Improve placement to .data.rel.ro and .rodata sections.
Fix support for -y and -W when creating thinpool with vdo.
Bettter support for runtime valgrind detection.
Allow command interruption when communicating with dmeventd.
Fix resize of VDO volume used for thin pool data volume.
Use -Wl,-z,now and -Wl,--as-needed for compilation by default.
Require 3.7 as minimal version for sanlock.
Share code for closing opened desriptors on program startup.
Fix memleak in lvmcache.
Add configure --with-default-event-activation=ON setting.
Fix return value from reporter function when hitting internal error.
Skip checking of pools for lvremove and vgremove commands.
VDO modprobes dm-vdo for 6.9 kernel and kvdo for older kernel version.
Fix lvs reporting for VDO volumes with new upstream kernel driver.
Don't import DM_UDEV_DISABLE_OTHER_RULES_FLAG in LVM rules, DM rules cover it.
Fix table line generation for cache snapshots using cachevol.
Enhance lvconvert support for external origins stacking.
When swapping LV names also swap properties like hostname, time and data.
Fix removal of stacked external origins.
Lock filesystem when converting volume to read-only external origin.
Support external origin between different thin-pool.
Improve validation of acceptable volumes for external origins.
Reduce amount of preloaded devices for complex device trees.
Avoid logging problems from monitoring snapshots with inactive origins.
Check for cache policy module presence in kernel's builtin modules file.
Add configure --with-modulesdir to select kernel modules directory.
Support creation of thin-pool with VDO use for its data volume.
Version 2.03.23 - 21st November 2023
version 2.03.19 -
====================================
Set the first lv_attr flag for raid integrity images to i or I.
Add -A option for pvs and pvscan to show PVs outside devices file.
Improve searched_devnames temp file usage to prevent redundant scanning.
Change default search_for_devnames from auto to all.
Add lvmdevices --refresh to search for missing PVIDs on all devices.
Add comparison between old and new entries in lvmdevices --check.
Fix device_id matching order - match non-devname first.
Fix "lvconvert -m 0" when there is other than first in-sync leg.
Use system.devices as default for dmeventd when dmeventd.devices is undefined.
Accept WWIDs containing QEMU HARDDISK for device_id.
Improve handling of non-standard WWID prefixes used for device_id.
Configure automatically enables cmdlib for dmeventd and notify-dbus for dbus.
Fix hint calculation for pools with zero or error segment.
Configure supports --disable-shared to build only static binaries.
Configure supports --without-{blkid|systemd|udev} for easier static build.
Refresh device ids if the system changes.
Fix pvmove when specifying raid components as moved LVs.
Enhance error detection for lvm_import_vdo.
Support PV lists with thin lvconvert.
Fix support for lvm_import_vdo with SCSI VDO volumes.
Fix locking issue leading to hanging concurrent vgchange --refresh.
Recognize lvm.conf report/headings=2 for full column names in report headings.
Add --headings none|abbrev|full cmd line option to set report headings type.
Fix conversion to thin pool using lvmlockd.
Fix conversion from thick into thin volume using lvmlockd.
Require writable LV for conversion to vdo pool.
Fix return value from lvconvert integrity remove.
Preserve UUID for pool metadata spare.
Preserve UUID for swapped pool metadata.
Rewrite validation of device name entries used as device_id.
version 2.03.22 - 02nd August 2023
==================================
Fix pv_major/pv_minor report field types so they are integers, not strings.
Add lvmdevices --delnotfound to delete entries for missing devices.
Always use cachepool name for metadata backup LV for lvconvert --repair.
Make metadata backup LVs read-only after pool's lvconvert --repair.
Improve VDO and Thin support with lvmlockd.
Handle 'lvextend --usepolicies' for pools for all activation variants.
Fix memleak in vgchange autoactivation setup.
Update py-compile building script.
Support conversion from thick to fully provisioned thin LV.
Cache/Thin-pool can use error and zero volumes for testing.
Individual thin volume can be cached, but cannot take snapshot.
Better internal support for handling error and zero target (for testing).
Resize COW above trimmed maximal size is does not return error.
Support parsing of vdo geometry format version 4.
Add lvm.conf thin_restore and cache_restore settings.
Handle multiple mounts while resizing volume with a FS.
Handle leading/trailing spaces in sys_wwid and sys_serial used by device_id.
Enhance lvm_import_vdo and use snapshot when converting VDO volume.
Fix parsing of VDO metadata.
Fix failing -S|--select for non-reporting cmds if using LV info/status fields.
Allow snapshots of raid+integrity LV.
Fix multisegment RAID1 allocator to prevent using single disk for more legs.
version 2.03.21 - 21st April 2023
=================================
Fix activation of vdo-pool for with 0 length headers (converted pools).
Avoid printing internal init messages when creation integration devices.
Allow (write)cache over raid+integrity LV.
version 2.03.20 - 21st March 2023
=================================
Fix segfault if using -S|--select with log/report_command_log=1 setting.
Configure now fails when requested lvmlockd dependencies are missing.
Add some configure Gentoo enhancements for static builds.
version 2.03.19 - 21st February 2023
====================================
Configure supports --with-systemd-run executed from udev rules.
Enhancement for build with MuslC systemd and non-bash system shells (dash).
Do not reset SYSTEMD_READY variable in udev for PVs on MD and loop devices.
Ensure udev is processing origin LV before its thick snapshots LVs.
Fix and improve runtime memory size detection for VDO volumes.
version 2.03.18 - 22nd December 2022
version 2.03.18 - 22nd december 2022
====================================
Fix issues reported by coverity scan.
Fix warning for thin pool overprovisioning on lvextend (2.03.17).
@ -239,7 +124,7 @@ Version 2.03.12 - 07th May 2021
Fix IMSM MD RAID detection on 4k devices.
Check for presence of VDO target before starting any conversion.
Support metatadata profiles with volume VDO pool conversions.
Support -Zn for conversion of already formatted VDO pools.
Support -Zn for conversion of already formated VDO pools.
Avoid removing LVs on error path of lvconvert during creation volumes.
Fix crashing lvdisplay when thin volume was waiting for merge.
Support option --errorwhenfull when converting volume to thin-pool.
@ -3325,7 +3210,7 @@ Version 2.02.68 - 23rd June 2010
Add device name and offset to raw_read_mda_header error messages.
Honour log argument when down-converting stacked mirror.
Sleep to workaround clvmd -S race: socket closed early and server drops cmd.
Use early udev synchronization and update of dev nodes for clustered mirrors.
Use early udev synchronisation and update of dev nodes for clustered mirrors.
Remove incorrect inclusion of kdev_t.h from cmirrord/functions.h.
Add man pages for lvmconf and non-existent lvmsadc and lvmsar tools.
Exit successfully when using -o help (but not -o +help) with LVM reports.
@ -5459,5 +5344,3 @@ Display output. Some metadata information cannot yet be displayed.
Recovery tools to salvage "lost" metadata directly from the disks:
but we hope the new format will mean such tools are hardly ever needed!

View File

@ -1,48 +1,5 @@
Version 1.02.199 -
===================
Version 1.02.198 - 16th May 2024
================================
Fix static only compilation of libdevmapper.a and dmsetup tool.
Use better code for closing opened descriptors when starting dmeventd.
Correct dmeventd -R for systemd environment.
Restart of dmeventd -R checks pid file to detect running dmeventd first.
Query with dmeventd -i quickly ends when there is no running dmeventd.
Enhance dm_get_status_raid to handle mismatching status or reported legs.
Create /dev/disk/by-label symlinks for DM devs that have crypto as next layer.
Persist udev db for DM devs on cleanup used in initrd to rootfs transition.
Process synthetic udev events other than 'add/change' as 'change' events.
Increase DM_UDEV_RULES_VSN to 3 to indicate changed udev rules.
Rename DM_NOSCAN to .DM_NOSCAN so it's not stored in udev db.
Rename DM_SUSPENDED to .DM_SUSPENDED so it's not stored in udev db.
Do not import DM_UDEV_DISABLE_OTHER_RULES_FLAG from db in 10-dm-disk.rules.
Test DISK_RO after importing properties from db in 10-dm.rules.
Also import ID_FS_TYPE in 13-dm-disk.rules from db if needed.
Version 1.02.197 - 21st November 2023
Version 1.02.191 -
=====================================
Fix invalid JSON report if using DM_REPORT_OUTPUT_MULTIPLE_TIMES and selection.
Propagate ioctl errno from dm_task_run when creating new table line.
Add support for group aliases in dmstats.
Add support for exit-on file for dmeventd to reduce shutdown delays.
Add configure option --with-dmeventd-exit-on-path to specify default path.
Add dmsetup --headings none|abbrev|full to set report headings type.
Add DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS to provide alternative headings.
Version 1.02.196 - 02nd August 2023
===================================
Version 1.02.195 - 21st April 2023
==================================
Version 1.02.193 - 21st March 2023
==================================
Version 1.02.191 - 21st February 2023
=====================================
Improve parallel creation of /dev/mapper/control device node.
Import previous ID_FS_* udev records in 13-dm-disk.rules for suspended DM dev.
Remove NAME="mapper/control" rule from 10-dm.rules to avoid udev warnings.
Version 1.02.189 - 22nd December 2022
=====================================
@ -1153,7 +1110,7 @@ Version 1.02.37 - 15th September 2009
Version 1.02.36 - 6th August 2009
=================================
Add udevcookies, udevcomplete, udevcomplete_all and --noudevwait to dmsetup.
Add libdevmapper functions to support synchronization with udev.
Add libdevmapper functions to support synchronisation with udev.
Version 1.02.35 - 28th July 2009
================================
@ -1556,5 +1513,3 @@ Version 1.00.08 - 27 Feb 2004
Fixed DESTDIR for make install/install_static_lib.
Updated README/INSTALL to reflect move to sources.redhat.com.
Updated autoconf files to 2003-06-17.

View File

@ -62,24 +62,6 @@ AC_DEFUN([AC_TRY_LDFLAGS],
fi
])
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
dnl -------------------------------------------
dnl Since: 0.28
dnl
dnl Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])dnl PKG_CHECK_VAR
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html
# ===========================================================================

34
aclocal.m4 vendored
View File

@ -69,8 +69,8 @@ AC_DEFUN([AX_PYTHON_MODULE],[
fi
])
# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*-
# serial 12 (pkg-config-0.29.2)
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 11 (pkg-config-0.29.1)
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
@ -112,7 +112,7 @@ dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
[m4_define([PKG_MACROS_VERSION], [0.29.2])
[m4_define([PKG_MACROS_VERSION], [0.29.1])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
@ -157,7 +157,7 @@ dnl Check to see whether a particular set of modules exists. Similar to
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
dnl
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
dnl only at the first occurrence in configure.ac, so if the first place
dnl only at the first occurence in configure.ac, so if the first place
dnl it's called might be skipped (such as if it is within an "if", you
dnl have to call PKG_CHECK_EXISTS manually
AC_DEFUN([PKG_CHECK_EXISTS],
@ -213,7 +213,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no
AC_MSG_CHECKING([for $2])
AC_MSG_CHECKING([for $1])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
@ -223,17 +223,17 @@ and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
AC_MSG_RESULT([no])
AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
m4_default([$4], [AC_MSG_ERROR(
m4_default([$4], [AC_MSG_ERROR(
[Package requirements ($2) were not met:
$$1_PKG_ERRORS
@ -244,8 +244,8 @@ installed software in a non-standard prefix.
_PKG_TEXT])[]dnl
])
elif test $pkg_failed = untried; then
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
@ -255,10 +255,10 @@ _PKG_TEXT
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
])
else
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
AC_MSG_RESULT([yes])
$3
$3
fi[]dnl
])dnl PKG_CHECK_MODULES

View File

@ -1,9 +1,9 @@
#!/bin/sh
# py-compile - Compile a Python program
scriptversion=2023-03-30.00; # UTC
scriptversion=2011-06-08.12; # UTC
# Copyright (C) 2000-2023 Free Software Foundation, Inc.
# Copyright (C) 2000-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -16,7 +16,7 @@ scriptversion=2023-03-30.00; # UTC
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -27,7 +27,7 @@ scriptversion=2023-03-30.00; # UTC
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
if test -z "$PYTHON"; then
if [ -z "$PYTHON" ]; then
PYTHON=python
fi
@ -62,19 +62,13 @@ while test $# -ne 0; do
;;
-h|--help)
cat <<\EOF
Usage: py-compile [options] FILES...
Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..."
Byte compile some python scripts FILES. Use --destdir to specify any
leading directory path to the FILES that you don't want to include in the
byte compiled file. Specify --basedir for any additional path information you
do want to be shown in the byte compiled file.
Options:
--basedir DIR Prefix all FILES with DIR, and include in error messages.
--destdir DIR Prefix all FILES with DIR before compiling.
-v, --version Display version information.
-h, --help This help screen.
Example:
py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py
@ -100,143 +94,77 @@ EOF
shift
done
if test $# -eq 0; then
usage_error "no files given"
files=$*
if test -z "$files"; then
usage_error "no files given"
fi
# if basedir was given, then it should be prepended to filenames before
# byte compilation.
if test -z "$basedir"; then
pathtrans="path = file"
if [ -z "$basedir" ]; then
pathtrans="path = file"
else
pathtrans="path = os.path.join('$basedir', file)"
pathtrans="path = os.path.join('$basedir', file)"
fi
# if destdir was given, then it needs to be prepended to the filename to
# byte compile but not go into the compiled file.
if test -z "$destdir"; then
filetrans="filepath = path"
if [ -z "$destdir" ]; then
filetrans="filepath = path"
else
filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
fi
python_major=`$PYTHON -c 'import sys; print(sys.version_info[0])'`
if test -z "$python_major"; then
usage_error "could not determine $PYTHON major version"
fi
case $python_major in
[01])
usage_error "python version 0.x and 1.x not supported"
;;
esac
python_minor=`$PYTHON -c 'import sys; print(sys.version_info[1])'`
# NB: When adding support for newer versions, prefer copying & adding new cases
# rather than try to keep things merged with shell variables.
# First byte compile (no optimization) all the modules.
# This works for all currently known Python versions.
$PYTHON -c "
import sys, os, py_compile
import sys, os, py_compile, imp
try:
import importlib
except ImportError:
importlib = None
# importlib.util.cache_from_source was added in 3.4
if (
hasattr(importlib, 'util')
and hasattr(importlib.util, 'cache_from_source')
):
destpath = importlib.util.cache_from_source
else:
destpath = lambda filepath: filepath + 'c'
files = '''$files'''
sys.stdout.write('Byte-compiling python modules...\n')
for file in sys.argv[1:]:
for file in files.split():
$pathtrans
$filetrans
if (
not os.path.exists(filepath)
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
):
continue
sys.stdout.write(file + ' ')
if not os.path.exists(filepath) or not (len(filepath) >= 3
and filepath[-3:] == '.py'):
continue
sys.stdout.write(file)
sys.stdout.flush()
py_compile.compile(filepath, destpath(filepath), path)
sys.stdout.write('\n')" "$@" || exit $?
if hasattr(imp, 'get_tag'):
py_compile.compile(filepath, imp.cache_from_source(filepath), path)
else:
py_compile.compile(filepath, filepath + 'c', path)
sys.stdout.write('\n')" || exit $?
# Then byte compile w/optimization all the modules.
# this will fail for python < 1.5, but that doesn't matter ...
$PYTHON -O -c "
import sys, os, py_compile
import sys, os, py_compile, imp
try:
import importlib
except ImportError:
importlib = None
# importlib.util.cache_from_source was added in 3.4
if (
hasattr(importlib, 'util')
and hasattr(importlib.util, 'cache_from_source')
):
destpath = importlib.util.cache_from_source
else:
destpath = lambda filepath: filepath + 'o'
# pypy2 does not use .pyo optimization
if sys.version_info.major <= 2 and hasattr(sys, 'pypy_translation_info'):
# pypy does not use .pyo optimization
if hasattr(sys, 'pypy_translation_info'):
sys.exit(0)
files = '''$files'''
sys.stdout.write('Byte-compiling python modules (optimized versions) ...\n')
for file in sys.argv[1:]:
for file in files.split():
$pathtrans
$filetrans
if (
not os.path.exists(filepath)
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
):
continue
sys.stdout.write(file + ' ')
if not os.path.exists(filepath) or not (len(filepath) >= 3
and filepath[-3:] == '.py'):
continue
sys.stdout.write(file)
sys.stdout.flush()
py_compile.compile(filepath, destpath(filepath), path)
sys.stdout.write('\n')" "$@" 2>/dev/null || exit $?
# Then byte compile w/more optimization.
# Only do this for Python 3.5+, see https://bugs.gnu.org/38043 for background.
case $python_major.$python_minor in
2.*|3.[0-4])
;;
*)
$PYTHON -OO -c "
import sys, os, py_compile, importlib
sys.stdout.write('Byte-compiling python modules (more optimized versions)'
' ...\n')
for file in sys.argv[1:]:
$pathtrans
$filetrans
if (
not os.path.exists(filepath)
or not (len(filepath) >= 3 and filepath[-3:] == '.py')
):
continue
sys.stdout.write(file + ' ')
sys.stdout.flush()
py_compile.compile(filepath, importlib.util.cache_from_source(filepath), path)
sys.stdout.write('\n')" "$@" 2>/dev/null || exit $?
;;
esac
if hasattr(imp, 'get_tag'):
py_compile.compile(filepath, imp.cache_from_source(filepath, False), path)
else:
py_compile.compile(filepath, filepath + 'o', path)
sys.stdout.write('\n')" 2>/dev/null || :
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -31,10 +31,10 @@ CLEAN_TARGETS += $(BASE_DEPENDS) $(BASE_OBJECTS) \
$(BASE_TARGET)
$(BASE_TARGET): $(BASE_OBJECTS)
$(SHOW) " [AR] $@"
@echo " [AR] $@"
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(BASE_OBJECTS) > /dev/null
ifeq ("$(USE_TRACKING)","yes")
ifeq ("$(DEPENDS)","yes")
-include $(BASE_DEPENDS)
endif

View File

@ -41,7 +41,7 @@ struct dm_hash_table {
static unsigned _hash(const void *key, unsigned len)
{
/* Permutation of the Integers 0 through 255 */
static const unsigned char _nums[] = {
static unsigned char _nums[] = {
1, 14, 110, 25, 97, 174, 132, 119, 138, 170, 125, 118, 27, 233, 140, 51,
87, 197, 177, 107, 234, 169, 56, 68, 30, 7, 173, 73, 188, 40, 36, 65,
49, 213, 104, 190, 57, 211, 148, 223, 48, 115, 15, 2, 67, 186, 210, 28,

View File

@ -19,7 +19,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//----------------------------------------------------------------
@ -70,7 +69,7 @@ struct node48 {
};
struct node256 {
uint32_t nr_entries;
uint32_t nr_entries;
struct value values[256];
};
@ -100,7 +99,7 @@ struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
static inline void _dtr(struct radix_tree *rt, union radix_value v)
{
if (rt->dtr)
rt->dtr(rt->dtr_context, v);
rt->dtr(rt->dtr_context, v);
}
// Returns the number of values removed
@ -119,8 +118,8 @@ static unsigned _free_node(struct radix_tree *rt, struct value v)
break;
case VALUE:
_dtr(rt, v.value);
nr = 1;
_dtr(rt, v.value);
nr = 1;
break;
case VALUE_CHAIN:
@ -179,9 +178,9 @@ unsigned radix_tree_size(struct radix_tree *rt)
return rt->nr_entries;
}
static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv);
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv);
static bool _insert_unset(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert_unset(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
unsigned len = ke - kb;
@ -208,7 +207,7 @@ static bool _insert_unset(struct radix_tree *rt, struct value *v, const uint8_t
return true;
}
static bool _insert_value(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert_value(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
unsigned len = ke - kb;
@ -235,7 +234,7 @@ static bool _insert_value(struct radix_tree *rt, struct value *v, const uint8_t
return true;
}
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert_value_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct value_chain *vc = v->value.ptr;
return _insert(rt, &vc->child, kb, ke, rv);
@ -249,7 +248,7 @@ static unsigned min(unsigned lhs, unsigned rhs)
return rhs;
}
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct prefix_chain *pc = v->value.ptr;
@ -314,7 +313,7 @@ static bool _insert_prefix_chain(struct radix_tree *rt, struct value *v, const u
return true;
}
static bool _insert_node4(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert_node4(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct node4 *n4 = v->value.ptr;
if (n4->nr_entries == 4) {
@ -344,7 +343,7 @@ static bool _insert_node4(struct radix_tree *rt, struct value *v, const uint8_t
return true;
}
static bool _insert_node16(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert_node16(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct node16 *n16 = v->value.ptr;
@ -383,7 +382,7 @@ static bool _insert_node16(struct radix_tree *rt, struct value *v, const uint8_t
return true;
}
static bool _insert_node48(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert_node48(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct node48 *n48 = v->value.ptr;
if (n48->nr_entries == 48) {
@ -418,20 +417,20 @@ static bool _insert_node48(struct radix_tree *rt, struct value *v, const uint8_t
return true;
}
static bool _insert_node256(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert_node256(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
struct node256 *n256 = v->value.ptr;
bool r, was_unset = n256->values[*kb].type == UNSET;
r = _insert(rt, n256->values + *kb, kb + 1, ke, rv);
if (r && was_unset)
n256->nr_entries++;
n256->nr_entries++;
return r;
}
// FIXME: the tree should not be touched if insert fails (eg, OOM)
static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, const uint8_t *ke, union radix_value rv)
static bool _insert(struct radix_tree *rt, struct value *v, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
if (kb == ke) {
if (v->type == UNSET) {
@ -488,10 +487,10 @@ static bool _insert(struct radix_tree *rt, struct value *v, const uint8_t *kb, c
struct lookup_result {
struct value *v;
const uint8_t *kb;
uint8_t *kb;
};
static struct lookup_result _lookup_prefix(struct value *v, const uint8_t *kb, const uint8_t *ke)
static struct lookup_result _lookup_prefix(struct value *v, uint8_t *kb, uint8_t *ke)
{
unsigned i;
struct value_chain *vc;
@ -501,7 +500,7 @@ static struct lookup_result _lookup_prefix(struct value *v, const uint8_t *kb, c
struct node48 *n48;
struct node256 *n256;
if (kb == ke || !kb) /* extra check for !kb for coverity */
if (kb == ke)
return (struct lookup_result) {.v = v, .kb = kb};
switch (v->type) {
@ -556,10 +555,8 @@ static struct lookup_result _lookup_prefix(struct value *v, const uint8_t *kb, c
return (struct lookup_result) {.v = v, .kb = kb};
}
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value rv)
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value rv)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
return _insert(rt, lr.v, lr.kb, ke, rv);
}
@ -567,14 +564,14 @@ bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, un
// 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));
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);
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;
@ -583,20 +580,20 @@ static void _degrade_to_n4(struct node16 *n16, struct value *result)
static void _degrade_to_n16(struct node48 *n48, struct value *result)
{
unsigned i, count = 0;
struct node16 *n16 = zalloc(sizeof(*n16));
struct node16 *n16 = zalloc(sizeof(*n16));
assert(n16 != NULL);
n16->nr_entries = n48->nr_entries;
for (i = 0; i < 256; i++) {
if (n48->keys[i] < 48) {
n16->keys[count] = i;
n16->values[count] = n48->values[n48->keys[i]];
count++;
}
}
n16->nr_entries = n48->nr_entries;
for (i = 0; i < 256; i++) {
if (n48->keys[i] < 48) {
n16->keys[count] = i;
n16->values[count] = n48->values[n48->keys[i]];
count++;
}
}
free(n48);
free(n48);
result->type = NODE16;
result->value.ptr = n16;
@ -604,13 +601,13 @@ static void _degrade_to_n16(struct node48 *n48, struct value *result)
static void _degrade_to_n48(struct node256 *n256, struct value *result)
{
unsigned i, count = 0;
struct node48 *n48 = zalloc(sizeof(*n48));
unsigned i, count = 0;
struct node48 *n48 = zalloc(sizeof(*n48));
assert(n48 != NULL);
n48->nr_entries = n256->nr_entries;
for (i = 0; i < 256; i++) {
n48->nr_entries = n256->nr_entries;
for (i = 0; i < 256; i++) {
if (n256->values[i].type == UNSET)
n48->keys[i] = 48;
@ -619,9 +616,9 @@ static void _degrade_to_n48(struct node256 *n256, struct value *result)
n48->values[count] = n256->values[i];
count++;
}
}
}
free(n256);
free(n256);
result->type = NODE48;
result->value.ptr = n48;
@ -635,14 +632,14 @@ static void _erase_elt(void *array, size_t obj_size, unsigned count, unsigned id
return;
memmove(((uint8_t *) array) + (obj_size * idx),
((uint8_t *) array) + (obj_size * (idx + 1)),
obj_size * (count - idx - 1));
((uint8_t *) array) + (obj_size * (idx + 1)),
obj_size * (count - idx - 1));
// Zero the now unused last elt (set's v.type to UNSET)
memset(((uint8_t *) array) + (count - 1) * obj_size, 0, obj_size);
}
static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb, const uint8_t *ke)
static bool _remove(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke)
{
bool r;
unsigned i, j;
@ -654,27 +651,27 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
struct node256 *n256;
if (kb == ke) {
if (root->type == VALUE) {
root->type = UNSET;
_dtr(rt, root->value);
return true;
if (root->type == VALUE) {
root->type = UNSET;
_dtr(rt, root->value);
return true;
} else if (root->type == VALUE_CHAIN) {
} else if (root->type == VALUE_CHAIN) {
vc = root->value.ptr;
_dtr(rt, vc->value);
memcpy(root, &vc->child, sizeof(*root));
free(vc);
return true;
} else
} else
return false;
}
switch (root->type) {
case UNSET:
case VALUE:
// this is a value for a prefix of the key
return false;
// this is a value for a prefix of the key
return false;
case VALUE_CHAIN:
vc = root->value.ptr;
@ -689,11 +686,11 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
case PREFIX_CHAIN:
pc = root->value.ptr;
if (ke - kb < pc->len)
return false;
return false;
for (i = 0; i < pc->len; i++)
if (kb[i] != pc->prefix[i])
return false;
return false;
r = _remove(rt, &pc->child, kb + pc->len, ke);
if (r && pc->child.type == UNSET) {
@ -708,12 +705,12 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
if (n4->keys[i] == *kb) {
r = _remove(rt, n4->values + i, kb + 1, ke);
if (r && n4->values[i].type == UNSET) {
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
n4->nr_entries--;
n4->nr_entries--;
if (!n4->nr_entries) {
free(n4);
root->type = UNSET;
@ -725,19 +722,19 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
return false;
case NODE16:
n16 = root->value.ptr;
n16 = root->value.ptr;
for (i = 0; i < n16->nr_entries; i++) {
if (n16->keys[i] == *kb) {
r = _remove(rt, n16->values + i, kb + 1, ke);
if (r && n16->values[i].type == UNSET) {
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
n16->nr_entries--;
n16->nr_entries--;
if (n16->nr_entries <= 4) {
_degrade_to_n4(n16, root);
_degrade_to_n4(n16, root);
}
}
return r;
@ -749,18 +746,18 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
n48 = root->value.ptr;
i = n48->keys[*kb];
if (i < 48) {
r = _remove(rt, n48->values + i, kb + 1, ke);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
r = _remove(rt, n48->values + i, kb + 1, ke);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
_erase_elt(n48->values, sizeof(*n48->values), n48->nr_entries, i);
n48->nr_entries--;
if (n48->nr_entries <= 16)
_degrade_to_n16(n48, root);
}
return r;
_degrade_to_n16(n48, root);
}
return r;
}
return false;
@ -770,7 +767,7 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
if (r && n256->values[*kb].type == UNSET) {
n256->nr_entries--;
if (n256->nr_entries <= 48)
_degrade_to_n48(n256, root);
_degrade_to_n48(n256, root);
}
return r;
}
@ -778,14 +775,11 @@ static bool _remove(struct radix_tree *rt, struct value *root, const uint8_t *kb
return false;
}
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
bool radix_tree_remove(struct radix_tree *rt, uint8_t *key_begin, uint8_t *key_end)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
if (_remove(rt, &rt->root, kb, ke)) {
rt->nr_entries--;
return true;
if (_remove(rt, &rt->root, key_begin, key_end)) {
rt->nr_entries--;
return true;
}
return false;
@ -793,25 +787,25 @@ bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
//----------------------------------------------------------------
static bool _prefix_chain_matches(const struct lookup_result *lr, const uint8_t *ke)
static bool _prefix_chain_matches(struct lookup_result *lr, uint8_t *ke)
{
// It's possible the top node is a prefix chain, and
// the remaining key matches part of it.
if (lr->v->type == PREFIX_CHAIN) {
unsigned i, rlen = ke - lr->kb;
const struct prefix_chain *pc = lr->v->value.ptr;
if (rlen < pc->len) {
for (i = 0; i < rlen; i++)
if (pc->prefix[i] != lr->kb[i])
return false;
return true;
// It's possible the top node is a prefix chain, and
// the remaining key matches part of it.
if (lr->v->type == PREFIX_CHAIN) {
unsigned i, rlen = ke - lr->kb;
struct prefix_chain *pc = lr->v->value.ptr;
if (rlen < pc->len) {
for (i = 0; i < rlen; i++)
if (pc->prefix[i] != lr->kb[i])
return false;
return true;
}
}
}
return false;
return false;
}
static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uint8_t *kb, const uint8_t *ke, unsigned *count)
static bool _remove_subtree(struct radix_tree *rt, struct value *root, uint8_t *kb, uint8_t *ke, unsigned *count)
{
bool r;
unsigned i, j, len;
@ -832,7 +826,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uin
case UNSET:
case VALUE:
// No entries with the given prefix
return true;
return true;
case VALUE_CHAIN:
vc = root->value.ptr;
@ -849,7 +843,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uin
len = min(pc->len, ke - kb);
for (i = 0; i < len; i++)
if (kb[i] != pc->prefix[i])
return true;
return true;
r = _remove_subtree(rt, &pc->child, len < pc->len ? ke : (kb + pc->len), ke, count);
if (r && pc->child.type == UNSET) {
@ -864,12 +858,12 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uin
if (n4->keys[i] == *kb) {
r = _remove_subtree(rt, n4->values + i, kb + 1, ke, count);
if (r && n4->values[i].type == UNSET) {
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
if (i < n4->nr_entries) {
_erase_elt(n4->keys, sizeof(*n4->keys), n4->nr_entries, i);
_erase_elt(n4->values, sizeof(*n4->values), n4->nr_entries, i);
}
n4->nr_entries--;
n4->nr_entries--;
if (!n4->nr_entries) {
free(n4);
root->type = UNSET;
@ -881,19 +875,19 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uin
return true;
case NODE16:
n16 = root->value.ptr;
n16 = root->value.ptr;
for (i = 0; i < n16->nr_entries; i++) {
if (n16->keys[i] == *kb) {
r = _remove_subtree(rt, n16->values + i, kb + 1, ke, count);
if (r && n16->values[i].type == UNSET) {
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
if (i < n16->nr_entries) {
_erase_elt(n16->keys, sizeof(*n16->keys), n16->nr_entries, i);
_erase_elt(n16->values, sizeof(*n16->values), n16->nr_entries, i);
}
n16->nr_entries--;
n16->nr_entries--;
if (n16->nr_entries <= 4)
_degrade_to_n4(n16, root);
_degrade_to_n4(n16, root);
}
return r;
}
@ -904,18 +898,18 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uin
n48 = root->value.ptr;
i = n48->keys[*kb];
if (i < 48) {
r = _remove_subtree(rt, n48->values + i, kb + 1, ke, count);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
r = _remove_subtree(rt, n48->values + i, kb + 1, ke, count);
if (r && n48->values[i].type == UNSET) {
n48->keys[*kb] = 48;
for (j = 0; j < 256; j++)
if (n48->keys[j] < 48 && n48->keys[j] > i)
n48->keys[j]--;
_erase_elt(n48->values, sizeof(*n48->values), n48->nr_entries, i);
n48->nr_entries--;
if (n48->nr_entries <= 16)
_degrade_to_n16(n48, root);
}
return r;
_degrade_to_n16(n48, root);
}
return r;
}
return true;
@ -928,7 +922,7 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uin
if (r && n256->values[*kb].type == UNSET) {
n256->nr_entries--;
if (n256->nr_entries <= 48)
_degrade_to_n48(n256, root);
_degrade_to_n48(n256, root);
}
return r;
}
@ -937,13 +931,11 @@ static bool _remove_subtree(struct radix_tree *rt, struct value *root, const uin
return false;
}
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, uint8_t *kb, uint8_t *ke)
{
const uint8_t *kb = prefix;
const uint8_t *ke = kb + prefix_len;
unsigned count = 0;
unsigned count = 0;
if (_remove_subtree(rt, &rt->root, kb, ke, &count))
if (_remove_subtree(rt, &rt->root, kb, ke, &count))
rt->nr_entries -= count;
return count;
@ -951,11 +943,9 @@ unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *prefix, siz
//----------------------------------------------------------------
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value *result)
bool radix_tree_lookup(struct radix_tree *rt,
uint8_t *kb, uint8_t *ke, union radix_value *result)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct value_chain *vc;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke) {
@ -978,58 +968,58 @@ bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
}
// FIXME: build up the keys too
static bool _iterate(struct radix_tree_iterator *it, const struct value *v)
static bool _iterate(struct value *v, struct radix_tree_iterator *it)
{
unsigned i;
const struct value_chain *vc;
const struct prefix_chain *pc;
const struct node4 *n4;
const struct node16 *n16;
const struct node48 *n48;
const struct node256 *n256;
struct value_chain *vc;
struct prefix_chain *pc;
struct node4 *n4;
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
switch (v->type) {
case UNSET:
// can't happen
// can't happen
break;
case VALUE:
return it->visit(it, NULL, 0, v->value);
return it->visit(it, NULL, NULL, v->value);
case VALUE_CHAIN:
vc = v->value.ptr;
return it->visit(it, NULL, 0, vc->value) && _iterate(it, &vc->child);
return it->visit(it, NULL, NULL, vc->value) && _iterate(&vc->child, it);
case PREFIX_CHAIN:
pc = v->value.ptr;
return _iterate(it, &pc->child);
return _iterate(&pc->child, it);
case NODE4:
n4 = (const struct node4 *) v->value.ptr;
n4 = (struct node4 *) v->value.ptr;
for (i = 0; i < n4->nr_entries; i++)
if (!_iterate(it, n4->values + i))
return false;
return true;
if (!_iterate(n4->values + i, it))
return false;
return true;
case NODE16:
n16 = (const struct node16 *) v->value.ptr;
n16 = (struct node16 *) v->value.ptr;
for (i = 0; i < n16->nr_entries; i++)
if (!_iterate(it, n16->values + i))
return false;
if (!_iterate(n16->values + i, it))
return false;
return true;
case NODE48:
n48 = (const struct node48 *) v->value.ptr;
n48 = (struct node48 *) v->value.ptr;
for (i = 0; i < n48->nr_entries; i++)
if (!_iterate(it, n48->values + i))
return false;
if (!_iterate(n48->values + i, it))
return false;
return true;
case NODE256:
n256 = (const struct node256 *) v->value.ptr;
n256 = (struct node256 *) v->value.ptr;
for (i = 0; i < 256; i++)
if (n256->values[i].type != UNSET && !_iterate(it, n256->values + i))
return false;
if (n256->values[i].type != UNSET && !_iterate(n256->values + i, it))
return false;
return true;
}
@ -1037,14 +1027,12 @@ static bool _iterate(struct radix_tree_iterator *it, const struct value *v)
return false;
}
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
struct radix_tree_iterator *it)
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke || _prefix_chain_matches(&lr, ke))
(void) _iterate(it, lr.v);
(void) _iterate(lr.v, it);
}
//----------------------------------------------------------------
@ -1142,7 +1130,7 @@ static bool _check_nodes(struct value *v, unsigned *count)
if (ncount != n48->nr_entries) {
fprintf(stderr, "incorrect number of entries in n48, n48->nr_entries = %u, actual = %u\n",
n48->nr_entries, ncount);
n48->nr_entries, ncount);
return false;
}
@ -1178,7 +1166,7 @@ static bool _check_nodes(struct value *v, unsigned *count)
if (ncount != n256->nr_entries) {
fprintf(stderr, "incorrect number of entries in n256, n256->nr_entries = %u, actual = %u\n",
n256->nr_entries, ncount);
n256->nr_entries, ncount);
return false;
}
@ -1201,7 +1189,7 @@ bool radix_tree_is_well_formed(struct radix_tree *rt)
if (rt->nr_entries != count) {
fprintf(stderr, "incorrect entry count: rt->nr_entries = %u, actual = %u\n",
rt->nr_entries, count);
rt->nr_entries, count);
return false;
}
@ -1219,7 +1207,6 @@ static void _dump(FILE *out, struct value v, unsigned indent)
struct node16 *n16;
struct node48 *n48;
struct node256 *n256;
unsigned printable;
if (v.type == UNSET)
return;
@ -1244,22 +1231,9 @@ static void _dump(FILE *out, struct value v, unsigned indent)
case PREFIX_CHAIN:
pc = v.value.ptr;
fprintf(out, "<prefix(%u): ", pc->len);
printable = 1;
fprintf(out, "<prefix: ");
for (i = 0; i < pc->len; i++)
if (!isprint(pc->prefix[i])) {
printable = 0;
break;
}
if (printable)
fputc('"', out);
for (i = 0; i < pc->len; i++)
if (printable)
fprintf(out, "%c", pc->prefix[i]);
else
fprintf(out, "%02x.", (unsigned) *(pc->prefix + i));
if (printable)
fputc('"', out);
fprintf(out, "%x.", (unsigned) *(pc->prefix + i));
fprintf(out, ">\n");
_dump(out, pc->child, indent + 1);
break;
@ -1268,7 +1242,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
n4 = v.value.ptr;
fprintf(out, "<n4: ");
for (i = 0; i < n4->nr_entries; i++)
fprintf(out, "%02x ", (unsigned) n4->keys[i]);
fprintf(out, "%x ", (unsigned) n4->keys[i]);
fprintf(out, ">\n");
for (i = 0; i < n4->nr_entries; i++)
@ -1279,7 +1253,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
n16 = v.value.ptr;
fprintf(out, "<n16: ");
for (i = 0; i < n16->nr_entries; i++)
fprintf(out, "%02x ", (unsigned) n16->keys[i]);
fprintf(out, "%x ", (unsigned) n16->keys[i]);
fprintf(out, ">\n");
for (i = 0; i < n16->nr_entries; i++)
@ -1291,7 +1265,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
fprintf(out, "<n48: ");
for (i = 0; i < 256; i++)
if (n48->keys[i] < 48)
fprintf(out, "%02x ", i);
fprintf(out, "%x ", i);
fprintf(out, ">\n");
for (i = 0; i < n48->nr_entries; i++) {
@ -1305,7 +1279,7 @@ static void _dump(FILE *out, struct value v, unsigned indent)
fprintf(out, "<n256: ");
for (i = 0; i < 256; i++)
if (n256->values[i].type != UNSET)
fprintf(out, "%02x ", i);
fprintf(out, "%x ", i);
fprintf(out, ">\n");
for (i = 0; i < 256; i++)

View File

@ -1,5 +1,5 @@
// Copyright (C) 2018 Red Hat, Inc. All rights reserved.
//
//
// This file is part of LVM2.
//
// This copyrighted material is made available to anyone wishing to use,
@ -18,7 +18,6 @@
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
//----------------------------------------------------------------
// This implementation is based around nested binary trees. Very
@ -38,12 +37,12 @@ struct node {
struct radix_tree {
radix_value_dtr dtr;
void *dtr_context;
unsigned nr_entries;
struct node *root;
};
struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context)
struct radix_tree *
radix_tree_create(radix_value_dtr dtr, void *dtr_context)
{
struct radix_tree *rt = zalloc(sizeof(*rt));
@ -106,7 +105,7 @@ unsigned radix_tree_size(struct radix_tree *rt)
return _count(rt->root);
}
static struct node **_lookup(struct node **pn, const uint8_t *kb, const uint8_t *ke)
static struct node **_lookup(struct node **pn, uint8_t *kb, uint8_t *ke)
{
struct node *n = *pn;
@ -123,7 +122,7 @@ static struct node **_lookup(struct node **pn, const uint8_t *kb, const uint8_t
return _lookup(&n->center, kb + 1, ke);
}
static bool _insert(struct node **pn, const uint8_t *kb, const uint8_t *ke, union radix_value v)
static bool _insert(struct node **pn, uint8_t *kb, uint8_t *ke, union radix_value v)
{
struct node *n = *pn;
@ -152,51 +151,39 @@ static bool _insert(struct node **pn, const uint8_t *kb, const uint8_t *ke, unio
return _insert(&n->center, kb + 1, ke, v);
}
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value v)
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
if (!_insert(&rt->root, kb, ke, v))
return false;
rt->nr_entries++;
return true;
return _insert(&rt->root, kb, ke, v);
}
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen)
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct node **pn = _lookup(&rt->root, kb, ke);
struct node *n = *pn;
if (!n || !n->has_value)
return false;
rt->nr_entries--;
else {
if (rt->dtr)
rt->dtr(rt->dtr_context, n->value);
if (rt->dtr)
rt->dtr(rt->dtr_context, n->value);
if (n->left || n->center || n->right) {
n->has_value = false;
return true;
if (n->left || n->center || n->right) {
n->has_value = false;
return true;
} else {
// FIXME: delete parent if this was the last entry
free(n);
*pn = NULL;
}
return true;
}
// FIXME: delete parent if this was the last entry
free(n);
*pn = NULL;
return true;
}
unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *key, size_t keylen)
unsigned radix_tree_remove_prefix(struct radix_tree *rt, uint8_t *kb, uint8_t *ke)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct node **pn;
unsigned count;
@ -210,20 +197,17 @@ unsigned radix_tree_remove_prefix(struct radix_tree *rt, const void *key, size_t
return count;
}
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value *result)
bool
radix_tree_lookup(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value *result)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
struct node **pn = _lookup(&rt->root, kb, ke);
struct node *n = *pn;
if (n && n->has_value) {
*result = n->value;
return true;
}
return false;
} else
return false;
}
static void _iterate(struct node *n, struct radix_tree_iterator *it)
@ -235,18 +219,15 @@ static void _iterate(struct node *n, struct radix_tree_iterator *it)
if (n->has_value)
// FIXME: fill out the key
it->visit(it, NULL, 0, n->value);
it->visit(it, NULL, NULL, n->value);
_iterate(n->center, it);
_iterate(n->right, it);
}
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it)
{
const uint8_t *kb = key;
const uint8_t *ke = kb + keylen;
if (kb == ke)
_iterate(rt->root, it);
@ -256,7 +237,7 @@ void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
if (n) {
if (n->has_value)
it->visit(it, NULL, 0, n->value);
it->visit(it, NULL, NULL, n->value);
_iterate(n->center, it);
}
}
@ -267,32 +248,8 @@ bool radix_tree_is_well_formed(struct radix_tree *rt)
return true;
}
static void _dump(FILE *out, struct node *n, unsigned indent)
{
unsigned i;
if (!n)
return;
_dump(out, n->left, indent + 1);
for (i = 0; i < 2 * indent; i++)
fprintf(out, " ");
if (n->has_value) {
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);
}
_dump(out, n->center, indent + 1);
_dump(out, n->right, indent + 1);
}
void radix_tree_dump(struct radix_tree *rt, FILE *out)
{
_dump(out, rt->root, 0);
}
//----------------------------------------------------------------

View File

@ -19,45 +19,3 @@
#endif
//----------------------------------------------------------------
struct visitor {
struct radix_tree_iterator it;
unsigned pos, nr_entries;
union radix_value *values;
};
static bool _visitor(struct radix_tree_iterator *it,
const void *key, size_t keylen,
union radix_value v)
{
struct visitor *vt = container_of(it, struct visitor, it);
if (vt->pos >= vt->nr_entries)
return false;
vt->values[vt->pos++] = v;
return true;
}
bool radix_tree_values(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value **values, unsigned *nr_values)
{
struct visitor vt = {
.it.visit = _visitor,
.nr_entries = rt->nr_entries,
.values = calloc(rt->nr_entries + 1, sizeof(union radix_value)),
};
if (vt.values) {
// build set of all values in current radix tree
radix_tree_iterate(rt, key, keylen, &vt.it);
*nr_values = vt.pos;
*values = vt.values;
return true;
}
return false;
}
//----------------------------------------------------------------

View File

@ -33,51 +33,32 @@ struct radix_tree *radix_tree_create(radix_value_dtr dtr, void *dtr_context);
void radix_tree_destroy(struct radix_tree *rt);
unsigned radix_tree_size(struct radix_tree *rt);
bool radix_tree_insert(struct radix_tree *rt, const void *key, size_t keylen, union radix_value v);
bool radix_tree_remove(struct radix_tree *rt, const void *key, size_t keylen);
bool radix_tree_insert(struct radix_tree *rt, uint8_t *kb, uint8_t *ke, union radix_value v);
bool radix_tree_remove(struct radix_tree *rt, uint8_t *kb, uint8_t *ke);
// Returns the number of values removed
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, uint8_t *prefix_b, uint8_t *prefix_e);
bool radix_tree_lookup(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value *result);
bool radix_tree_lookup(struct radix_tree *rt,
uint8_t *kb, uint8_t *ke, union radix_value *result);
// The radix tree stores entries in lexicographical order. Which means
// we can iterate entries, in order. Or iterate entries with a particular
// prefix.
struct radix_tree_iterator {
// Returns false if the iteration should end.
// Returns false if the iteration should end.
bool (*visit)(struct radix_tree_iterator *it,
const void *key, size_t keylen, union radix_value v);
uint8_t *kb, uint8_t *ke, union radix_value v);
};
void radix_tree_iterate(struct radix_tree *rt, const void *key, size_t keylen,
struct radix_tree_iterator *it);
// Alternative traversing radix_tree.
// Builds whole set all radix_tree nr_values values.
// After use, free(values).
bool radix_tree_values(struct radix_tree *rt, const void *key, size_t keylen,
union radix_value **values, unsigned *nr_values);
void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
struct radix_tree_iterator *it);
// Checks that some constraints on the shape of the tree are
// being held. For debug only.
bool radix_tree_is_well_formed(struct radix_tree *rt);
void radix_tree_dump(struct radix_tree *rt, FILE *out);
// Shortcut for ptr value return
// Note: if value would be NULL, it's same result for not/found case.
static inline void *radix_tree_lookup_ptr(struct radix_tree *rt, const void *key, size_t keylen)
{
union radix_value v;
return radix_tree_lookup(rt, key, keylen, &v) ? v.ptr : NULL;
}
static inline bool radix_tree_insert_ptr(struct radix_tree *rt, const void *key, size_t keylen, void *ptr)
{
union radix_value v = { .ptr = ptr };
return radix_tree_insert(rt, key, keylen, v);
}
//----------------------------------------------------------------
#endif

View File

@ -49,7 +49,7 @@ install_localconf: $(CONFLOCAL)
fi
install_profiles: $(PROFILES)
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(profiledir)
$(Q) $(INSTALL_DATA) $(PROFILES) $(profiledir)/

View File

@ -135,16 +135,6 @@ devices {
# This configuration option has an automatic default value.
# devicesfile = "system.devices"
# Configuration option devices/devicesfile_backup_limit.
# The max number of backup files to keep in /etc/lvm/devices/backup.
# LVM creates a backup of the devices file each time a new
# version is created, or each time a modification is detected.
# When the max number of backups is reached, the oldest are
# removed to remain at the limit. Set to 0 to disable backups.
# Only the system devices file is backed up.
# This configuration option has an automatic default value.
# devicesfile_backup_limit = 50
# Configuration option devices/search_for_devnames.
# Look outside of the devices file for missing devname entries.
# A devname entry is used for a device that does not have a stable
@ -159,27 +149,7 @@ devices {
# at other devices, but only those that are likely to have the PV.
# If "all", lvm will look at all devices on the system.
# This configuration option has an automatic default value.
# search_for_devnames = "all"
# Configuration option devices/device_ids_refresh.
# Find PVs on new devices and update the device IDs in the devices file.
# If PVs are restored or moved to a new system with new devices, but
# an old system.devices remains with old device IDs, then search for
# the PVIDs on new devices and update the device IDs in system.devices.
# The original device IDs must also not be found on the new system.
# See device_ids_refresh_check for conditions that trigger the refresh.
# This configuration option has an automatic default value.
# device_ids_refresh = 1
# Configuration option devices/device_ids_refresh_checks.
# Conditions that trigger device_ids_refresh to locate PVIDs on new devices.
# product_uuid: refresh if /sys/devices/virtual/dmi/id/product_uuid does not
# match the value saved in system.devices.
# hostname: refresh if hostname does not match the value saved in system.devices.
# (hostname is used if product_uuid is not available.)
# Remove values from this list to prevent lvm from using them.
# This configuration option has an automatic default value.
# device_ids_refresh_checks = [ "product_uuid", "hostname" ]
# search_for_devnames = "auto"
# Configuration option devices/filter.
# Limit the block devices that are used by LVM commands.
@ -241,12 +211,17 @@ devices {
# sysfs_scan = 1
# Configuration option devices/scan_lvs.
# Allow LVM LVs to be used as PVs. When enabled, LVM commands will
# scan active LVs to look for other PVs. Caution is required to
# 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.)
# Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.
# When 1, LVM will detect PVs layered on LVs, and caution must be
# taken to avoid a host accessing a layered VG that may not belong
# to it, e.g. from a guest image. This generally requires excluding
# the LVs with device filters. Also, when this setting is enabled,
# every LVM command will scan every active LV on the system (unless
# filtered), which can cause performance problems on systems with
# many active LVs. When this setting is 0, LVM will not detect or
# use PVs that exist on LVs, and will not allow a PV to be created on
# an LV. The LVs are ignored using a built in device filter that
# identifies and excludes LVs.
# This configuration option has an automatic default value.
# scan_lvs = 0
@ -675,6 +650,11 @@ allocation {
# This configuration option has an automatic default value.
# vdo_block_map_period = 16380
# Configuration option allocation/vdo_check_point_frequency.
# The default check point frequency for VDO volume.
# This configuration option has an automatic default value.
# vdo_check_point_frequency = 0
# Configuration option allocation/vdo_use_sparse_index.
# Enables sparse indexing for VDO volume.
# This configuration option has an automatic default value.
@ -1032,7 +1012,7 @@ global {
# Location of proc filesystem.
# This configuration option is advanced.
# This configuration option has an automatic default value.
# proc = "@DEFAULT_PROC_DIR@"
# proc = "/proc"
# Configuration option global/etc.
# Location of /etc system configuration directory.
@ -1176,7 +1156,7 @@ global {
# services (via the lvm2-activation-generator), but the autoactivation
# services and generator have been removed.
# This configuration option has an automatic default value.
# event_activation = @DEFAULT_EVENT_ACTIVATION@
# event_activation = 1
# Configuration option global/use_aio.
# Use async I/O when reading and writing devices.
@ -1221,7 +1201,7 @@ global {
# Configuration option global/thin_check_executable.
# The full path to the thin_check command.
# LVM uses this command to check that a thin pool metadata device is in a
# LVM uses this command to check that a thin metadata device is in a
# usable state. When a thin pool is activated and after it is
# deactivated, this command is run. Activation will only proceed if
# the command has an exit status of 0. Set to "" to skip this check.
@ -1245,14 +1225,6 @@ global {
# This configuration option has an automatic default value.
# thin_repair_executable = "@THIN_REPAIR_CMD@"
# Configuration option global/thin_restore_executable.
# The full path to the thin_restore command.
# LVM uses this command to restore generated data for a thin pool metadata device.
# Also see thin_restore_options.
# (See package device-mapper-persistent-data or thin-provisioning-tools)
# This configuration option has an automatic default value.
# thin_restore_executable = "@THIN_RESTORE_CMD@"
# Configuration option global/thin_check_options.
# List of options passed to the thin_check command.
# With thin_check version 2.1 or newer you can add the option
@ -1267,11 +1239,6 @@ global {
# This configuration option has an automatic default value.
# thin_repair_options = [ "" ]
# Configuration option global/thin_restore_options.
# List of options passed to the thin_restore command.
# This configuration option has an automatic default value.
# thin_restore_options = [ "" ]
# Configuration option global/thin_disabled_features.
# Features to not use in the thin driver.
# This can be helpful for testing, or to avoid using a feature that is
@ -1320,14 +1287,6 @@ global {
# This configuration option has an automatic default value.
# cache_repair_executable = "@CACHE_REPAIR_CMD@"
# Configuration option global/cache_restore_executable.
# The full path to the cache_restore command.
# LVM uses this command to restore generated data for a cache metadata device.
# Also see cache_restore_options.
# (See package device-mapper-persistent-data or thin-provisioning-tools)
# This configuration option has an automatic default value.
# cache_restore_executable = "@CACHE_RESTORE_CMD@"
# Configuration option global/cache_check_options.
# List of options passed to the cache_check command.
# With cache_check version 5.0 or newer you should include the option
@ -1340,11 +1299,6 @@ global {
# This configuration option has an automatic default value.
# cache_repair_options = [ "" ]
# Configuration option global/cache_restore_options.
# List of options passed to the cache_restore command.
# This configuration option has an automatic default value.
# cache_restore_options = [ "" ]
# Configuration option global/vdo_format_executable.
# The full path to the vdoformat command.
# LVM uses this command to initial data volume for VDO type logical volume
@ -1359,10 +1313,10 @@ global {
# Configuration option global/vdo_disabled_features.
# Features to not use in the vdo driver.
# This can be helpful for testing, or to avoid using a feature that is
# causing problems. Features include: online_rename, version4
# causing problems. Features include: online_rename
#
# Example
# vdo_disabled_features = [ "online_rename", "version4" ]
# vdo_disabled_features = [ "online_rename" ]
#
# This configuration option does not have a default value defined.
@ -1392,9 +1346,8 @@ global {
# Use an LVM-specific derivation of the local machine-id as the
# system ID. See 'man machine-id'.
# machineid
# Use the contents of the machine-id file to set the system ID.
# (appmachineid is recommended to avoid exposing the confidential
# machine-id.)
# Use the contents of the machine-id file to set the system ID
# (appmachineid is recommended.)
# file
# Use the contents of another file (system_id_file) to set the
# system ID.
@ -1837,7 +1790,7 @@ activation {
# Configuration option activation/polling_interval.
# Check pvmove or lvconvert progress at this interval (seconds).
# When pvmove or lvconvert must wait for the kernel to finish
# synchronizing or merging data, they check and report progress at
# synchronising or merging data, they check and report progress at
# intervals of this number of seconds. If this is set to 0 and there
# is only one thing to wait for, there are no progress reports, but
# the process is awoken immediately once the operation is complete.
@ -1982,7 +1935,8 @@ activation {
# Configuration section report.
# LVM report command output formatting.
report {
# This configuration section has an automatic default value.
# report {
# Configuration option report/output_format.
# Format of LVM command's report output.
@ -2042,11 +1996,7 @@ report {
# buffered = 1
# Configuration option report/headings.
# Format of LVM command's report output headings.
# Accepted values:
# 0 no headings,
# 1 headings with column abbreviations,
# 2 headings with full column names.
# Show headings for columns on report.
# This configuration option has an automatic default value.
# headings = 1
@ -2396,7 +2346,7 @@ report {
# This is displayed when the device for a PV is not known.
# This configuration option has an automatic default value.
# two_word_unknown_device = 0
}
# }
# Configuration section dmeventd.
# Settings for the LVM event daemon.

View File

@ -8,6 +8,7 @@ allocation {
vdo_minimum_io_size=4096
vdo_block_map_cache_size_mb=128
vdo_block_map_period=16380
vdo_check_point_frequency=0
vdo_use_sparse_index=0
vdo_index_memory_size_mb=256
vdo_slab_size_mb=2048

6196
configure vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -32,12 +32,12 @@ CFLAGS += $(CPG_CFLAGS) $(EXTRA_EXEC_CFLAGS)
LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
cmirrord: $(OBJECTS)
$(SHOW) " [CC] $@"
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
install_cluster: $(TARGETS)
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(usrsbindir)/$(<F)
install: install_cluster

View File

@ -43,14 +43,14 @@ static void usage (FILE *dest)
int main(int argc, char *argv[])
{
int foreground_mode = 0;
static const struct option _long_options[] = {
struct option longopts[] = {
{ "foreground", no_argument, NULL, 'f' },
{ "help" , no_argument, NULL, 'h' },
{ 0, 0, 0, 0 }
};
int opt;
while ((opt = getopt_long (argc, argv, "fh", _long_options, NULL)) != -1) {
while ((opt = getopt_long (argc, argv, "fh", longopts, NULL)) != -1) {
switch (opt) {
case 'f':
foreground_mode = 1;

View File

@ -1091,7 +1091,6 @@ static void cpg_message_callback(cpg_handle_t handle, const struct cpg_name *gna
(rq->u_rq.request_type != DM_ULOG_RESUME) &&
(rq->u_rq.request_type != DM_ULOG_CLEAR_REGION) &&
(rq->u_rq.request_type != DM_ULOG_CHECKPOINT_READY)) {
/* coverity[suspicious_sizeof] allocation is using varargs data @end */
tmp_rq = malloc(DM_ULOG_REQUEST_SIZE);
if (!tmp_rq) {
/*
@ -1341,7 +1340,6 @@ static void cpg_join_callback(struct clog_cpg *match,
goto out;
}
/* coverity[suspicious_sizeof] allocation is using varargs data @end */
rq = malloc(DM_ULOG_REQUEST_SIZE);
if (!rq) {
LOG_ERROR("cpg_config_callback: "
@ -1634,7 +1632,7 @@ int create_cluster_cpg(char *uuid, uint64_t luid)
size = ((strlen(uuid) + 1) > CPG_MAX_NAME_LENGTH) ?
CPG_MAX_NAME_LENGTH : (strlen(uuid) + 1);
dm_strncpy(new->name.value, uuid, size);
(void) dm_strncpy(new->name.value, uuid, size);
new->name.length = (uint32_t)size;
new->luid = luid;

View File

@ -67,7 +67,7 @@ struct log_c {
uint32_t recoverer;
uint64_t recovering_region; /* -1 means not recovering */
uint64_t skip_bit_warning; /* used to warn if region skipped */
unsigned sync_search;
int sync_search;
int resume_override;
@ -220,7 +220,7 @@ static int rw_log(struct log_c *lc, int do_write)
if (r < 0)
LOG_ERROR("[%s] rw_log: read failure: %s",
SHORT_UUID(lc->uuid), strerror(errno));
if ((unsigned) r != lc->disk_size)
if (r != lc->disk_size)
return -EIO; /* Failed disk read */
return 0;
}
@ -292,13 +292,13 @@ static int write_log(struct log_c *lc)
}
/* FIXME Rewrite this function taking advantage of the udev changes (where in use) to improve its efficiency! */
static int find_disk_path(char *major_minor_str, char *path_rtn, size_t sz, int *unlink_path __attribute__((unused)))
static int find_disk_path(char *major_minor_str, char *path_rtn, int *unlink_path __attribute__((unused)))
{
int r;
DIR *dp;
struct dirent *dep;
struct stat statbuf;
unsigned major, minor;
int major, minor;
if (!strstr(major_minor_str, ":")) {
r = stat(major_minor_str, &statbuf);
@ -306,7 +306,7 @@ static int find_disk_path(char *major_minor_str, char *path_rtn, size_t sz, int
return -errno;
if (!S_ISBLK(statbuf.st_mode))
return -EINVAL;
dm_strncpy(path_rtn, major_minor_str, sz);
sprintf(path_rtn, "%s", major_minor_str);
return 0;
}
@ -329,7 +329,7 @@ static int find_disk_path(char *major_minor_str, char *path_rtn, size_t sz, int
* wanted.
*/
snprintf(path_rtn, sz, "/dev/mapper/%s", dep->d_name);
sprintf(path_rtn, "/dev/mapper/%s", dep->d_name);
if (stat(path_rtn, &statbuf) < 0) {
LOG_DBG("Unable to stat %s", path_rtn);
continue;
@ -394,7 +394,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
goto fail;
}
r = find_disk_path(argv[0], disk_path, sizeof(disk_path), &unlink_path);
r = find_disk_path(argv[0], disk_path, &unlink_path);
if (r) {
LOG_ERROR("Unable to find path to device %s", argv[0]);
goto fail;
@ -452,7 +452,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
lc->skip_bit_warning = region_count;
lc->disk_fd = -1;
lc->log_dev_failed = 0;
if (!_dm_strncpy(lc->uuid, uuid, DM_UUID_LEN)) {
if (!dm_strncpy(lc->uuid, uuid, DM_UUID_LEN)) {
LOG_ERROR("Cannot use too long UUID %s.", uuid);
r = -EINVAL;
goto fail;

View File

@ -13,7 +13,6 @@
#define _LVM_CLOG_FUNCTIONS_H
#include "libdm/libdevmapper.h"
#include "libdm/dm-tools/util.h"
#include "libdm/misc/dm-log-userspace.h"
#include "cluster.h"

View File

@ -266,7 +266,7 @@ static int do_local_work(void *data __attribute__((unused)))
RQ_TYPE(u_rq->request_type));
break;
}
/* ELSE */ /* fall through */
/* ELSE, fall through */
case DM_ULOG_IS_CLEAN:
case DM_ULOG_FLUSH:
case DM_ULOG_MARK_REGION:

View File

@ -11,7 +11,7 @@
*/
#include "logging.h"
const char * const __rq_types_off_by_one[] = {
const char *__rq_types_off_by_one[] = {
"DM_ULOG_CTR",
"DM_ULOG_DTR",
"DM_ULOG_PRESUSPEND",

View File

@ -20,7 +20,7 @@
/* SHORT_UUID - print last 8 chars of a string */
#define SHORT_UUID(x) (strlen(x) > 8) ? ((x) + (strlen(x) - 8)) : (x)
extern const char * const __rq_types_off_by_one[];
extern const char *__rq_types_off_by_one[];
#define RQ_TYPE(x) __rq_types_off_by_one[(x) - 1]
extern int log_tabbing;

View File

@ -70,13 +70,13 @@ plugins.device-mapper: $(LIB_SHARED)
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
dmeventd: $(LIB_SHARED) dmeventd.o
$(SHOW) " [CC] $@"
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS)
dmeventd.static: $(LIB_STATIC) dmeventd.o
$(SHOW) " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(STATIC_LDFLAGS) -static dmeventd.o \
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
ifeq ("@PKGCONFIG@", "yes")
@ -84,27 +84,27 @@ ifeq ("@PKGCONFIG@", "yes")
endif
install_include: $(srcdir)/libdevmapper-event.h
$(SHOW) " [INSTALL] $(<F)"
@echo " [INSTALL] $(<F)"
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
install_pkgconfig: libdevmapper-event.pc
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(pkgconfigdir)/devmapper-event.pc
install_lib_dynamic: install_lib_shared
install_lib_static: $(LIB_STATIC)
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(usrlibdir)/$(<F)
install_lib: $(INSTALL_LIB_TARGETS)
install_dmeventd_dynamic: dmeventd
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_dmeventd_static: dmeventd.static
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(staticdir)/$(<F)
install_dmeventd: $(INSTALL_DMEVENTD_TARGETS)

View File

@ -23,12 +23,12 @@
#include "libdm/misc/dm-logging.h"
#include "base/memory/zalloc.h"
#include "libdaemon/server/daemon-stray.h"
#include <dlfcn.h>
#include <pthread.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>
#include <arpa/inet.h> /* for htonl, ntohl */
@ -92,10 +92,12 @@ static const size_t THREAD_STACK_SIZE = 300 * 1024;
/* Default idle exit timeout 1 hour (in seconds) */
static const time_t DMEVENTD_IDLE_EXIT_TIMEOUT = 60 * 60;
static int _debug_level = 0;
static int _use_syslog = 1;
static int _systemd_activation = 0;
static int _foreground = 0;
static int _restart = 0;
static time_t _idle_since = 0;
static const char *_exit_on = DEFAULT_DMEVENTD_EXIT_ON_PATH;
static char **_initial_registrations = 0;
/* FIXME Make configurable at runtime */
@ -200,9 +202,9 @@ struct message_data {
char *dso_name; /* Name of DSO. */
char *device_uuid; /* Mapped device path. */
char *events_str; /* Events string as fetched from message. */
unsigned events_field; /* Events bitfield. */
uint32_t timeout_secs;
enum dm_event_mask events_field; /* Events bitfield. */
char *timeout_str;
uint32_t timeout_secs;
struct dm_event_daemon_message *msg; /* Pointer to message buffer. */
};
@ -721,18 +723,12 @@ static int _get_status(struct message_data *message_data)
static int _get_parameters(struct message_data *message_data) {
struct dm_event_daemon_message *msg = message_data->msg;
int size;
char idle_buf[32] = "";
if (_idle_since)
(void)dm_snprintf(idle_buf, sizeof(idle_buf), " idle=%lu", (long unsigned) (time(NULL) - _idle_since));
free(msg->data);
if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s exit_on=\"%s\"%s",
if ((size = dm_asprintf(&msg->data, "%s pid=%d daemon=%s exec_method=%s",
message_data->id, getpid(),
_foreground ? "no" : "yes",
_systemd_activation ? "systemd" : "direct",
_exit_on,
idle_buf)) < 0) {
_systemd_activation ? "systemd" : "direct")) < 0) {
stack;
return -ENOMEM;
}
@ -991,7 +987,6 @@ static void _monitor_unregister(void *arg)
DEBUGLOG("Unregistering monitor for %s.", thread->device.name);
_unregister_for_timeout(thread);
/* coverity[missing_lock] no missing lock here */
if ((thread->status != DM_THREAD_REGISTERING) &&
!_do_unregister_device(thread))
log_error("%s: %s unregister failed.", __func__,
@ -1002,8 +997,6 @@ static void _monitor_unregister(void *arg)
_lock_mutex();
thread->status = DM_THREAD_DONE; /* Last access to thread memory! */
_unlock_mutex();
if (_exit_now) /* Exit is already in-progress, wake-up sleeping select() */
kill(getpid(), SIGINT);
}
/* Device monitoring thread. */
@ -1050,9 +1043,9 @@ static void *_monitor_thread(void *arg)
_unlock_mutex();
_do_process_event(thread);
thread->current_events = 0; /* Current events processed */
_lock_mutex();
thread->current_events = 0; /* Current events processed */
thread->processing = 0;
/*
@ -1168,36 +1161,6 @@ static int _unregister_for_event(struct message_data *message_data)
return ret;
}
static void _unregister_all_threads(void)
{
struct thread_status *thread, *tmp;
_lock_mutex();
dm_list_iterate_items_safe(thread, tmp, &_thread_registry)
_update_events(thread, 0);
_unlock_mutex();
}
static void _wait_for_new_pid(void)
{
unsigned long st_ino = 0;
struct stat st;
int i;
for (i = 0; i < 400000; ++i) {
if (lstat(DMEVENTD_PIDFILE, &st) == 0) {
if (!st_ino)
st_ino = st.st_ino;
else if (st_ino != st.st_ino)
break; /* different pidfile */
} else if (errno == ENOENT)
break; /* pidfile is removed */
usleep(100);
}
}
/*
* Register for an event.
*
@ -1441,8 +1404,7 @@ static int _open_fifo(const char *path)
} else if (!S_ISFIFO(st.st_mode) || st.st_uid ||
(st.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
log_warn("WARNING: %s has wrong attributes: Replacing.", path);
/* coverity[toctou] don't care, path is going to be recreated */
if (unlink(path) && (errno != ENOENT)) {
if (unlink(path)) {
log_sys_error("unlink", path);
return -1;
}
@ -1450,7 +1412,6 @@ static int _open_fifo(const char *path)
/* Create fifo. */
(void) dm_prepare_selinux_context(path, S_IFIFO);
/* coverity[toctou] revalidating things again */
if ((mkfifo(path, 0600) == -1) && errno != EEXIST) {
log_sys_error("mkfifo", path);
(void) dm_prepare_selinux_context(NULL, 0);
@ -1679,7 +1640,7 @@ static int _do_process_request(struct dm_event_daemon_message *msg)
} else
ret = _handle_request(msg, &message_data);
msg->cmd = (uint32_t)ret;
msg->cmd = ret;
if (!msg->data)
msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
@ -1716,9 +1677,9 @@ static void _process_request(struct dm_event_fifos *fifos)
free(msg.data);
if (cmd == DM_EVENT_CMD_DIE) {
_unregister_all_threads();
_exit_now = DM_SCHEDULED_EXIT;
log_info("dmeventd exiting for restart.");
if (unlink(DMEVENTD_PIDFILE))
log_sys_error("unlink", DMEVENTD_PIDFILE);
_exit(0);
}
}
@ -1765,7 +1726,7 @@ static void _cleanup_unused_threads(void)
DEBUGLOG("Destroying Thr %x.", (int)thread->thread);
if (pthread_join(thread->thread, NULL))
log_sys_debug("pthread_join", "");
log_sys_error("pthread_join", "");
_free_thread_status(thread);
_lock_mutex();
@ -1796,7 +1757,7 @@ static void _init_thread_signals(void)
sigdelset(&my_sigset, SIGQUIT);
if (pthread_sigmask(SIG_BLOCK, &my_sigset, NULL))
log_sys_debug("pthread_sigmask", "SIG_BLOCK");
log_sys_error("pthread_sigmask", "SIG_BLOCK");
}
/*
@ -1808,8 +1769,7 @@ static void _init_thread_signals(void)
*/
static void _exit_handler(int sig __attribute__((unused)))
{
if (!_exit_now)
_exit_now = DM_SIGNALED_EXIT;
_exit_now = DM_SIGNALED_EXIT;
}
#ifdef __linux__
@ -1825,7 +1785,7 @@ static int _set_oom_adj(const char *oom_adj_path, int val)
fprintf(fp, "%i", val);
if (dm_fclose(fp))
log_sys_debug("fclose", oom_adj_path);
log_sys_error("fclose", oom_adj_path);
return 1;
}
@ -1839,11 +1799,11 @@ static int _protect_against_oom_killer(void)
if (stat(OOM_ADJ_FILE, &st) == -1) {
if (errno != ENOENT)
log_sys_debug("stat", OOM_ADJ_FILE);
log_sys_error("stat", OOM_ADJ_FILE);
/* Try old oom_adj interface as a fallback */
if (stat(OOM_ADJ_FILE_OLD, &st) == -1) {
log_sys_debug("stat", OOM_ADJ_FILE_OLD);
log_sys_error("stat", OOM_ADJ_FILE_OLD);
return 1;
}
@ -1931,30 +1891,26 @@ out:
static void _remove_files_on_exit(void)
{
if (unlink(DMEVENTD_PIDFILE) && (errno != ENOENT))
log_sys_debug("unlink", DMEVENTD_PIDFILE);
if (unlink(DMEVENTD_PIDFILE))
log_sys_error("unlink", DMEVENTD_PIDFILE);
if (!_systemd_activation) {
if (unlink(DM_EVENT_FIFO_CLIENT) && (errno != ENOENT))
log_sys_debug("unlink", DM_EVENT_FIFO_CLIENT);
if (unlink(DM_EVENT_FIFO_CLIENT))
log_sys_error("unlink", DM_EVENT_FIFO_CLIENT);
if (unlink(DM_EVENT_FIFO_SERVER) && (errno != ENOENT))
log_sys_debug("unlink", DM_EVENT_FIFO_SERVER);
if (unlink(DM_EVENT_FIFO_SERVER))
log_sys_error("unlink", DM_EVENT_FIFO_SERVER);
}
}
static void _daemonize(void)
{
int child_status, null_fd;
int child_status;
int fd;
pid_t pid;
struct rlimit rlim;
struct timeval tval;
sigset_t my_sigset;
struct custom_fds custom_fds = {
/* Do not close fds preloaded by systemd! */
.out = (_systemd_activation) ? SD_FD_FIFO_SERVER : -1,
.err = -1,
.report = (_systemd_activation) ? SD_FD_FIFO_CLIENT : -1,
};
sigemptyset(&my_sigset);
if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
@ -1998,28 +1954,33 @@ static void _daemonize(void)
if (chdir("/"))
exit(EXIT_CHDIR_FAILURE);
daemon_close_stray_fds("dmeventd", 0, -1, &custom_fds);
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
fd = 256; /* just have to guess */
else
fd = rlim.rlim_cur;
if ((null_fd = open("/dev/null", O_RDWR)) < 0)
for (--fd; fd >= 0; fd--) {
#ifdef __linux__
/* Do not close fds preloaded by systemd! */
if (_systemd_activation &&
(fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT))
continue;
#endif
(void) close(fd);
}
if ((open("/dev/null", O_RDONLY) < 0) ||
(open("/dev/null", O_WRONLY) < 0) ||
(open("/dev/null", O_WRONLY) < 0))
exit(EXIT_DESC_OPEN_FAILURE);
if ((dup2(null_fd, STDIN_FILENO) == -1) ||
(dup2(null_fd, STDOUT_FILENO) == -1) ||
(dup2(null_fd, STDERR_FILENO) == -1))
exit(EXIT_DESC_OPEN_FAILURE);
if ((null_fd > STDERR_FILENO) && close(null_fd))
exit(EXIT_DESC_CLOSE_FAILURE);
setsid();
/* coverity[leaked_handle] 'null_fd' handle is not leaking */
}
static int _reinstate_registrations(struct dm_event_fifos *fifos)
{
static const char _failed_parsing_msg[] = "Failed to parse existing event registration.\n";
static const char _delim[] = " ";
static const char *_delim = " ";
struct dm_event_daemon_message msg = { 0 };
char *endp, *dso_name, *dev_name, *mask, *timeout;
unsigned long mask_value, timeout_value;
@ -2069,94 +2030,28 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos)
return 1;
}
static int _info_dmeventd(const char *name, struct dm_event_fifos *fifos)
{
struct dm_event_daemon_message msg = { 0 };
int i, count = 0;
char *line;
int version;
int ret = 0;
if (!dm_daemon_is_running(DMEVENTD_PIDFILE)) {
fprintf(stderr, "No running dmeventd instance for status query.\n");
return 0;
}
/* Get the list of registrations from the running daemon. */
if (!init_fifos(fifos)) {
fprintf(stderr, "Could not initiate communication with existing dmeventd.\n");
return 0;
}
if (!dm_event_get_version(fifos, &version)) {
fprintf(stderr, "Could not communicate with existing dmeventd.\n");
goto out;
}
if (version < 1) {
fprintf(stderr, "The running dmeventd instance is too old.\n"
"Protocol version %d (required: 1). Action cancelled.\n", version);
goto out;
}
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0)) {
fprintf(stderr, "Failed to acquire status from existing dmeventd.\n");
goto out;
}
line = strchr(msg.data, ' ') + 1;
for (i = 0; msg.data[i]; ++i)
if (msg.data[i] == ';') {
msg.data[i] = 0;
if (!count)
printf("%s is monitoring:\n", name);
printf("%s\n", line);
line = msg.data + i + 1;
++count;
}
free(msg.data);
if (!count)
printf("%s does not monitor any device.\n", name);
if (version >= 2) {
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
fprintf(stderr, "Failed to acquire parameters from existing dmeventd.\n");
goto out;
}
printf("%s internal status: %s\n", name, msg.data);
free(msg.data);
}
ret = 1;
out:
fini_fifos(fifos);
return ret;
}
/* Return 0 - fail, 1 - success, 2 - continue */
static int _restart_dmeventd(struct dm_event_fifos *fifos)
static void _restart_dmeventd(void)
{
struct dm_event_fifos fifos = {
.client = -1,
.server = -1,
/* FIXME Make these either configurable or depend directly on dmeventd_path */
.client_path = DM_EVENT_FIFO_CLIENT,
.server_path = DM_EVENT_FIFO_SERVER
};
struct dm_event_daemon_message msg = { 0 };
int i, count = 0;
char *message;
int version;
const char *e;
if (!dm_daemon_is_running(DMEVENTD_PIDFILE)) {
fprintf(stderr, "WARNING: Could not find running dmeventd associated with pid file %s.\n", DMEVENTD_PIDFILE);
return 0;
}
/* Get the list of registrations from the running daemon. */
if (!init_fifos(fifos)) {
if (!init_fifos(&fifos)) {
fprintf(stderr, "WARNING: Could not initiate communication with existing dmeventd.\n");
return 0;
exit(EXIT_FAILURE);
}
if (!dm_event_get_version(fifos, &version)) {
if (!dm_event_get_version(&fifos, &version)) {
fprintf(stderr, "WARNING: Could not communicate with existing dmeventd.\n");
goto bad;
}
@ -2168,7 +2063,7 @@ static int _restart_dmeventd(struct dm_event_fifos *fifos)
goto bad;
}
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0))
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_STATUS, "-", "-", 0, 0))
goto bad;
message = strchr(msg.data, ' ') + 1;
@ -2192,7 +2087,7 @@ static int _restart_dmeventd(struct dm_event_fifos *fifos)
}
if (version >= 2) {
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {
fprintf(stderr, "Failed to acquire parameters from old dmeventd.\n");
goto bad;
}
@ -2212,7 +2107,7 @@ static int _restart_dmeventd(struct dm_event_fifos *fifos)
}
#endif
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_DIE, "-", "-", 0, 0)) {
fprintf(stderr, "Old dmeventd refused to die.\n");
goto bad;
}
@ -2221,41 +2116,43 @@ static int _restart_dmeventd(struct dm_event_fifos *fifos)
((e = getenv(SD_ACTIVATION_ENV_VAR_NAME)) && strcmp(e, "1")))
_systemd_activation = 1;
fini_fifos(fifos);
/* Give a few seconds dmeventd to finish */
_wait_for_new_pid();
if (!_systemd_activation)
return 2; // continue with dmeventd start up
/* Reopen fifos. */
if (!init_fifos(fifos)) {
fprintf(stderr, "Could not initiate communication with new instance of dmeventd.\n");
return 0;
for (i = 0; i < 10; ++i) {
if ((access(DMEVENTD_PIDFILE, F_OK) == -1) && (errno == ENOENT))
break;
usleep(10);
}
if (!_reinstate_registrations(fifos)) {
if (!_systemd_activation) {
fini_fifos(&fifos);
return;
}
/* Reopen fifos. */
fini_fifos(&fifos);
if (!init_fifos(&fifos)) {
fprintf(stderr, "Could not initiate communication with new instance of dmeventd.\n");
exit(EXIT_FAILURE);
}
if (!_reinstate_registrations(&fifos)) {
fprintf(stderr, "Failed to reinstate monitoring with new instance of dmeventd.\n");
goto bad;
}
fini_fifos(fifos);
return 1;
fini_fifos(&fifos);
exit(EXIT_SUCCESS);
bad:
fini_fifos(fifos);
return 0;
fini_fifos(&fifos);
exit(EXIT_FAILURE);
}
static void _usage(char *prog, FILE *file)
{
fprintf(file, "Usage:\n"
"%s [-d [-d [-d]]] [-e path] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
"%s [-d [-d [-d]]] [-f] [-h] [-l] [-R] [-V] [-?]\n\n"
" -d Log debug messages to syslog (-d, -dd, -ddd)\n"
" -e Select a file path checked on exit\n"
" -f Don't fork, run in the foreground\n"
" -h Show this help information\n"
" -i Query running instance of dmeventd for info\n"
" -l Log to stdout,stderr instead of syslog\n"
" -? Show this help information on stderr\n"
" -R Restart dmeventd\n"
@ -2265,10 +2162,6 @@ static void _usage(char *prog, FILE *file)
int main(int argc, char *argv[])
{
signed char opt;
int debug_level = 0;
int info = 0;
int restart = 0;
int use_syslog = 1;
struct dm_event_fifos fifos = {
.client = -1,
.server = -1,
@ -2276,58 +2169,39 @@ int main(int argc, char *argv[])
.server_path = DM_EVENT_FIFO_SERVER
};
time_t now, idle_exit_timeout = DMEVENTD_IDLE_EXIT_TIMEOUT;
opterr = 0;
optind = 0;
optopt = optind = opterr = 0;
optarg = (char*) "";
while ((opt = getopt(argc, argv, ":?e:fhiVdlR")) != EOF) {
while ((opt = getopt(argc, argv, "?fhVdlR")) != EOF) {
switch (opt) {
case 'h':
_usage(argv[0], stdout);
return EXIT_SUCCESS;
exit(EXIT_SUCCESS);
case '?':
_usage(argv[0], stderr);
return EXIT_SUCCESS;
case 'i':
info++;
break;
exit(EXIT_SUCCESS);
case 'R':
restart++;
break;
case 'e':
if (strchr(optarg, '"')) {
fprintf(stderr, "dmeventd: option -e does not accept path \"%s\" with '\"' character.\n", optarg);
return EXIT_FAILURE;
}
_exit_on=optarg;
_restart++;
break;
case 'f':
_foreground++;
break;
case 'd':
debug_level++;
_debug_level++;
break;
case 'l':
use_syslog = 0;
_use_syslog = 0;
break;
case 'V':
printf("dmeventd version: %s\n", DM_LIB_VERSION);
return EXIT_SUCCESS;
case ':':
fprintf(stderr, "dmeventd: option -%c requires an argument.\n", optopt);
return EXIT_FAILURE;
exit(EXIT_SUCCESS);
}
}
if (info) {
_foreground = 1;
use_syslog = 0;
}
if (!_foreground && !use_syslog) {
if (!_foreground && !_use_syslog) {
printf("WARNING: Ignoring logging to stdout, needs options -f\n");
use_syslog = 1;
_use_syslog = 1;
}
/*
* Switch to C locale to avoid reading large locale-archive file
* used by some glibc (on some distributions it takes over 100MB).
@ -2336,29 +2210,21 @@ int main(int argc, char *argv[])
if (setenv("LC_ALL", "C", 1))
perror("Cannot set LC_ALL to C");
if (info)
return _info_dmeventd(argv[0], &fifos) ? EXIT_SUCCESS : EXIT_FAILURE;
if (_restart)
_restart_dmeventd();
#ifdef __linux__
_systemd_activation = _systemd_handover(&fifos);
#endif
dm_log_with_errno_init(_libdm_log);
if (restart) {
dm_event_log_set(debug_level, 0);
if ((restart = _restart_dmeventd(&fifos)) < 2)
return restart ? EXIT_SUCCESS : EXIT_FAILURE;
}
if (!_foreground)
_daemonize();
if (use_syslog)
if (_use_syslog)
openlog("dmeventd", LOG_PID, LOG_DAEMON);
dm_event_log_set(debug_level, use_syslog);
dm_event_log_set(_debug_level, _use_syslog);
dm_log_with_errno_init(_libdm_log);
(void) dm_prepare_selinux_context(DMEVENTD_PIDFILE, S_IFREG);
if (dm_create_lockfile(DMEVENTD_PIDFILE) == 0)
@ -2419,28 +2285,15 @@ int main(int argc, char *argv[])
break;
}
}
} else
switch (_exit_now) {
case DM_SIGNALED_EXIT:
_exit_now = DM_SCHEDULED_EXIT;
/*
* When '_exit_now' is set, signal has been received,
* but can not simply exit unless all
* threads are done processing.
*/
log_info("dmeventd received break, scheduling exit.");
/* fall through */
case DM_SCHEDULED_EXIT:
/* While exit is scheduled, check for exit_on file */
DEBUGLOG("Checking exit on file \"%s\".", _exit_on);
if (_exit_on[0] && (access(_exit_on, F_OK) == 0)) {
log_info("dmeventd detected exit on file %s, unregistering all monitored devices.",
_exit_on);
_unregister_all_threads();
}
break;
}
} else if (_exit_now == DM_SIGNALED_EXIT) {
_exit_now = DM_SCHEDULED_EXIT;
/*
* When '_exit_now' is set, signal has been received,
* but can not simply exit unless all
* threads are done processing.
*/
log_info("dmeventd received break, scheduling exit.");
}
_process_request(&fifos);
_cleanup_unused_threads();
}
@ -2450,11 +2303,11 @@ int main(int argc, char *argv[])
log_notice("dmeventd shutting down.");
if (fifos.client >= 0 && close(fifos.client))
log_sys_debug("client close", fifos.client_path);
log_sys_error("client close", fifos.client_path);
if (fifos.server >= 0 && close(fifos.server))
log_sys_debug("server close", fifos.server_path);
log_sys_error("server close", fifos.server_path);
if (use_syslog)
if (_use_syslog)
closelog();
_exit_dm_lib();

View File

@ -68,7 +68,7 @@ struct dm_event_fifos {
int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
unsigned evmask, uint32_t timeout);
enum dm_event_mask evmask, uint32_t timeout);
int init_fifos(struct dm_event_fifos *fifos);
void fini_fifos(struct dm_event_fifos *fifos);
int dm_event_get_version(struct dm_event_fifos *fifos, int *version);

View File

@ -352,7 +352,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
unsigned evmask, uint32_t timeout)
enum dm_event_mask evmask, uint32_t timeout)
{
int msg_size;
memset(msg, 0, sizeof(*msg));
@ -400,16 +400,25 @@ int daemon_talk(struct dm_event_fifos *fifos,
return (int32_t) msg->cmd;
}
/*
* Check for usable client fifo file
* start_daemon
*
* Returns: 2 cliant path does not exists, dmeventd should be restarted
* 1 on success, 0 otherwise
* This function forks off a process (dmeventd) that will handle
* the events. I am currently test opening one of the fifos to
* ensure that the daemon is running and listening... I thought
* this would be less expensive than fork/exec'ing every time.
* Perhaps there is an even quicker/better way (no, checking the
* lock file is _not_ a better way).
*
* Returns: 1 on success, 0 otherwise
*/
static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *fifos)
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
{
int pid, ret = 0;
int status;
struct stat statbuf;
char default_dmeventd_path[] = DMEVENTD_PATH;
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
/*
* FIXME Explicitly verify the code's requirement that client_path is secure:
@ -420,7 +429,7 @@ static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *f
if ((lstat(fifos->client_path, &statbuf) < 0)) {
if (errno == ENOENT)
/* Jump ahead if fifo does not already exist. */
return 2;
goto start_server;
else {
log_sys_error("stat", fifos->client_path);
return 0;
@ -446,14 +455,12 @@ static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *f
log_error("%s is no longer a secure root-owned fifo with mode 0600.", fifos->client_path);
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
fifos->client = -1;
return 0;
}
/* server is running and listening */
if (close(fifos->client))
log_sys_debug("close", fifos->client_path);
fifos->client = -1;
return 1;
}
if (errno != ENXIO && errno != ENOENT) {
@ -462,36 +469,9 @@ static int _check_for_usable_fifos(char *dmeventd_path, struct dm_event_fifos *f
return 0;
}
return 2;
}
/*
* start_daemon
*
* This function forks off a process (dmeventd) that will handle
* the events. I am currently test opening one of the fifos to
* ensure that the daemon is running and listening... I thought
* this would be less expensive than fork/exec'ing every time.
* Perhaps there is an even quicker/better way (no, checking the
* lock file is _not_ a better way).
*
* Returns: 1 on success, 0 otherwise
*/
static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
{
struct stat statbuf;
char default_dmeventd_path[] = DMEVENTD_PATH;
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
int pid, ret = 0;
int status;
switch (_check_for_usable_fifos(dmeventd_path, fifos)) {
case 0: return_0;
case 1: return 1; /* Already running dmeventd */
}
start_server:
/* server is not running */
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
log_sys_error("stat", args[0]);
return 0;
@ -512,17 +492,8 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
strerror(errno));
else if (WEXITSTATUS(status))
log_error("Unable to start dmeventd.");
else {
/* Loop here till forked dmeventd is serving fifos */
for (ret = 100; ret > 0; --ret)
switch (_check_for_usable_fifos(dmeventd_path, fifos)) {
case 0: return_0;
case 1: return 1;
case 2: usleep(1000); break;
}
/* ret == 0 */
log_error("Dmeventd is not serving fifos.");
}
else
ret = 1;
}
return ret;
@ -542,7 +513,7 @@ int init_fifos(struct dm_event_fifos *fifos)
/* Lock out anyone else trying to do communication with the daemon. */
if (flock(fifos->server, LOCK_EX) < 0) {
log_sys_error("flock", fifos->server_path);
goto bad_no_unlock;
goto bad;
}
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
@ -553,9 +524,6 @@ int init_fifos(struct dm_event_fifos *fifos)
return 1;
bad:
if (flock(fifos->server, LOCK_UN))
log_sys_debug("flock unlock", fifos->server_path);
bad_no_unlock:
if (close(fifos->server))
log_sys_debug("close", fifos->server_path);
fifos->server = -1;
@ -584,8 +552,6 @@ void fini_fifos(struct dm_event_fifos *fifos)
if (close(fifos->server))
log_sys_debug("close", fifos->server_path);
}
fifos->client = fifos->server = -1;
}
/* Get uuid of a device */
@ -754,7 +720,7 @@ static char *_fetch_string(char **src, const int delimiter)
/* Parse a device message from the daemon. */
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, unsigned *evmask)
char **uuid, enum dm_event_mask *evmask)
{
char *id;
char *p = msg->data;
@ -779,7 +745,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
int ret = 0;
const char *uuid = NULL;
char *reply_dso = NULL, *reply_uuid = NULL;
unsigned reply_mask = 0;
enum dm_event_mask reply_mask = 0;
struct dm_task *dmt = NULL;
struct dm_event_daemon_message msg = { 0 };
struct dm_info info;
@ -878,7 +844,6 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
char *p;
struct dm_event_daemon_message msg = { 0 };
int ret = 0;
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
return 0;
@ -886,17 +851,13 @@ int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
*version = 0;
if (!p || !(p = strchr(p, ' '))) /* Message ID */
goto out;
return 0;
if (!(p = strchr(p + 1, ' '))) /* HELLO */
goto out;
return 0;
if ((p = strchr(p + 1, ' '))) /* HELLO, once more */
*version = atoi(p);
ret = 1;
out:
free(msg.data);
return ret;
return 1;
}
void dm_event_log_set(int debug_log_level, int use_syslog)
@ -911,11 +872,11 @@ void dm_event_log(const char *subsys, int level, const char *file,
{
static int _abort_on_internal_errors = -1;
static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
static long long _start = 0;
static time_t start = 0;
const char *indent = "";
FILE *stream = log_stderr(level) ? stderr : stdout;
int prio;
long long now, now_nsec;
time_t now;
int log_with_debug = 0;
if (subsys[0] == '#') {
@ -962,28 +923,17 @@ void dm_event_log(const char *subsys, int level, const char *file,
if (_use_syslog) {
vsyslog(prio, format, ap);
} else {
if (_debug_level) {
#define _NSEC_PER_SEC (1000000000LL)
#ifdef HAVE_REALTIME
struct timespec mono_time = { 0 };
if (clock_gettime(CLOCK_MONOTONIC, &mono_time) == 0)
now = mono_time.tv_sec * _NSEC_PER_SEC + mono_time.tv_nsec;
else
#endif
now = time(NULL) * _NSEC_PER_SEC;
if (!_start)
_start = now;
now -= _start;
now_nsec = now %_NSEC_PER_SEC;
now /= _NSEC_PER_SEC;
fprintf(stream, "[%2lld:%02lld.%06lld] %8x:%-6s%s",
now / 60, now % 60, now_nsec / 1000,
now = time(NULL);
if (!start)
start = now;
now -= start;
if (_debug_level)
fprintf(stream, "[%2ld:%02ld] %8x:%-6s%s",
(long)now / 60, (long)now % 60,
// TODO: Maybe use shorter ID
// ((int)(pthread_self()) >> 6) & 0xffff,
(int)pthread_self(), subsys,
(_debug_level > 3) ? "" : indent);
}
if (_debug_level > 3)
fprintf(stream, "%28s:%4d %s", file, line, indent);
vfprintf(stream, _(format), ap);

View File

@ -123,7 +123,6 @@ struct dm_pool *dmeventd_lvm2_pool(void)
int dmeventd_lvm2_run(const char *cmdline)
{
/* coverity[missing_lock] no locking for run part */
return (lvm2_run(_lvm_handle, cmdline) == LVM2_COMMAND_SUCCEEDED);
}

View File

@ -51,14 +51,18 @@ include $(top_builddir)/make.tmpl
.PHONY: install_lvmdbusd
all:
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
install_lvmdbusd: $(LVMDBUSD)
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(sbindir)
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
$(Q) $(INSTALL_DIR) $(lvmdbusdir) $(lvmdbusdir)/__pycache__
$(Q) $(INSTALL_DIR) $(lvmdbusdir)
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(lvmdbusdir))
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(lvmdbusdir)
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbuspydir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
$(Q) $(CHMOD) 755 $(lvmdbusdir)/__pycache__
$(Q) $(CHMOD) 444 $(lvmdbusdir)/__pycache__/*.py[co]
install_lvm2: install_lvmdbusd

View File

@ -44,10 +44,10 @@ class AutomatedProperties(dbus.service.Object):
def set_interface(self, interface):
"""
With inheritance, we can't easily tell what interfaces a class provides,
With inheritance we can't easily tell what interfaces a class provides
so we will have each class that implements an interface tell the
base AutomatedProperties what it is they do provide. This is kind of
clunky, and perhaps we can figure out a better way to do this later.
clunky and perhaps we can figure out a better way to do this later.
:param interface: An interface the object supports
:return:
"""

View File

@ -62,7 +62,7 @@ def _move_callback(job_state, line_str):
def _move_merge(interface_name, command, job_state):
# We need to execute these command stand alone by forking & exec'ing
# the command always as we will be getting periodic output from them on
# the status of the long-running operation.
# the status of the long running operation.
meta = LvmExecutionMeta(time.time(), 0, command)
cfg.flightrecorder.add(meta)

View File

@ -11,7 +11,6 @@ import os
import multiprocessing
import queue
import itertools
from lvmdbusd.utils import LvmDebugData
from lvmdbusd import path
@ -19,10 +18,6 @@ LVM_CMD = os.getenv('LVM_BINARY', path.LVM_BINARY)
LOCK_FILE = os.getenv("LVM_DBUSD_LOCKFILE", "/var/lock/lvm/lvmdbusd")
# Save off the debug data needed for lvm team to debug issues
# only used for 'fullreport' at this time.
lvmdebug = LvmDebugData(os.getenv('LVM_DBUSD_COLLECT_LVM_DEBUG', False))
# This is the global object manager
om = None
@ -32,13 +27,13 @@ bus = None
# Command line args
args = None
# Set to true if we depend on external events for updates
# Set to true if we are depending on external events for updates
got_external_event = False
# Shared state variable across all processes
run = multiprocessing.Value('i', 1)
# If this is set to true, the current setup support lvm shell, and we are
# If this is set to true, the current setup support lvm shell and we are
# running in that mode of operation
SHELL_IN_USE = None
@ -50,8 +45,6 @@ worker_q = queue.Queue()
# Main event loop
loop = None
G_LOOP_TMO = 0.5
# Used to instruct the daemon if we should ignore SIGTERM
ignore_sigterm = False
@ -121,4 +114,7 @@ def exit_daemon():
loop.quit()
# Debug data for lvm
lvmdebug = None
systemd = False

View File

@ -109,7 +109,7 @@ def call_lvm(command, debug=False, line_cb=None,
stdin, CALL MUST EXECUTE QUICKLY and not *block*
otherwise call_lvm function will fail to read
stdin/stdout. Return value of call back is ignored
:param cb_data: Supplied to call back to allow caller access to
:param cb_data: Supplied to callback to allow caller access to
its own data
# Callback signature
@ -136,7 +136,7 @@ def call_lvm(command, debug=False, line_cb=None,
while True and cfg.run.value != 0:
try:
rd_fd = [process.stdout.fileno(), process.stderr.fileno()]
ready = select.select(rd_fd, [], [], cfg.G_LOOP_TMO)
ready = select.select(rd_fd, [], [], 2)
for r in ready[0]:
if r == process.stdout.fileno():
@ -213,7 +213,7 @@ def _shell_cfg():
def set_execution(shell):
global _t_call
with cmd_lock:
# If the user requested lvm shell, and we are currently setup that
# If the user requested lvm shell and we are currently setup that
# way, just return
if cfg.SHELL_IN_USE and shell:
return True
@ -324,12 +324,10 @@ def vg_rename(vg_uuid, new_name, rename_options):
return call(cmd)
def vg_remove(vg_id, remove_options):
def vg_remove(vg_name, remove_options):
cmd = ['vgremove']
cmd.extend(options_to_cli_args(remove_options))
cmd.extend(['-f', vg_id])
# https://bugzilla.redhat.com/show_bug.cgi?id=2175220 is preventing us from doing the following
# cmd.extend(['-f', "--select", "vg_uuid=%s" % vg_id])
cmd.extend(['-f', vg_name])
return call(cmd)
@ -628,18 +626,13 @@ def lvm_full_report_json():
# We are running the fullreport command, we will ask lvm to output the debug
# data, so we can have the required information for lvm to debug the fullreport failures.
# Note: this is disabled by default and can be enabled with env. var.
# LVM_DBUSD_COLLECT_LVM_DEBUG=True
fn = cfg.lvmdebug.setup()
if fn is not None:
add_config_option(cmd, "--config", "log {level=7 file=%s syslog=0}" % fn)
add_config_option(cmd, "--config", "log {level=7 file=%s syslog=0}" % fn)
rc, out, err = call(cmd)
# When we have an exported vg the exit code of lvs or fullreport will be 5
if rc == 0 or rc == 5:
if type(out) != dict:
raise LvmBug("lvm likely returned invalid JSON, lvm exit code = %d, output = %s, err= %s" %
(rc, str(out), str(err)))
assert(type(out) == dict)
return out
raise LvmBug("'fullreport' exited with code '%d'" % rc)
@ -787,10 +780,6 @@ def activate_deactivate(op, name, activate, control_flags, options):
if (1 << 5) & control_flags:
cmd.append('--ignoreactivationskip')
# Shared locking (Cluster)
if (1 << 6) & control_flags:
op += 's'
if activate:
op += 'y'
else:

View File

@ -183,9 +183,9 @@ class StateUpdate(object):
obj.deferred = False
if len(queued_requests) == 0 and wait:
# Note: If we don't have anything for N seconds we will
# Note: If we don't have anything for 2 seconds we will
# get a queue.Empty exception raised here
queued_requests.append(obj.queue.get(block=True, timeout=cfg.G_LOOP_TMO))
queued_requests.append(obj.queue.get(block=True, timeout=2))
# Ok we have one or the deferred queue has some,
# check if any others and grab them too
@ -228,17 +228,8 @@ class StateUpdate(object):
self.queue = queue.Queue()
self.deferred = False
# Do initial load, with retries. During error injection testing we can and do fail here.
count = 0
need_refresh = False # First attempt we are building from new, any subsequent will be true
while count < 5:
try:
load(refresh=need_refresh, emit_signal=False, need_main_thread=False)
break
except LvmBug as bug:
count += 1
need_refresh = True
log_error("We encountered an lvm bug on initial load, trying again %s" % str(bug))
# Do initial load
load(refresh=False, emit_signal=False, need_main_thread=False)
self.thread = threading.Thread(target=StateUpdate.update_thread,
args=(self,),

View File

@ -44,7 +44,7 @@ class WaitingClient(object):
self.timer_id = GLib.timeout_add_seconds(
tmo, WaitingClient._timeout, self)
# The job finished before the timer popped, and we are being notified that
# The job finished before the timer popped and we are being notified that
# it's done
def notify(self):
with self.rlock:
@ -71,7 +71,7 @@ class JobState(object):
self._stderr = ''
self._waiting_clients = []
# This is a lvm command that is just taking too long and doesn't
# This is an lvm command that is just taking too long and doesn't
# support background operation
if self._request:
# Faking the percentage when we don't have one
@ -138,7 +138,7 @@ class JobState(object):
# If a waiting client timer pops before the job is done we will allow
# the client to remove themselves from the list. As we have a lock
# here and a lock in the waiting client too, and they can be obtained
# in different orders, a deadlock can occur.
# in different orders, a dead lock can occur.
# As this remove is really optional, we will try to acquire the lock
# and remove. If we are unsuccessful it's not fatal, we just delay
# the time when the objects can be garbage collected by python

View File

@ -42,7 +42,7 @@ def common(retrieve, o_type, search_keys,
existing_paths = cfg.om.object_paths_by_type(o_type)
for o in objects:
# Assume we need to add this one to dbus, unless we are refreshing,
# Assume we need to add this one to dbus, unless we are refreshing
# and it's already present
return_object = True

View File

@ -25,8 +25,8 @@ from .utils import round_size, mt_remove_dbus_objects, lvm_column_key
from .job import JobState
# Try and build a key for a LV, so that we sort the LVs with the least dependencies
# first. This may be error-prone because of the flexibility LVM
# Try and build a key for a LV, so that we sort the LVs with least dependencies
# first. This may be error prone because of the flexibility LVM
# provides and what you can stack.
def get_key(i):
@ -65,13 +65,13 @@ def lvs_state_retrieve(selection, cache_refresh=True):
if cache_refresh:
cfg.db.refresh()
try:
# When building up the model, it's best to process LVs with the least
# dependencies to those that are dependant upon other LVs. Otherwise, when
# we are trying to gather information we could be in a position where we
# don't have information available yet.
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
# When building up the model, it's best to process LVs with the least
# dependencies to those that are dependant upon other LVs. Otherwise, when
# we are trying to gather information we could be in a position where we
# don't have information available yet.
lvs = sorted(cfg.db.fetch_lvs(selection), key=get_key)
try:
for l in lvs:
if cfg.vdo_support:
rc.append(LvStateVdo(

78
daemons/lvmdbusd/lvm_shell_proxy.py.in Normal file → Executable file
View File

@ -18,7 +18,6 @@ import pty
import sys
import tempfile
import time
import threading
import select
try:
@ -66,7 +65,7 @@ class LVMShellProxy(object):
self.parent_stdout_fd,
self.report_stream.fileno(),
self.parent_stderr_fd]
ready = select.select(rd_fd, [], [], cfg.G_LOOP_TMO)
ready = select.select(rd_fd, [], [], 2)
for r in ready[0]:
if r == self.parent_stdout_fd:
@ -108,14 +107,11 @@ class LVMShellProxy(object):
else:
raise LvmBug(
"lvm returned no JSON output!")
except Exception as e:
log_error("While reading from lvm shell we encountered an error %s" % str(e))
log_error("stdout= %s\nstderr= %s\n" % (stdout, stderr))
if self.lvm_shell.poll() is not None:
log_error("Underlying lvm shell process unexpectedly exited: %d" % self.lvm_shell.returncode)
else:
log_error("Underlying lvm shell process is still present!")
raise e
except IOError as ioe:
log_debug(str(ioe))
self.exit_shell()
raise ioe
if keep_reading and cfg.run.value == 0:
# We didn't complete as we are shutting down
@ -135,10 +131,6 @@ class LVMShellProxy(object):
tmp_dir = tempfile.mkdtemp(prefix="lvmdbus_")
tmp_file = "%s/lvmdbus_report" % (tmp_dir)
# Create a lock so that we don't step on each other when we are waiting for a command
# to finish and some other request comes in concurrently, like to exit the shell.
self.shell_lock = threading.RLock()
# Create a fifo for the report output
os.mkfifo(tmp_file, 0o600)
@ -154,8 +146,6 @@ class LVMShellProxy(object):
# If any env variables contain LVM we will propagate them too
for k, v in os.environ.items():
if "PATH" in k:
local_env[k] = v
if "LVM" in k:
local_env[k] = v
@ -198,8 +188,7 @@ class LVMShellProxy(object):
os.unlink(tmp_file)
os.rmdir(tmp_dir)
def _get_last_log(self):
# Precondition, lock is held
def get_last_log(self):
self._write_cmd('lastlog\n')
report_json = self._read_response()[1]
return get_error_msg(report_json)
@ -220,29 +209,28 @@ class LVMShellProxy(object):
cmd += "\n"
# run the command by writing it to the shell's STDIN
with self.shell_lock:
self._write_cmd(cmd)
self._write_cmd(cmd)
# read everything from the STDOUT to the next prompt
stdout, report_json, stderr = self._read_response()
# read everything from the STDOUT to the next prompt
stdout, report_json, stderr = self._read_response()
# Parse the report to see what happened
if 'log' in report_json:
ret_code = int(report_json['log'][-1:][0]['log_ret_code'])
# If we have an exported vg we get a log_ret_code == 5 when
# we do a 'fullreport'
# Note: 0 == error
if (ret_code == 1) or (ret_code == 5 and argv[0] == 'fullreport'):
rc = 0
else:
# Depending on where lvm fails the command, it may not have anything
# to report for "lastlog", so we need to check for a message in the
# report json too.
error_msg = self._get_last_log()
# Parse the report to see what happened
if 'log' in report_json:
ret_code = int(report_json['log'][-1:][0]['log_ret_code'])
# If we have an exported vg we get a log_ret_code == 5 when
# we do a 'fullreport'
# Note: 0 == error
if (ret_code == 1) or (ret_code == 5 and argv[0] == 'fullreport'):
rc = 0
else:
# Depending on where lvm fails the command, it may not have anything
# to report for "lastlog", so we need to check for a message in the
# report json too.
error_msg = self.get_last_log()
if error_msg is None:
error_msg = get_error_msg(report_json)
if error_msg is None:
error_msg = get_error_msg(report_json)
if error_msg is None:
error_msg = 'No error reason provided! (missing "log" section)'
error_msg = 'No error reason provided! (missing "log" section)'
if debug or rc != 0:
log_error(("CMD= %s" % cmd))
@ -252,14 +240,12 @@ class LVMShellProxy(object):
return rc, report_json, error_msg
def exit_shell(self):
with self.shell_lock:
try:
if self.lvm_shell is not None:
self._write_cmd('exit\n')
self.lvm_shell.wait(1)
self.lvm_shell = None
except Exception as _e:
log_error("exit_shell: %s" % (str(_e)))
try:
self._write_cmd('exit\n')
self.lvm_shell.wait(1)
self.lvm_shell = None
except Exception as _e:
log_error(str(_e))
def __del__(self):
# Note: When we are shutting down the daemon and the main process has already exited

View File

@ -437,8 +437,6 @@ class DataStore(object):
if __name__ == "__main__":
os.environ["LC_ALL"] = "C"
os.environ["LVM_COMMAND_PROFILE"] = "lvmdbusd"
pp = prettyprint.PrettyPrinter(indent=4)
ds = DataStore()

View File

@ -41,7 +41,7 @@ def process_request():
while cfg.run.value != 0:
# noinspection PyBroadException
try:
req = cfg.worker_q.get(True, cfg.G_LOOP_TMO)
req = cfg.worker_q.get(True, 5)
log_debug(
"Method start: %s with args %s (callback = %s)" %
(str(req.method), str(req.arguments), str(req.cb)))
@ -67,7 +67,7 @@ def check_fr_size(value):
def install_signal_handlers():
# Because of the glib main loop stuff the python signal handler code is
# apparently not usable, and we need to use the glib calls instead
# apparently not usable and we need to use the glib calls instead
signal_add = None
if hasattr(GLib, 'unix_signal_add'):
@ -154,6 +154,10 @@ def main():
os.environ["LC_ALL"] = "C"
os.environ["LVM_COMMAND_PROFILE"] = "lvmdbusd"
# Save off the debug data needed for lvm team to debug issues
# only used for 'fullreport' at this time.
cfg.lvmdebug = utils.LvmDebugData()
# Indicator if we are running under systemd
cfg.systemd = running_under_systemd()
@ -204,7 +208,7 @@ def main():
thread_list.append(
threading.Thread(target=process_request, name='process_request'))
# Have a single thread handling updating lvm and the dbus model, so we
# Have a single thread handling updating lvm and the dbus model so we
# don't have multiple threads doing this as the same time
updater = StateUpdate()
thread_list.append(updater.thread)

View File

@ -13,7 +13,7 @@ import dbus
import os
import copy
from . import cfg
from .utils import log_debug, log_error, extract_stack_trace
from .utils import log_debug, pv_obj_path_generate, log_error, extract_stack_trace
from .automatedproperties import AutomatedProperties
@ -159,7 +159,7 @@ class ObjectManager(AutomatedProperties):
# print('Registering object path %s for %s' %
# (path, dbus_object.lvm_id))
# We want fast access to the object by a number of different ways,
# We want fast access to the object by a number of different ways
# so we use multiple hashs with different keys
self._lookup_add(dbus_object, path, dbus_object.lvm_id,
dbus_object.Uuid)
@ -209,7 +209,7 @@ class ObjectManager(AutomatedProperties):
def get_object_by_lvm_id(self, lvm_id):
"""
Given a lvm identifier, return the object registered for it
Given an lvm identifier, return the object registered for it
:param lvm_id: The lvm identifier
"""
with self.rlock:
@ -220,7 +220,7 @@ class ObjectManager(AutomatedProperties):
def get_object_path_by_lvm_id(self, lvm_id):
"""
Given a lvm identifier, return the object path for it
Given an lvm identifier, return the object path for it
:param lvm_id: The lvm identifier
:return: Object path or '/' if not found
"""
@ -295,7 +295,7 @@ class ObjectManager(AutomatedProperties):
if uuid == lvm_id:
path = self._id_lookup(lvm_id)
else:
# We have an uuid and a lvm_id we can do sanity checks to ensure
# We have a 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
@ -305,7 +305,7 @@ class ObjectManager(AutomatedProperties):
if cfg.db.pv_missing(uuid):
lvm_id = None
# Let's check for the uuid first
# Lets check for the uuid first
path = self._id_lookup(uuid)
if path:
# Ensure table lookups are correct

View File

@ -141,7 +141,7 @@ class RequestEntry(object):
mt_async_call(self.cb_error, error_exception)
else:
# We have a job, and it's complete, indicate that it's done.
# We have a job and it's complete, indicate that it's done.
self._job.Complete = True
self._job = None

View File

@ -11,6 +11,7 @@ import xml.etree.ElementTree as Et
import sys
import inspect
import collections
import ctypes
import errno
import fcntl
import os
@ -89,7 +90,7 @@ def init_class_from_arguments(
nt = k
# If the current attribute has a value, but the incoming does
# not, don't overwrite it. Otherwise, the default values on the
# not, don't overwrite it. Otherwise the default values on the
# property decorator don't work as expected.
cur = getattr(obj_instance, nt, v)
@ -109,7 +110,7 @@ def init_class_from_arguments(
def get_properties(f):
"""
Walks through an object instance, or it's parent class(es) and determines
Walks through an object instance or it's parent class(es) and determines
which attributes are properties and if they were created to be used for
dbus.
:param f: Object to inspect
@ -193,7 +194,7 @@ def add_properties(xml, interface, props):
interface_element = c
break
# Interface is not present, lets create it, so we have something to
# Interface is not present, lets create it so we have something to
# attach the properties too
if interface_element is None:
interface_element = Et.Element("interface", name=interface)
@ -304,16 +305,8 @@ class DebugMessages(object):
self.queue.clear()
def _get_tid():
try:
# Only 3.8 and later have this
return threading.get_native_id()
except:
return -1
def _format_log_entry(msg):
tid = _get_tid()
tid = ctypes.CDLL('libc.so.6').syscall(186)
if not cfg.systemd and STDOUT_TTY:
msg = "%s: %d:%d - %s" % \
@ -330,17 +323,16 @@ def _format_log_entry(msg):
def _common_log(msg, *attributes):
msg = _format_log_entry(msg)
cfg.stdout_lock.acquire()
msg = _format_log_entry(msg)
if STDOUT_TTY and attributes:
print(color(msg, *attributes))
else:
print(msg)
sys.stdout.flush()
cfg.stdout_lock.release()
sys.stdout.flush()
# Serializes access to stdout to prevent interleaved output
@ -543,7 +535,7 @@ def round_size(size_bytes):
return size_bytes + bs - remainder
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_/%'
_ALLOWABLE_CH = string.ascii_letters + string.digits + '#+-.:=@_\/%'
_ALLOWABLE_CH_SET = set(_ALLOWABLE_CH)
_ALLOWABLE_VG_LV_CH = string.ascii_letters + string.digits + '.-_+'
@ -778,7 +770,6 @@ class LockFile(object):
def __enter__(self):
try:
os.makedirs(os.path.dirname(self.lock_file), exist_ok=True)
self.fd = os.open(self.lock_file, os.O_CREAT | os.O_RDWR, stat.S_IRUSR | stat.S_IWUSR)
# Get and set the close on exec and lock the file
@ -828,12 +819,9 @@ class LvmBug(RuntimeError):
class LvmDebugData:
def __init__(self, do_collection):
def __init__(self):
self.fd = -1
self.fn = None
self.collect = do_collection
if self.collect:
log_msg("Collecting lvm debug data!")
def _remove_file(self):
if self.fn is not None:
@ -847,10 +835,8 @@ class LvmDebugData:
def setup(self):
# Create a secure filename
if self.collect:
self.fd, self.fn = tempfile.mkstemp(suffix=".log", prefix="lvmdbusd.lvm.debug.")
return self.fn
return None
self.fd, self.fn = tempfile.mkstemp(suffix=".log", prefix="lvmdbusd.lvm.debug.")
return self.fn
def lvm_complete(self):
# Remove the file ASAP, so we decrease our odds of leaving it

View File

@ -151,7 +151,6 @@ class Vg(AutomatedProperties):
_AllocNormal_meta = ('b', VG_INTERFACE)
_AllocAnywhere_meta = ('b', VG_INTERFACE)
_Clustered_meta = ('b', VG_INTERFACE)
_Shared_meta = ('b', VG_INTERFACE)
_Name_meta = ('s', VG_INTERFACE)
# noinspection PyUnusedLocal,PyPep8Naming
@ -786,10 +785,6 @@ class Vg(AutomatedProperties):
def Clustered(self):
return self._attribute(5, 'c')
@property
def Shared(self):
return self._attribute(5, 's')
class VgVdo(Vg):

View File

@ -15,61 +15,61 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
USE_SD_NOTIFY=yes
SOURCES = lvmlockd-core.c
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl
include $(top_builddir)/make.tmpl
ifeq ("@BUILD_LOCKDSANLOCK@", "yes")
SOURCES += lvmlockd-sanlock.c
CFLAGS += $(LIBSANLOCKCLIENT_CFLAGS)
LOCK_LIBS += $(LIBSANLOCKCLIENT_LIBS)
LOCK_LIBS += -lsanlock_client
endif
ifeq ("@BUILD_LOCKDDLM@", "yes")
SOURCES += lvmlockd-dlm.c
CFLAGS += $(LIBDLM) $(LIBDLMCONTROL_CFLAGS)
# LOCK_LIBS += $(LIBDLM_LIBS) $(LIBDLMCONTROL_LIBS)
LOCK_LIBS += -ldlm_lt $(LIBDLMCONTROL_LIBS)
LOCK_LIBS += -ldlm_lt
LOCK_LIBS += -ldlmcontrol
endif
ifeq ("@BUILD_LOCKDIDM@", "yes")
SOURCES += lvmlockd-idm.c
LOCK_LIBS += $(LIBSEAGATEILM_LIBS) $(BLKID_LIBS)
LOCK_LIBS += -lseagate_ilm -lblkid
endif
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
CFLOW_TARGET = lvmlockd
.PHONY: install_lvmlockd install_lvmlockctl
include $(top_builddir)/make.tmpl
CFLAGS += $(EXTRA_EXEC_CFLAGS)
INCLUDES += -I$(top_srcdir)/libdaemon/server
LDFLAGS += -L$(top_builddir)/libdaemon/server $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
ifneq (,$(firstword $(LIBSYSTEMD_LIBS)))
DEFS += -DUSE_SD_NOTIFY
CFLAGS += $(LIBSYSTEMD_CFLAGS)
LIBS += $(LIBSYSTEMD_LIBS)
ifeq ($(USE_SD_NOTIFY),yes)
CFLAGS += $(shell pkg-config --cflags libsystemd) -DUSE_SD_NOTIFY
LIBS += $(shell pkg-config --libs libsystemd)
endif
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
$(SHOW) " [CC] $@"
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LOCK_LIBS) $(LIBS)
lvmlockctl: lvmlockctl.o $(INTERNAL_LIBS)
$(SHOW) " [CC] $@"
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
install_lvmlockd: lvmlockd
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvmlockctl: lvmlockctl
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvm2: install_lvmlockd install_lvmlockctl

View File

@ -264,19 +264,19 @@ static void format_info_r_action(char *line, char *r_name, char *r_type)
static void format_info_line(char *line, char *r_name, char *r_type)
{
if (!strncmp(line, "info=structs ", sizeof("info=structs ") - 1)) {
if (!strncmp(line, "info=structs ", strlen("info=structs "))) {
/* only print this in the raw info dump */
} else if (!strncmp(line, "info=client ", sizeof("info=client ") - 1)) {
} else if (!strncmp(line, "info=client ", strlen("info=client "))) {
save_client_info(line);
} else if (!strncmp(line, "info=ls ", sizeof("info=ls ") - 1)) {
} else if (!strncmp(line, "info=ls ", strlen("info=ls "))) {
format_info_ls(line);
} else if (!strncmp(line, "info=ls_action ", sizeof("info=ls_action ") - 1)) {
} else if (!strncmp(line, "info=ls_action ", strlen("info=ls_action "))) {
format_info_ls_action(line);
} else if (!strncmp(line, "info=r ", sizeof("info=r ") - 1)) {
} else if (!strncmp(line, "info=r ", strlen("info=r "))) {
/*
* r_name/r_type are reset when a new resource is found.
* They are reused for the lock and action lines that
@ -286,11 +286,11 @@ static void format_info_line(char *line, char *r_name, char *r_type)
memset(r_type, 0, MAX_NAME+1);
format_info_r(line, r_name, r_type);
} else if (!strncmp(line, "info=lk ", sizeof("info=lk ") - 1)) {
} else if (!strncmp(line, "info=lk ", strlen("info=lk "))) {
/* will use info from previous r */
format_info_lk(line, r_name, r_type);
} else if (!strncmp(line, "info=r_action ", sizeof("info=r_action ") - 1)) {
} else if (!strncmp(line, "info=r_action ", strlen("info=r_action "))) {
/* will use info from previous r */
format_info_r_action(line, r_name, r_type);
} else {
@ -940,7 +940,7 @@ static int read_options(int argc, char *argv[])
int option_index = 0;
int c;
static const struct option _long_options[] = {
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
{"quit", no_argument, 0, 'q' },
{"info", no_argument, 0, 'i' },
@ -962,7 +962,7 @@ static int read_options(int argc, char *argv[])
}
while (1) {
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", _long_options, &option_index);
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", long_options, &option_index);
if (c == -1)
break;

View File

@ -16,12 +16,9 @@
#define LVMLOCKD_SOCKET DEFAULT_RUN_DIR "/lvmlockd.socket"
#define LVMLOCKD_ADOPT_FILE DEFAULT_RUN_DIR "/lvmlockd.adopt"
#define LVMLOCKD_USE_SANLOCK_LVB 0
/* Wrappers to open/close connection */
static inline __attribute__((always_inline))
daemon_handle lvmlockd_open(const char *sock)
static inline daemon_handle lvmlockd_open(const char *sock)
{
daemon_info lvmlockd_info = {
.path = "lvmlockd",
@ -54,8 +51,5 @@ static inline void lvmlockd_close(daemon_handle h)
#define EREMOVED 219
#define EDEVOPEN 220 /* sanlock failed to open lvmlock LV */
#define ELMERR 221
#define EORPHAN 222
#define EADOPT_NONE 223
#define EADOPT_RETRY 224
#endif /* _LVM_LVMLOCKD_CLIENT_H */

View File

@ -140,7 +140,7 @@ static int str_to_mode(const char *str);
* the act is passed back to the client_thread to be returned to the client.
*/
static const char lvmlockd_protocol[] = "lvmlockd";
static const char *lvmlockd_protocol = "lvmlockd";
static const int lvmlockd_protocol_version = 1;
static int daemon_quit;
static int adopt_opt;
@ -810,27 +810,6 @@ static const char *op_str(int x)
};
}
static const char *op_mode_str(int op, int mode)
{
if (op != LD_OP_LOCK)
return op_str(op);
switch (mode) {
case LD_LK_IV:
return "lock_iv";
case LD_LK_UN:
return "unlock";
case LD_LK_NL:
return "lock_nl";
case LD_LK_SH:
return "lock_sh";
case LD_LK_EX:
return "lock_ex";
default:
return "lock_bad";
}
}
int last_string_from_args(char *args_in, char *last)
{
const char *args = args_in;
@ -1062,16 +1041,16 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
return rv;
}
static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt_only, int adopt_ok)
static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt)
{
int rv;
if (ls->lm_type == LD_LM_DLM)
rv = lm_add_lockspace_dlm(ls, adopt_only, adopt_ok);
rv = lm_add_lockspace_dlm(ls, adopt);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_add_lockspace_sanlock(ls, adopt_only, adopt_ok);
rv = lm_add_lockspace_sanlock(ls, adopt);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_add_lockspace_idm(ls, adopt_only, adopt_ok);
rv = lm_add_lockspace_idm(ls, adopt);
else
return -1;
@ -1099,17 +1078,17 @@ static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_v
}
static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct action *act,
struct val_blk *vb_out, int *retry, int adopt_only, int adopt_ok)
struct val_blk *vb_out, int *retry, int adopt)
{
int rv;
if (ls->lm_type == LD_LM_DLM)
rv = lm_lock_dlm(ls, r, mode, vb_out, adopt_only, adopt_ok);
rv = lm_lock_dlm(ls, r, mode, vb_out, adopt);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_lock_sanlock(ls, r, mode, vb_out, retry, adopt_only, adopt_ok);
rv = lm_lock_sanlock(ls, r, mode, vb_out, retry, adopt);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid,
&act->pvs, adopt_only, adopt_ok);
&act->pvs, adopt);
else
return -1;
@ -1190,13 +1169,10 @@ static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *s
/*
* While adopting locks, actions originate from the adopt_locks()
* function, not from a client. So, these actions (flagged ADOPT_ONLY),
* function, not from a client. So, these actions (flagged ADOPT),
* should be passed back to the adopt_locks() function through the
* adopt_results list, and not be sent back to a client via the
* client_list/client_thread. INTERNAL_CLIENT_ID indicates the
* act was generated internally and not from a client, and
* distinguishes internal adopt request from those received from
* a client.
* client_list/client_thread.
*/
static void add_client_result(struct action *act)
@ -1209,7 +1185,7 @@ static void add_client_result(struct action *act)
}
pthread_mutex_lock(&client_mutex);
if ((act->flags & LD_AF_ADOPT_ONLY) && (act->client_id == INTERNAL_CLIENT_ID))
if (act->flags & LD_AF_ADOPT)
list_add_tail(&act->list, &adopt_results);
else
list_add_tail(&act->list, &client_results);
@ -1274,11 +1250,9 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
r->last_client_id = act->client_id;
if (r->type == LD_RT_LV)
log_debug("%s:%s res_lock %s cl %u (%s)", ls->name, r->name,
mode_str(act->mode), act->client_id, act->lv_name);
log_debug("S %s R %s res_lock cl %u mode %s (%s)", ls->name, r->name, act->client_id, mode_str(act->mode), act->lv_name);
else
log_debug("%s:%s res_lock %s cl %u", ls->name, r->name,
mode_str(act->mode), act->client_id);
log_debug("S %s R %s res_lock cl %u mode %s", ls->name, r->name, act->client_id, mode_str(act->mode));
if (r->mode == LD_LK_SH && act->mode == LD_LK_SH)
goto add_lk;
@ -1286,15 +1260,13 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
if (r->type == LD_RT_LV && act->lv_args[0])
memcpy(r->lv_args, act->lv_args, MAX_ARGS);
rv = lm_lock(ls, r, act->mode, act, &vb, retry,
act->flags & LD_AF_ADOPT_ONLY ? 1 : 0,
act->flags & LD_AF_ADOPT ? 1 : 0);
rv = lm_lock(ls, r, act->mode, act, &vb, retry, act->flags & LD_AF_ADOPT);
if (rv && r->use_vb)
log_debug("%s:%s res_lock rv %d read vb %x %x %u",
if (r->use_vb)
log_debug("S %s R %s res_lock rv %d read vb %x %x %u",
ls->name, r->name, rv, vb.version, vb.flags, vb.r_version);
else if (rv)
log_debug("%s:%s res_lock rv %d", ls->name, r->name, rv);
else
log_debug("S %s R %s res_lock rv %d", ls->name, r->name, rv);
if (rv < 0)
return rv;
@ -1307,7 +1279,7 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
* be invalidated. When we need to invalidate the lvmetad
* cache, but don't have a usable r_version from the lvb,
* send lvmetad new_version 0 which causes it to invalidate
* the VG metadata without comparing against the currently
* the VG metdata without comparing against the currently
* cached VG seqno.
*/
@ -1317,7 +1289,7 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
/* LV locks don't use an lvb. */
} else if (vb.version && ((vb.version & 0xFF00) > (VAL_BLK_VERSION & 0xFF00))) {
log_error("%s:%s res_lock invalid val_blk version %x flags %x r_version %u",
log_error("S %s R %s res_lock invalid val_blk version %x flags %x r_version %u",
ls->name, r->name, vb.version, vb.flags, vb.r_version);
inval_meta = 1;
new_version = 0;
@ -1335,7 +1307,7 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
* acquired it, and increased r_version so we know that our
* cache is invalid.
*/
log_debug("%s:%s res_lock got version %u our %u",
log_debug("S %s R %s res_lock got version %u our %u",
ls->name, r->name, vb.r_version, r->version);
r->version = vb.r_version;
new_version = vb.r_version;
@ -1348,9 +1320,7 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
* once someone uses the lock and writes a new lvb value.
* Do nothing.
*/
/*
log_debug("%s:%s res_lock version_zero_valid still zero", ls->name, r->name);
*/
log_debug("S %s R %s res_lock version_zero_valid still zero", ls->name, r->name);
} else if (r->version_zero_valid && vb.r_version) {
/*
@ -1373,11 +1343,11 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
* larger version?)
*/
if (r->version && (r->version >= vb.r_version)) {
log_debug("%s:%s res_lock version_zero_valid got version %u less than our %u",
log_debug("S %s R %s res_lock version_zero_valid got version %u less than our %u",
ls->name, r->name, vb.r_version, r->version);
new_version = 0;
} else {
log_debug("%s:%s res_lock version_zero_valid got version %u our %u",
log_debug("S %s R %s res_lock version_zero_valid got version %u our %u",
ls->name, r->name, vb.r_version, r->version);
new_version = vb.r_version;
}
@ -1389,7 +1359,7 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
/*
* The first time we've acquired the lock and seen the lvb.
*/
log_debug("%s:%s res_lock initial version %u", ls->name, r->name, vb.r_version);
log_debug("S %s R %s res_lock initial version %u", ls->name, r->name, vb.r_version);
r->version = vb.r_version;
inval_meta = 1;
new_version = vb.r_version;
@ -1400,7 +1370,7 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
* The lock may have never been used to change something.
* (e.g. a new sanlock GL?)
*/
log_debug("%s:%s res_lock all versions zero", ls->name, r->name);
log_debug("S %s R %s res_lock all versions zero", ls->name, r->name);
if (!r->version_zero_valid) {
inval_meta = 1;
new_version = 0;
@ -1424,9 +1394,9 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
* is unchanged and we don't need to invalidate metadata.
*/
if ((ls->lm_type == LD_LM_DLM) && !vb.version && !vb.flags)
log_debug("%s:%s res_lock all lvb content is blank",
log_debug("S %s R %s res_lock all lvb content is blank",
ls->name, r->name);
log_debug("%s:%s res_lock our version %u got vb %x %x %u",
log_debug("S %s R %s res_lock our version %u got vb %x %x %u",
ls->name, r->name, r->version, vb.version, vb.flags, vb.r_version);
r->version_zero_valid = 1;
inval_meta = 1;
@ -1443,21 +1413,21 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
* FIXME: how does the cache validation and replacement in lvmetad
* work in this case?
*/
log_debug("%s:%s res_lock got version %u less than our version %u",
log_debug("S %s R %s res_lock got version %u less than our version %u",
ls->name, r->name, vb.r_version, r->version);
r->version = vb.r_version;
inval_meta = 1;
new_version = 0;
r->version_zero_valid = 0;
} else {
log_debug("%s:%s res_lock undefined vb condition vzv %d our version %u vb %x %x %u",
log_debug("S %s R %s res_lock undefined vb condition vzv %d our version %u vb %x %x %u",
ls->name, r->name, r->version_zero_valid, r->version,
vb.version, vb.flags, vb.r_version);
}
if (vb.version && vb.r_version && (vb.flags & VBF_REMOVED)) {
/* Should we set ls->thread_stop = 1 ? */
log_debug("%s:%s res_lock vb flag REMOVED",
log_debug("S %s R %s res_lock vb flag REMOVED",
ls->name, r->name);
rv = -EREMOVED;
}
@ -1499,12 +1469,12 @@ static int res_lock(struct lockspace *ls, struct resource *r, struct action *act
*/
if (inval_meta && (r->type == LD_RT_VG)) {
log_debug("%s:%s res_lock invalidate vg state version %u",
log_debug("S %s R %s res_lock invalidate vg state version %u",
ls->name, r->name, new_version);
}
if (inval_meta && (r->type == LD_RT_GL)) {
log_debug("%s:%s res_lock invalidate global state", ls->name, r->name);
log_debug("S %s R %s res_lock invalidate global state", ls->name, r->name);
}
/*
@ -1561,8 +1531,7 @@ static int res_convert(struct lockspace *ls, struct resource *r,
r->last_client_id = act->client_id;
log_debug("%s:%s res_convert %s cl %u", ls->name, r->name,
mode_str(act->mode), act->client_id);
log_debug("S %s R %s res_convert cl %u mode %s", ls->name, r->name, act->client_id, mode_str(act->mode));
if (act->mode == LD_LK_EX && lk->mode == LD_LK_SH && r->sh_count > 1)
return -EAGAIN;
@ -1578,7 +1547,7 @@ static int res_convert(struct lockspace *ls, struct resource *r,
r_version = r->version;
r->version_zero_valid = 0;
log_debug("%s:%s res_convert r_version inc %u",
log_debug("S %s R %s res_convert r_version inc %u",
ls->name, r->name, r_version);
} else if ((r->type == LD_RT_VG) && (r->mode == LD_LK_EX) && (lk->version > r->version)) {
@ -1586,14 +1555,14 @@ static int res_convert(struct lockspace *ls, struct resource *r,
r_version = r->version;
r->version_zero_valid = 0;
log_debug("%s:%s res_convert r_version new %u", ls->name, r->name, r_version);
log_debug("S %s R %s res_convert r_version new %u", ls->name, r->name, r_version);
} else {
r_version = 0;
}
rv = lm_convert(ls, r, act->mode, act, r_version);
log_debug("%s:%s res_convert rv %d", ls->name, r->name, rv);
log_debug("S %s R %s res_convert rv %d", ls->name, r->name, rv);
if (rv < 0)
return rv;
@ -1604,7 +1573,7 @@ static int res_convert(struct lockspace *ls, struct resource *r,
r->sh_count = 0;
} else {
/* should not be possible */
log_error("%s:%s res_convert invalid modes %d %d",
log_error("S %s R %s res_convert invalid modes %d %d",
ls->name, r->name, lk->mode, act->mode);
return -1;
}
@ -1643,7 +1612,7 @@ static int res_cancel(struct lockspace *ls, struct resource *r,
return -ENOENT;
do_cancel:
log_debug("%s:%s res_cancel cl %u", ls->name, r->name, cact->client_id);
log_debug("S %s R %s res_cancel cl %u", ls->name, r->name, cact->client_id);
cact->result = -ECANCELED;
list_del(&cact->list);
add_client_result(cact);
@ -1691,12 +1660,12 @@ static int res_unlock(struct lockspace *ls, struct resource *r,
}
if (act->op != LD_OP_CLOSE)
log_debug("%s:%s res_unlock cl %u no locks", ls->name, r->name, act->client_id);
log_debug("S %s R %s res_unlock cl %u no locks", ls->name, r->name, act->client_id);
return -ENOENT;
do_unlock:
if ((act->flags & LD_AF_LV_UNLOCK) && (r->last_client_id != act->client_id)) {
log_debug("%s:%s res_unlock cl %u for failed client ignored, last client %u",
log_debug("S %s R %s res_unlock cl %u for failed client ignored, last client %u",
ls->name, r->name, act->client_id, r->last_client_id);
return -ENOENT;
}
@ -1704,17 +1673,17 @@ do_unlock:
r->last_client_id = act->client_id;
if (act->op == LD_OP_CLOSE)
log_debug("%s:%s res_unlock cl %u from close", ls->name, r->name, act->client_id);
log_debug("S %s R %s res_unlock cl %u from close", ls->name, r->name, act->client_id);
else if (r->type == LD_RT_LV)
log_debug("%s:%s res_unlock cl %u (%s)", ls->name, r->name, act->client_id, act->lv_name);
log_debug("S %s R %s res_unlock cl %u (%s)", ls->name, r->name, act->client_id, act->lv_name);
else
log_debug("%s:%s res_unlock cl %u", ls->name, r->name, act->client_id);
log_debug("S %s R %s res_unlock cl %u", ls->name, r->name, act->client_id);
/* send unlock to lm when last sh lock is unlocked */
if (lk->mode == LD_LK_SH) {
r->sh_count--;
if (r->sh_count > 0) {
log_debug("%s:%s res_unlock sh_count %u", ls->name, r->name, r->sh_count);
log_debug("S %s R %s res_unlock sh_count %u", ls->name, r->name, r->sh_count);
goto rem_lk;
}
}
@ -1725,14 +1694,14 @@ do_unlock:
r_version = r->version;
r->version_zero_valid = 0;
log_debug("%s:%s res_unlock r_version inc %u", ls->name, r->name, r_version);
log_debug("S %s R %s res_unlock r_version inc %u", ls->name, r->name, r_version);
} else if ((r->type == LD_RT_VG) && (r->mode == LD_LK_EX) && (lk->version > r->version)) {
r->version = lk->version;
r_version = r->version;
r->version_zero_valid = 0;
log_debug("%s:%s res_unlock r_version new %u",
log_debug("S %s R %s res_unlock r_version new %u",
ls->name, r->name, r_version);
} else {
r_version = 0;
@ -1741,11 +1710,11 @@ do_unlock:
rv = lm_unlock(ls, r, act, r_version, 0);
if (rv < 0) {
/* should never happen, retry? */
log_error("%s:%s res_unlock lm error %d", ls->name, r->name, rv);
log_error("S %s R %s res_unlock lm error %d", ls->name, r->name, rv);
return rv;
}
/* log_debug("%s:%s res_unlock lm done", ls->name, r->name); */
log_debug("S %s R %s res_unlock lm done", ls->name, r->name);
rem_lk:
list_del(&lk->list);
@ -1764,13 +1733,13 @@ static int res_update(struct lockspace *ls, struct resource *r,
lk = find_lock_client(r, act->client_id);
if (!lk) {
log_error("%s:%s res_update cl %u lock not found",
log_error("S %s R %s res_update cl %u lock not found",
ls->name, r->name, act->client_id);
return -ENOENT;
}
if (r->mode != LD_LK_EX) {
log_error("%s:%s res_update cl %u version on non-ex lock",
log_error("S %s R %s res_update cl %u version on non-ex lock",
ls->name, r->name, act->client_id);
return -EINVAL;
}
@ -1791,13 +1760,13 @@ static int res_update(struct lockspace *ls, struct resource *r,
* force an invalidation on other hosts. The next change
* will return to using the seqno again.
*/
log_error("%s:%s res_update cl %u old version %u new version %u too small",
log_error("S %s R %s res_update cl %u old version %u new version %u too small",
ls->name, r->name, act->client_id, r->version, act->version);
}
lk->version = act->version;
}
log_debug("%s:%s res_update cl %u lk version to %u", ls->name, r->name, act->client_id, lk->version);
log_debug("S %s R %s res_update cl %u lk version to %u", ls->name, r->name, act->client_id, lk->version);
return 0;
}
@ -1950,7 +1919,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
list_for_each_entry_safe(act, safe, &r->actions, list) {
if (act->op == LD_OP_FREE && act->rt == LD_RT_LV) {
log_debug("%s:%s free_lv", ls->name, r->name);
log_debug("S %s R %s free_lv", ls->name, r->name);
rv = free_lv(ls, r);
act->result = rv;
list_del(&act->list);
@ -1972,7 +1941,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
add_client_result(act);
if (!rv && act->op == LD_OP_DISABLE) {
log_debug("%s:%s free disabled", ls->name, r->name);
log_debug("S %s R %s free disabled", ls->name, r->name);
goto r_free;
}
}
@ -2190,7 +2159,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
(act->retries <= act->max_retries) &&
(lm_retry || (r->type != LD_RT_LV))) {
/* leave act on list */
log_debug("%s:%s res_lock EAGAIN retry", ls->name, r->name);
log_debug("S %s R %s res_lock EAGAIN retry", ls->name, r->name);
act->retries++;
*retry_out = 1;
} else {
@ -2223,7 +2192,7 @@ static void res_process(struct lockspace *ls, struct resource *r,
(act->retries <= act->max_retries) &&
(lm_retry || (r->type != LD_RT_LV))) {
/* leave act on list */
log_debug("%s:%s res_lock EAGAIN retry", ls->name, r->name);
log_debug("S %s R %s res_lock EAGAIN retry", ls->name, r->name);
act->retries++;
*retry_out = 1;
} else {
@ -2242,13 +2211,13 @@ static void res_process(struct lockspace *ls, struct resource *r,
r_free:
/* For the EUNATCH case it may be possible there are queued actions? */
list_for_each_entry_safe(act, safe, &r->actions, list) {
log_error("%s:%s res_process r_free cancel %s client %d",
log_error("S %s R %s res_process r_free cancel %s client %d",
ls->name, r->name, op_str(act->op), act->client_id);
act->result = -ECANCELED;
list_del(&act->list);
add_client_result(act);
}
log_debug("%s:%s res_process free", ls->name, r->name);
log_debug("S %s R %s res_process free", ls->name, r->name);
lm_rem_resource(ls, r);
list_del(&r->list);
free_resource(r);
@ -2306,9 +2275,9 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
*/
if (lk->flags & LD_LF_PERSISTENT && !drop_vg)
log_error("%s:%s clear lock persistent", ls->name, r->name);
log_error("S %s R %s clear lock persistent", ls->name, r->name);
else
log_debug("%s:%s clear lock mode %s client %d", ls->name, r->name, mode_str(lk->mode), lk->client_id);
log_debug("S %s R %s clear lock mode %s client %d", ls->name, r->name, mode_str(lk->mode), lk->client_id);
if (lk->version > lk_version)
lk_version = lk->version;
@ -2323,13 +2292,13 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
if ((r->type == LD_RT_GL) && (r->mode == LD_LK_EX)) {
r->version++;
r_version = r->version;
log_debug("%s:%s clear_locks r_version inc %u",
log_debug("S %s R %s clear_locks r_version inc %u",
ls->name, r->name, r_version);
} else if ((r->type == LD_RT_VG) && (r->mode == LD_LK_EX) && (lk_version > r->version)) {
r->version = lk_version;
r_version = r->version;
log_debug("%s:%s clear_locks r_version new %u",
log_debug("S %s R %s clear_locks r_version new %u",
ls->name, r->name, r_version);
} else {
@ -2339,19 +2308,19 @@ static int clear_locks(struct lockspace *ls, int free_vg, int drop_vg)
rv = lm_unlock(ls, r, NULL, r_version, free_vg ? LMUF_FREE_VG : 0);
if (rv < 0) {
/* should never happen */
log_error("%s:%s clear_locks free %d drop %d lm unlock error %d",
log_error("S %s R %s clear_locks free %d drop %d lm unlock error %d",
ls->name, r->name, free_vg, drop_vg, rv);
}
list_for_each_entry_safe(act, act_safe, &r->actions, list) {
log_error("%s:%s clear_locks cancel %s client %d",
log_error("S %s R %s clear_locks cancel %s client %d",
ls->name, r->name, op_str(act->op), act->client_id);
act->result = -ECANCELED;
list_del(&act->list);
add_client_result(act);
}
r_free:
log_debug("%s:%s free", ls->name, r->name);
log_debug("S %s R %s free", ls->name, r->name);
lm_rem_resource(ls, r);
list_del(&r->list);
free_resource(r);
@ -2398,13 +2367,13 @@ static struct resource *find_resource_act(struct lockspace *ls,
r->mode = LD_LK_UN;
if (r->type == LD_RT_GL) {
dm_strncpy(r->name, R_NAME_GL, sizeof(r->name));
strncpy(r->name, R_NAME_GL, MAX_NAME);
r->use_vb = 1;
} else if (r->type == LD_RT_VG) {
dm_strncpy(r->name, R_NAME_VG, sizeof(r->name));
strncpy(r->name, R_NAME_VG, MAX_NAME);
r->use_vb = 1;
} else if (r->type == LD_RT_LV) {
dm_strncpy(r->name, act->lv_uuid, sizeof(r->name));
strncpy(r->name, act->lv_uuid, MAX_NAME);
r->use_vb = 0;
}
@ -2488,18 +2457,15 @@ static void *lockspace_thread_main(void *arg_in)
struct list_head tmp_act;
struct list_head act_close;
char tmp_name[MAX_NAME+5];
int fail_stop_busy;
int free_vg = 0;
int drop_vg = 0;
int error = 0;
int adopt_only = 0;
int adopt_ok = 0;
int adopt_flag = 0;
int wait_flag = 0;
int retry;
int rv;
INIT_LIST_HEAD(&act_close);
INIT_LIST_HEAD(&tmp_act);
/* first action may be client add */
pthread_mutex_lock(&ls->mutex);
@ -2513,21 +2479,14 @@ static void *lockspace_thread_main(void *arg_in)
if (add_act->flags & LD_AF_WAIT)
wait_flag = 1;
if (add_act->flags & LD_AF_ADOPT_ONLY)
adopt_only = 1;
if (add_act->flags & LD_AF_ADOPT)
adopt_ok = 1;
adopt_flag = 1;
}
}
pthread_mutex_unlock(&ls->mutex);
if (ls->lm_type == LD_LM_DLM && !strcmp(gl_lsname_dlm, ls->name)) {
log_debug("dlm global lockspace adopt_ok");
adopt_ok = 1;
}
log_debug("S %s lm_add_lockspace %s wait %d adopt_only %d adopt_ok %d",
ls->name, lm_str(ls->lm_type), wait_flag, adopt_only, adopt_ok);
log_debug("S %s lm_add_lockspace %s wait %d adopt %d",
ls->name, lm_str(ls->lm_type), wait_flag, adopt_flag);
/*
* The prepare step does not wait for anything and is quick;
@ -2546,7 +2505,7 @@ static void *lockspace_thread_main(void *arg_in)
* The actual lockspace join can take a while.
*/
if (!error) {
error = lm_add_lockspace(ls, add_act, adopt_only, adopt_ok);
error = lm_add_lockspace(ls, add_act, adopt_flag);
log_debug("S %s lm_add_lockspace done %d", ls->name, error);
@ -2573,8 +2532,6 @@ static void *lockspace_thread_main(void *arg_in)
if (error)
goto out_act;
restart:
while (1) {
pthread_mutex_lock(&ls->mutex);
while (!ls->thread_work) {
@ -2755,7 +2712,7 @@ static void *lockspace_thread_main(void *arg_in)
list_add_tail(&act->list, &r->actions);
log_debug("%s:%s action %s %s", ls->name, r->name,
log_debug("S %s R %s action %s %s", ls->name, r->name,
op_str(act->op), mode_str(act->mode));
}
pthread_mutex_unlock(&ls->mutex);
@ -2827,48 +2784,17 @@ out_rem:
* Leave the lockspace.
*/
fail_stop_busy = 0;
rv = lm_rem_lockspace(ls, NULL, free_vg);
if (rv < 0) {
pthread_mutex_lock(&ls->mutex);
list_for_each_entry_safe(act, safe, &ls->actions, list) {
/*
* If there's a stop action then there's a path to return an error,
* and in the case of EBUSY presumably there's a chance to redo it.
*/
if ((act->op == LD_OP_STOP) && (rv == -EBUSY)) {
log_debug("S %s rem_lockspace for stop error %d", ls->name, rv);
act->result = -EBUSY;
list_del(&act->list);
list_add_tail(&act->list, &tmp_act);
ls->thread_stop = 0;
fail_stop_busy = 1;
break;
}
}
pthread_mutex_unlock(&ls->mutex);
if (fail_stop_busy) {
pthread_mutex_lock(&client_mutex);
list_del(&act->list);
list_add_tail(&act->list, &client_results);
pthread_cond_signal(&client_cond);
pthread_mutex_unlock(&client_mutex);
goto restart;
}
}
if (rv < 0)
log_debug("S %s rem_lockspace error %d", ls->name, rv);
else
log_debug("S %s rem_lockspace done", ls->name);
log_debug("S %s rem_lockspace done %d", ls->name, rv);
out_act:
/*
* Move remaining actions to results; this will usually (always?)
* be only the stop action.
*/
INIT_LIST_HEAD(&tmp_act);
pthread_mutex_lock(&ls->mutex);
list_for_each_entry_safe(act, safe, &ls->actions, list) {
if (act->op == LD_OP_FREE) {
@ -2992,11 +2918,12 @@ static struct lockspace *find_lockspace_name(char *ls_name)
static int vg_ls_name(const char *vg_name, char *ls_name)
{
if (snprintf(ls_name, MAX_NAME, "%s%s", LVM_LS_PREFIX, vg_name) >= MAX_NAME) {
if (strlen(vg_name) + 4 > MAX_NAME) {
log_error("vg name too long %s", vg_name);
return -1;
}
snprintf(ls_name, MAX_NAME, "%s%s", LVM_LS_PREFIX, vg_name);
return 0;
}
@ -3054,13 +2981,13 @@ static int add_lockspace_thread(const char *ls_name,
if (vg_uuid)
/* coverity[buffer_size_warning] */
memccpy(ls->vg_uuid, vg_uuid, 0, 64);
strncpy(ls->vg_uuid, vg_uuid, 64);
if (vg_name)
dm_strncpy(ls->vg_name, vg_name, sizeof(ls->vg_name));
strncpy(ls->vg_name, vg_name, MAX_NAME);
if (vg_args)
dm_strncpy(ls->vg_args, vg_args, sizeof(ls->vg_args));
strncpy(ls->vg_args, vg_args, MAX_ARGS);
if (act)
ls->host_id = act->host_id;
@ -3602,7 +3529,7 @@ static void work_test_gl(void)
is_enabled = lm_gl_is_enabled(ls);
if (is_enabled) {
log_debug("S %s worker found gl_is_enabled", ls->name);
dm_strncpy(gl_lsname_sanlock, ls->name, sizeof(gl_lsname_sanlock));
strncpy(gl_lsname_sanlock, ls->name, MAX_NAME);
}
}
pthread_mutex_unlock(&ls->mutex);
@ -4144,7 +4071,7 @@ static int client_send_result(struct client *cl, struct action *act)
log_debug("send %s[%d] cl %u %s %s rv %d %s %s",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_mode_str(act->op, act->mode), rt_str(act->rt),
op_str(act->op), rt_str(act->rt),
act->result, (act->result == -ENOLS) ? "ENOLS" : "", result_flags);
res = daemon_reply_simple("OK",
@ -4228,26 +4155,12 @@ static int add_lock_action(struct action *act)
vg_ls_name(act->vg_name, ls_name);
} else {
if (!gl_use_dlm && !gl_use_sanlock && !gl_use_idm) {
int run_sanlock = lm_is_running_sanlock();
int run_dlm = lm_is_running_dlm();
int run_idm = lm_is_running_idm();
if (run_sanlock + run_dlm + run_idm >= 2) {
log_error("global lock op %s mode %s: multiple lock managers running sanlock=%d dlm=%d idm=%d",
op_str(act->op), mode_str(act->mode), run_sanlock, run_dlm, run_idm);
} else if (!run_sanlock && !run_dlm && !run_idm) {
log_debug("global lock op %s mode %s: no lock manager running",
op_str(act->op), mode_str(act->mode));
} else {
if (run_dlm)
gl_use_dlm = 1;
else if (run_sanlock)
gl_use_sanlock = 1;
else if (run_idm)
gl_use_idm = 1;
log_debug("global lock op %s mode %s: gl_use_sanlock %d gl_use_dlm %d gl_use_idm %d",
op_str(act->op), mode_str(act->mode), gl_use_sanlock, gl_use_dlm, gl_use_idm);
}
if (lm_is_running_dlm())
gl_use_dlm = 1;
else if (lm_is_running_sanlock())
gl_use_sanlock = 1;
else if (lm_is_running_idm())
gl_use_idm = 1;
}
gl_ls_name(ls_name);
}
@ -4553,12 +4466,6 @@ static uint32_t str_to_opts(const char *str)
flags |= LD_AF_ENABLE;
if (strstr(str, "disable"))
flags |= LD_AF_DISABLE;
/* FIXME: parse the flag values properly */
if (strstr(str, "adopt_only"))
flags |= LD_AF_ADOPT_ONLY;
else if (strstr(str, "adopt"))
flags |= LD_AF_ADOPT;
out:
return flags;
}
@ -4783,12 +4690,9 @@ static int dump_info(int *dump_len)
/*
* clients
* Proper lock order is client_mutex then cl->mutex,
* but cl->mutex is already held so skip client info
* if it would block.
*/
if (pthread_mutex_trylock(&client_mutex))
goto print_ls;
pthread_mutex_lock(&client_mutex);
list_for_each_entry(cl, &client_list, list) {
ret = print_client(cl, "client", pos, len);
if (ret >= len - pos) {
@ -4802,7 +4706,6 @@ static int dump_info(int *dump_len)
if (rv < 0)
return rv;
print_ls:
/*
* lockspaces with their action/resource/lock info
*/
@ -4999,13 +4902,13 @@ static void client_recv_action(struct client *cl)
act->path = strdup(path);
if (vg_name && strcmp(vg_name, "none"))
dm_strncpy(act->vg_name, vg_name, sizeof(act->vg_name));
strncpy(act->vg_name, vg_name, MAX_NAME);
if (vg_uuid && strcmp(vg_uuid, "none"))
memccpy(act->vg_uuid, vg_uuid, 0, 64);
strncpy(act->vg_uuid, vg_uuid, 64);
if (vg_sysid && strcmp(vg_sysid, "none"))
dm_strncpy(act->vg_sysid, vg_sysid, sizeof(act->vg_sysid));
strncpy(act->vg_sysid, vg_sysid, MAX_NAME);
str = daemon_request_str(req, "lv_name", NULL);
if (str && strcmp(str, "none"))
@ -5071,9 +4974,9 @@ skip_pvs_path:
dm_config_destroy(req.cft);
buffer_destroy(&req.buffer);
log_debug("recv %s[%d] cl %u %s %s \"%s\" flags %x",
log_debug("recv %s[%d] cl %u %s %s \"%s\" mode %s flags %x",
cl->name[0] ? cl->name : "client", cl->pid, cl->id,
op_mode_str(act->op, act->mode), rt_str(act->rt), act->vg_name, opts);
op_str(act->op), rt_str(act->rt), act->vg_name, mode_str(act->mode), opts);
if (lm == LD_LM_DLM && !lm_support_dlm()) {
log_debug("dlm not supported");
@ -5377,7 +5280,7 @@ static int match_dm_uuid(char *dm_uuid, char *lv_lock_uuid)
{
char buf1[64];
char buf2[64];
unsigned i, j;
int i, j;
memset(buf1, 0, sizeof(buf1));
memset(buf2, 0, sizeof(buf2));
@ -5461,7 +5364,7 @@ static int remove_inactive_lvs(struct list_head *vg_lockd)
goto next_dmname;
}
log_debug("adopt found active dm %s %s lv %s/%s",
log_debug("adopt remove_inactive dm name %s dm uuid %s vgname %s lvname %s",
names->name, dm_uuid, vgname, lvname);
if (!vgname || !lvname) {
@ -5482,7 +5385,8 @@ static int remove_inactive_lvs(struct list_head *vg_lockd)
continue;
/* Found an active LV in a lockd VG. */
log_debug("adopting %s", names->name);
log_debug("dm device %s adopt in vg %s lv %s",
names->name, ls->vg_name, r->name);
r->adopt = 1;
goto next_dmname;
}
@ -5719,7 +5623,7 @@ static void adopt_locks(void)
act->rt = LD_RT_VG;
act->lm_type = ls->lm_type;
act->client_id = INTERNAL_CLIENT_ID;
dm_strncpy(act->vg_name, ls->vg_name, sizeof(act->vg_name));
strncpy(act->vg_name, ls->vg_name, MAX_NAME);
memcpy(act->vg_uuid, ls->vg_uuid, 64);
memcpy(act->vg_args, ls->vg_args, MAX_ARGS);
act->host_id = ls->host_id;
@ -5754,6 +5658,7 @@ static void adopt_locks(void)
*/
while (count_start_done < count_start) {
sleep(1);
act = NULL;
pthread_mutex_lock(&client_mutex);
@ -5763,10 +5668,8 @@ static void adopt_locks(void)
}
pthread_mutex_unlock(&client_mutex);
if (!act) {
usleep(500000);
if (!act)
continue;
}
if (act->result < 0) {
log_error("adopt add lockspace failed vg %s %d", act->vg_name, act->result);
@ -5809,12 +5712,12 @@ static void adopt_locks(void)
act->op = LD_OP_LOCK;
act->rt = LD_RT_LV;
act->mode = r->adopt_mode;
act->flags = (LD_AF_ADOPT_ONLY | LD_AF_PERSISTENT);
act->flags = (LD_AF_ADOPT | LD_AF_PERSISTENT);
act->client_id = INTERNAL_CLIENT_ID;
act->lm_type = ls->lm_type;
dm_strncpy(act->vg_name, ls->vg_name, sizeof(act->vg_name));
dm_strncpy(act->lv_uuid, r->name, sizeof(act->lv_uuid));
dm_strncpy(act->lv_args, r->lv_args, sizeof(act->lv_args));
strncpy(act->vg_name, ls->vg_name, MAX_NAME);
strncpy(act->lv_uuid, r->name, MAX_NAME);
strncpy(act->lv_args, r->lv_args, MAX_ARGS);
log_debug("adopt lock for lv %s %s", act->vg_name, act->lv_uuid);
@ -5837,10 +5740,10 @@ static void adopt_locks(void)
act->op = LD_OP_LOCK;
act->rt = LD_RT_VG;
act->mode = LD_LK_SH;
act->flags = LD_AF_ADOPT_ONLY;
act->flags = LD_AF_ADOPT;
act->client_id = INTERNAL_CLIENT_ID;
act->lm_type = ls->lm_type;
dm_strncpy(act->vg_name, ls->vg_name, sizeof(act->vg_name));
strncpy(act->vg_name, ls->vg_name, MAX_NAME);
log_debug("adopt lock for vg %s", act->vg_name);
@ -5863,7 +5766,7 @@ static void adopt_locks(void)
act->op = LD_OP_LOCK;
act->rt = LD_RT_GL;
act->mode = LD_LK_SH;
act->flags = LD_AF_ADOPT_ONLY;
act->flags = LD_AF_ADOPT;
act->client_id = INTERNAL_CLIENT_ID;
act->lm_type = (gl_use_sanlock ? LD_LM_SANLOCK : LD_LM_DLM);
@ -5884,6 +5787,7 @@ static void adopt_locks(void)
*/
while (count_adopt_done < count_adopt) {
sleep(1);
act = NULL;
pthread_mutex_lock(&client_mutex);
@ -5893,16 +5797,14 @@ static void adopt_locks(void)
}
pthread_mutex_unlock(&client_mutex);
if (!act) {
usleep(200000);
if (!act)
continue;
}
/*
* lock adopt results
*/
if (act->result == -EADOPT_RETRY) {
if (act->result == -EUCLEAN) {
/*
* Adopt failed because the orphan has a different mode
* than initially requested. Repeat the lock-adopt operation
@ -5941,7 +5843,7 @@ static void adopt_locks(void)
free_action(act);
}
} else if (act->result == -EADOPT_NONE) {
} else if (act->result == -ENOENT) {
/*
* No orphan lock exists. This is common for GL/VG locks
* because they may not have been held when lvmlockd exited.
@ -6031,6 +5933,7 @@ static void adopt_locks(void)
/* Wait for the unlocks to complete. */
while (count_adopt_done < count_adopt) {
sleep(1);
act = NULL;
pthread_mutex_lock(&client_mutex);
@ -6040,10 +5943,8 @@ static void adopt_locks(void)
}
pthread_mutex_unlock(&client_mutex);
if (!act) {
usleep(200000);
if (!act)
continue;
}
if (act->result < 0)
log_error("adopt unlock error %d", act->result);
@ -6102,7 +6003,7 @@ static void process_listener(int poll_fd)
return;
if (!(cl = alloc_client())) {
if (close(fd))
if (!close(fd))
log_error("failed to close lockd poll fd");
return;
}
@ -6379,8 +6280,9 @@ int main(int argc, char *argv[])
.daemon_fini = NULL,
.daemon_main = main_loop,
};
daemon_host_id_file = NULL;
static const struct option long_options[] = {
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
{"version", no_argument, 0, 'V' },
{"test", no_argument, 0, 'T' },
@ -6398,8 +6300,6 @@ int main(int argc, char *argv[])
{0, 0, 0, 0 }
};
daemon_host_id_file = NULL;
while (1) {
int c;
int lm;

View File

@ -96,6 +96,7 @@ static int check_args_version(char *vg_args)
static int read_cluster_name(char *clustername)
{
static const char close_error_msg[] = "read_cluster_name: close_error %d";
char *n;
int fd;
int rv;
@ -114,19 +115,18 @@ static int read_cluster_name(char *clustername)
rv = read(fd, clustername, MAX_ARGS);
if (rv < 0) {
log_error("read_cluster_name: cluster name read error %d, check dlm_controld", fd);
goto out;
if (close(fd))
log_error(close_error_msg, fd);
return rv;
}
clustername[rv] = 0;
n = strstr(clustername, "\n");
if (n)
*n = '\0';
rv = 0;
out:
if (close(fd))
log_error("read_cluster_name: close_error %d", fd);
return rv;
log_error(close_error_msg, fd);
return 0;
}
#define MAX_VERSION 16
@ -226,14 +226,13 @@ static int get_local_nodeid(void)
{
struct dirent *de;
DIR *ls_dir;
char ls_comms_path[PATH_MAX] = { 0 };
char path[PATH_MAX] = { 0 };
FILE *file;
char ls_comms_path[PATH_MAX];
FILE *file = NULL;
char line[LOCK_LINE_MAX];
char *str1, *str2;
int rv = -1, val;
snprintf(ls_comms_path, sizeof(ls_comms_path), "%s", DLM_COMMS_PATH);
memset(ls_comms_path, 0, sizeof(ls_comms_path));
snprintf(ls_comms_path, PATH_MAX, "%s",DLM_COMMS_PATH);
if (!(ls_dir = opendir(ls_comms_path)))
return -ECONNREFUSED;
@ -241,41 +240,37 @@ static int get_local_nodeid(void)
while ((de = readdir(ls_dir))) {
if (de->d_name[0] == '.')
continue;
snprintf(path, sizeof(path), "%s/%s/local",
DLM_COMMS_PATH, de->d_name);
if (!(file = fopen(ls_comms_path, "r")))
memset(ls_comms_path, 0, sizeof(ls_comms_path));
snprintf(ls_comms_path, PATH_MAX, "%s/%s/local",
DLM_COMMS_PATH, de->d_name);
file = fopen(ls_comms_path, "r");
if (!file)
continue;
str1 = fgets(line, sizeof(line), file);
if (fclose(file))
log_sys_debug("fclose", path);
if (str1) {
if (fgets(line, LOCK_LINE_MAX, file)) {
fclose(file);
rv = sscanf(line, "%d", &val);
if ((rv == 1) && (val == 1 )) {
snprintf(path, sizeof(path), "%s/%s/nodeid",
DLM_COMMS_PATH, de->d_name);
if (!(file = fopen(path, "r")))
memset(ls_comms_path, 0, sizeof(ls_comms_path));
snprintf(ls_comms_path, PATH_MAX, "%s/%s/nodeid",
DLM_COMMS_PATH, de->d_name);
file = fopen(ls_comms_path, "r");
if (!file)
continue;
str2 = fgets(line, sizeof(line), file);
if (fclose(file))
log_sys_debug("fclose", path);
if (str2) {
if (fgets(line, LOCK_LINE_MAX, file)) {
rv = sscanf(line, "%d", &val);
if (rv == 1) {
if (closedir(ls_dir))
log_sys_debug("closedir", ls_comms_path);
fclose(file);
closedir(ls_dir);
return val;
}
}
}
}
fclose(file);
}
if (closedir(ls_dir))
log_sys_debug("closedir", ls_comms_path);
log_error("get_local_nodeid closedir error");
return rv;
}
@ -305,27 +300,20 @@ fail:
return rv;
}
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
if (daemon_test)
return 0;
if (adopt_only || adopt_ok) {
if (adopt)
lmd->dh = dlm_open_lockspace(ls->name);
if (!lmd->dh && adopt_ok)
lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
if (!lmd->dh)
log_error("add_lockspace_dlm adopt_only %d adopt_ok %d %s error",
adopt_only, adopt_ok, ls->name);
} else {
else
lmd->dh = dlm_new_lockspace(ls->name, 0600, DLM_LSFL_NEWEXCL);
if (!lmd->dh)
log_error("add_lockspace_dlm %s error", ls->name);
}
if (!lmd->dh) {
log_error("add_lockspace_dlm %s adopt %d error", ls->name, adopt);
free(lmd);
ls->lm_data = NULL;
return -1;
@ -393,7 +381,7 @@ static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int wit
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv < 0) {
log_error("%s:%s add_resource_dlm lock error %d", ls->name, r->name, rv);
log_error("S %s R %s add_resource_dlm lock error %d", ls->name, r->name, rv);
return rv;
}
out:
@ -417,7 +405,7 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
rv = dlm_ls_unlock_wait(lmd->dh, lksb->sb_lkid, 0, lksb);
if (rv < 0) {
log_error("%s:%s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
}
out:
free(rdd->vb);
@ -472,7 +460,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
goto fail;
}
log_debug("%s:%s adopt_dlm", ls->name, r->name);
log_debug("S %s R %s adopt_dlm", ls->name, r->name);
if (daemon_test)
return 0;
@ -481,29 +469,29 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
* dlm returns 0 for success, -EAGAIN if an orphan is
* found with another mode, and -ENOENT if no orphan.
*
* cast/bast/param are (void (*)(void*))1 because the kernel
* cast/bast/param are (void *)1 because the kernel
* returns errors if some are null.
*/
rv = dlm_ls_lockx(lmd->dh, mode, lksb, flags,
r->name, strlen(r->name), 0,
(void (*)(void*))1, (void (*)(void*))1, (void (*)(void*))1,
(void *)1, (void *)1, (void *)1,
NULL, NULL);
if (rv == -1 && (errno == EAGAIN)) {
log_debug("%s:%s adopt_dlm adopt mode %d try other mode",
log_debug("S %s R %s adopt_dlm adopt mode %d try other mode",
ls->name, r->name, ld_mode);
rv = -EADOPT_RETRY;
rv = -EUCLEAN;
goto fail;
}
if (rv == -1 && (errno == ENOENT)) {
log_debug("%s:%s adopt_dlm adopt mode %d no lock",
log_debug("S %s R %s adopt_dlm adopt mode %d no lock",
ls->name, r->name, ld_mode);
rv = -EADOPT_NONE;
rv = -ENOENT;
goto fail;
}
if (rv < 0) {
log_debug("%s:%s adopt_dlm mode %d flags %x error %d errno %d",
log_debug("S %s R %s adopt_dlm mode %d flags %x error %d errno %d",
ls->name, r->name, mode, flags, rv, errno);
goto fail;
}
@ -533,7 +521,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
*/
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int adopt_only, int adopt_ok)
struct val_blk *vb_out, int adopt)
{
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
@ -543,13 +531,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
int mode;
int rv;
if (adopt_ok) {
log_debug("%s:%s lock_dlm adopt_ok not supported", ls->name, r->name);
return -1;
}
if (adopt_only) {
log_debug("%s:%s lock_dlm adopt_only", ls->name, r->name);
if (adopt) {
/* When adopting, we don't follow the normal method
of acquiring a NL lock then converting it to the
desired mode. */
@ -578,7 +560,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
return -EINVAL;
}
log_debug("%s:%s lock_dlm", ls->name, r->name);
log_debug("S %s R %s lock_dlm", ls->name, r->name);
if (daemon_test) {
if (rdd->vb) {
@ -598,7 +580,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv == -1) {
log_debug("%s:%s lock_dlm acquire mode PR for %d rv %d",
log_debug("S %s R %s lock_dlm acquire mode PR for %d rv %d",
ls->name, r->name, mode, rv);
goto lockrv;
}
@ -611,17 +593,17 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
0, NULL, NULL, NULL);
lockrv:
if (rv == -1 && errno == EAGAIN) {
log_debug("%s:%s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
log_debug("S %s R %s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode);
return -EAGAIN;
}
if (rv < 0) {
log_error("%s:%s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
log_error("S %s R %s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno);
return -ELMERR;
}
if (rdd->vb) {
if (lksb->sb_flags & DLM_SBF_VALNOTVALID) {
log_debug("%s:%s lock_dlm VALNOTVALID", ls->name, r->name);
log_debug("S %s R %s lock_dlm VALNOTVALID", ls->name, r->name);
memset(rdd->vb, 0, sizeof(struct val_blk));
memset(vb_out, 0, sizeof(struct val_blk));
goto out;
@ -650,11 +632,11 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data;
struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data;
struct dlm_lksb *lksb = &rdd->lksb;
int mode;
uint32_t mode;
uint32_t flags = 0;
int rv;
log_debug("%s:%s convert_dlm", ls->name, r->name);
log_debug("S %s R %s convert_dlm", ls->name, r->name);
flags |= LKF_CONVERT;
flags |= LKF_NOQUEUE;
@ -668,16 +650,14 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
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",
log_debug("S %s R %s convert_dlm set r_version %u",
ls->name, r->name, r_version);
flags |= LKF_VALBLK;
}
if ((mode = to_dlm_mode(ld_mode)) < 0) {
log_error("lm_convert_dlm invalid mode %d", ld_mode);
return -EINVAL;
}
mode = to_dlm_mode(ld_mode);
if (daemon_test)
return 0;
@ -686,11 +666,11 @@ int lm_convert_dlm(struct lockspace *ls, struct resource *r,
0, NULL, NULL, NULL);
if (rv == -1 && errno == EAGAIN) {
/* FIXME: When does this happen? Should something different be done? */
log_error("%s:%s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
log_error("S %s R %s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode);
return -EAGAIN;
}
if (rv < 0) {
log_error("%s:%s convert_dlm error %d", ls->name, r->name, rv);
log_error("S %s R %s convert_dlm error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
return rv;
@ -740,7 +720,7 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
memcpy(rdd->vb, &vb_next, sizeof(struct val_blk));
memcpy(lksb->sb_lvbptr, &vb_next, sizeof(struct val_blk));
log_debug("%s:%s unlock_dlm vb old %x %x %u new %x %x %u",
log_debug("S %s R %s unlock_dlm vb old %x %x %u new %x %x %u",
ls->name, r->name,
le16_to_cpu(vb_prev.version),
le16_to_cpu(vb_prev.flags),
@ -749,12 +729,12 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
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);
log_debug("S %s R %s unlock_dlm vb unchanged", ls->name, r->name);
}
flags |= LKF_VALBLK;
} else {
log_debug("%s:%s unlock_dlm", ls->name, r->name);
log_debug("S %s R %s unlock_dlm", ls->name, r->name);
}
if (daemon_test)
@ -764,7 +744,7 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
r->name, strlen(r->name),
0, NULL, NULL, NULL);
if (rv < 0) {
log_error("%s:%s unlock_dlm error %d", ls->name, r->name, rv);
log_error("S %s R %s unlock_dlm error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
@ -799,6 +779,7 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
int lm_hosts_dlm(struct lockspace *ls, int notify)
{
static const char closedir_err_msg[] = "lm_hosts_dlm: closedir failed";
char ls_nodes_path[PATH_MAX];
struct dirent *de;
DIR *ls_dir;
@ -821,7 +802,7 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
}
if (closedir(ls_dir))
log_error("lm_hosts_dlm: closedir failed");
log_error(closedir_err_msg);
if (!count) {
log_error("lm_hosts_dlm found no nodes in %s", ls_nodes_path);
@ -838,10 +819,10 @@ int lm_hosts_dlm(struct lockspace *ls, int notify)
int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
{
static const char closedir_err_msg[] = "lm_get_lockspace_dlm: closedir failed";
struct lockspace *ls;
struct dirent *de;
DIR *ls_dir;
int ret = 0;
if (!(ls_dir = opendir(DLM_LOCKSPACES_PATH)))
return -ECONNREFUSED;
@ -854,20 +835,20 @@ int lm_get_lockspaces_dlm(struct list_head *ls_rejoin)
continue;
if (!(ls = alloc_lockspace())) {
ret = -ENOMEM;
goto out;
if (closedir(ls_dir))
log_error(closedir_err_msg);
return -ENOMEM;
}
ls->lm_type = LD_LM_DLM;
dm_strncpy(ls->name, de->d_name, sizeof(ls->name));
dm_strncpy(ls->vg_name, ls->name + strlen(LVM_LS_PREFIX), sizeof(ls->vg_name));
strncpy(ls->name, de->d_name, MAX_NAME);
strncpy(ls->vg_name, ls->name + strlen(LVM_LS_PREFIX), MAX_NAME);
list_add_tail(&ls->list, ls_rejoin);
}
out:
if (closedir(ls_dir))
log_error("lm_get_lockspace_dlm: closedir failed");
return ret;
if (closedir(ls_dir))
log_error(closedir_err_msg);
return 0;
}
int lm_is_running_dlm(void)
@ -897,7 +878,7 @@ int lm_refresh_lv_start_dlm(struct action *act)
int rv;
/* split /dev/vgname/lvname into vgname and lvname strings */
dm_strncpy(path, act->path, sizeof(path));
strncpy(path, act->path, PATH_MAX-1);
/* skip past dev */
if (!(p = strchr(path + 1, '/')))

View File

@ -391,7 +391,7 @@ int lm_prepare_lockspace_idm(struct lockspace *ls)
return 0;
}
int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok)
int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
{
char killpath[IDM_FAILURE_PATH_LEN];
char killargs[IDM_FAILURE_ARGS_LEN];
@ -530,7 +530,7 @@ static int to_idm_mode(int ld_mode)
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)
int adopt)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;

View File

@ -107,12 +107,11 @@ struct client {
#define LD_AF_SEARCH_LS 0x00000200
#define LD_AF_WAIT_STARTING 0x00001000
#define LD_AF_DUP_GL_LS 0x00002000
#define LD_AF_ADOPT 0x00010000 /* adopt ok but not required */
#define LD_AF_ADOPT 0x00010000
#define LD_AF_WARN_GL_REMOVED 0x00020000
#define LD_AF_LV_LOCK 0x00040000
#define LD_AF_LV_UNLOCK 0x00080000
#define LD_AF_SH_EXISTS 0x00100000
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
/*
* Number of times to repeat a lock request after
@ -364,8 +363,6 @@ void log_level(int level, const char *fmt, ...) __attribute__((format(printf, 2
#define log_debug(fmt, args...) log_level(LOG_DEBUG, fmt, ##args)
#define log_error(fmt, args...) log_level(LOG_ERR, fmt, ##args)
#define log_warn(fmt, args...) log_level(LOG_WARNING, fmt, ##args)
#define log_sys_debug(x, y) \
log_debug("%s: %s failed: %s", y, x, strerror(errno))
struct lockspace *alloc_lockspace(void);
int lockspaces_empty(void);
@ -394,11 +391,11 @@ static inline const char *mode_str(int x)
int lm_init_vg_dlm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_dlm(struct lockspace *ls);
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok);
int lm_add_lockspace_dlm(struct lockspace *ls, int adopt);
int lm_purge_locks_dlm(struct lockspace *ls);
int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg);
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int adopt_only, int adopt_ok);
struct val_blk *vb_out, int adopt);
int lm_convert_dlm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_dlm(struct lockspace *ls, struct resource *r,
@ -428,7 +425,7 @@ static inline int lm_prepare_lockspace_dlm(struct lockspace *ls)
return -1;
}
static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt_only, int adopt_ok)
static inline int lm_add_lockspace_dlm(struct lockspace *ls, int adopt)
{
return -1;
}
@ -444,7 +441,7 @@ static inline int lm_rem_lockspace_dlm(struct lockspace *ls, int free_vg)
}
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)
struct val_blk *vb_out, int adopt)
{
return -1;
}
@ -510,11 +507,10 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name, char *vg_arg
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);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok);
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt);
int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg);
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry,
int adopt_only, int adopt_ok);
struct val_blk *vb_out, int *retry, int adopt);
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,
@ -561,7 +557,7 @@ static inline int lm_prepare_lockspace_sanlock(struct lockspace *ls)
return -1;
}
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok)
static inline int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt)
{
return -1;
}
@ -572,8 +568,7 @@ static inline int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
}
static inline int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry,
int adopt_only, int adopt_ok)
struct val_blk *vb_out, int *retry, int adopt)
{
return -1;
}
@ -647,11 +642,11 @@ static inline int lm_support_sanlock(void)
int lm_data_size_idm(void);
int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
int lm_prepare_lockspace_idm(struct lockspace *ls);
int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok);
int lm_add_lockspace_idm(struct lockspace *ls, int adopt);
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg);
int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
int adopt_only, int adopt_ok);
int adopt);
int lm_convert_idm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version);
int lm_unlock_idm(struct lockspace *ls, struct resource *r,
@ -684,7 +679,7 @@ static inline int lm_prepare_lockspace_idm(struct lockspace *ls)
return -1;
}
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt_only, int adopt_ok)
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
{
return -1;
}
@ -696,7 +691,7 @@ static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
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)
int adopt)
{
return -1;
}

View File

@ -24,6 +24,21 @@
#include "sanlock_admin.h"
#include "sanlock_resource.h"
/* FIXME: these are copied from sanlock.h only until
an updated version of sanlock is available with them. */
#define SANLK_RES_ALIGN1M 0x00000010
#define SANLK_RES_ALIGN2M 0x00000020
#define SANLK_RES_ALIGN4M 0x00000040
#define SANLK_RES_ALIGN8M 0x00000080
#define SANLK_RES_SECTOR512 0x00000100
#define SANLK_RES_SECTOR4K 0x00000200
#define SANLK_LSF_ALIGN1M 0x00000010
#define SANLK_LSF_ALIGN2M 0x00000020
#define SANLK_LSF_ALIGN4M 0x00000040
#define SANLK_LSF_ALIGN8M 0x00000080
#define SANLK_LSF_SECTOR512 0x00000100
#define SANLK_LSF_SECTOR4K 0x00000200
#include <stddef.h>
#include <poll.h>
#include <errno.h>
@ -214,13 +229,13 @@ static uint64_t daemon_test_lv_count;
/*
* Copy a null-terminated string "str" into a fixed
* size struct field "buf" which is not null terminated.
* (ATM SANLK_NAME_LEN is only 48 bytes.
* Use memccpy() instead of strncpy().
* size (SANLK_NAME_LEN) struct field "buf" which is
* not null terminated.
*/
static void strcpy_name_len(char *buf, const char *str, size_t len)
static void strcpy_name_len(char *buf, char *str, int len)
{
memccpy(buf, str, 0, len);
/* coverity[buffer_size_warning] */
strncpy(buf, str, SANLK_NAME_LEN);
}
static int lock_lv_name_from_args(char *vg_args, char *lock_lv_name)
@ -516,6 +531,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
memset(&ss, 0, sizeof(ss));
memset(&rd, 0, sizeof(rd));
memset(&disk, 0, sizeof(disk));
memset(lock_lv_name, 0, sizeof(lock_lv_name));
memset(lock_args_version, 0, sizeof(lock_args_version));
if (!vg_args || !vg_args[0] || !strcmp(vg_args, "none")) {
@ -527,7 +543,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
/* see comment above about input vg_args being only lock_lv_name */
dm_strncpy(lock_lv_name, vg_args, sizeof(lock_lv_name));
snprintf(lock_lv_name, MAX_ARGS, "%s", vg_args);
if (strlen(lock_lv_name) + strlen(lock_args_version) + 2 > MAX_ARGS)
return -EARGS;
@ -602,7 +618,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
gl_name = R_NAME_GL;
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, gl_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)gl_name, SANLK_NAME_LEN);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
rd.rs.num_disks = 1;
@ -617,7 +633,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, R_NAME_VG, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)R_NAME_VG, SANLK_NAME_LEN);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
rd.rs.num_disks = 1;
@ -632,7 +648,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
}
if (!strcmp(gl_name, R_NAME_GL))
dm_strncpy(gl_lsname_sanlock, ls_name, sizeof(gl_lsname_sanlock));
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
if (rv >= MAX_ARGS)
@ -652,7 +668,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, "#unused", SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)"#unused", SANLK_NAME_LEN);
offset = align_size * LV_LOCK_BEGIN;
@ -999,16 +1015,16 @@ int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
struct sanlk_resource *rs = &rds->rs;
int rv;
log_debug("%s:%s free_lv_san", ls->name, r->name);
log_debug("S %s R %s free_lv_san", ls->name, r->name);
if (daemon_test)
return 0;
strcpy_name_len(rs->name, "#unused", SANLK_NAME_LEN);
strcpy_name_len(rs->name, (char *)"#unused", SANLK_NAME_LEN);
rv = sanlock_write_resource(rs, 0, 0, 0);
if (rv < 0) {
log_error("%s:%s free_lv_san write error %d",
log_error("S %s R %s free_lv_san write error %d",
ls->name, r->name, rv);
}
@ -1039,10 +1055,10 @@ int lm_ex_disable_gl_sanlock(struct lockspace *ls)
memset(&rd2, 0, sizeof(rd2));
strcpy_name_len(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd1.rs.name, R_NAME_GL, SANLK_NAME_LEN);
strcpy_name_len(rd1.rs.name, (char *)R_NAME_GL, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.name, R_NAME_GL_DISABLED, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.name, (char *)R_NAME_GL_DISABLED, SANLK_NAME_LEN);
rd1.rs.num_disks = 1;
memcpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
@ -1108,7 +1124,7 @@ int lm_able_gl_sanlock(struct lockspace *ls, int enable)
memset(&rd, 0, sizeof(rd));
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, gl_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)gl_name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
@ -1128,7 +1144,7 @@ out:
ls->sanlock_gl_enabled = enable;
if (enable)
dm_strncpy(gl_lsname_sanlock, ls->name, sizeof(gl_lsname_sanlock));
strncpy(gl_lsname_sanlock, ls->name, MAX_NAME);
if (!enable && !strcmp(gl_lsname_sanlock, ls->name))
memset(gl_lsname_sanlock, 0, sizeof(gl_lsname_sanlock));
@ -1319,7 +1335,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
struct stat st;
struct lm_sanlock *lms = NULL;
char lock_lv_name[MAX_ARGS+1];
char lsname[SANLK_NAME_LEN + 1] = { 0 };
char lsname[SANLK_NAME_LEN + 1];
char disk_path[SANLK_PATH_LEN];
char killpath[SANLK_PATH_LEN];
char killargs[SANLK_PATH_LEN];
@ -1400,7 +1416,8 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
goto fail;
}
dm_strncpy(lsname, ls->name, sizeof(lsname));
memset(lsname, 0, sizeof(lsname));
strncpy(lsname, ls->name, SANLK_NAME_LEN);
memcpy(lms->ss.name, lsname, SANLK_NAME_LEN);
lms->ss.host_id_disk.offset = 0;
@ -1501,7 +1518,7 @@ fail:
return ret;
}
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok)
int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt)
{
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
int rv;
@ -1512,15 +1529,11 @@ int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok)
}
rv = sanlock_add_lockspace_timeout(&lms->ss, 0, sanlock_io_timeout);
if (rv == -EEXIST && (adopt_ok || adopt_only)) {
if (rv == -EEXIST && adopt) {
/* We could alternatively just skip the sanlock call for adopt. */
log_debug("S %s add_lockspace_san adopt found ls", ls->name);
goto out;
}
if ((rv != -EEXIST) && adopt_only) {
log_error("S %s add_lockspace_san add_lockspace adopt_only not found", ls->name);
goto fail;
}
if (rv < 0) {
/* retry for some errors? */
log_error("S %s add_lockspace_san add_lockspace error %d", ls->name, rv);
@ -1563,10 +1576,8 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
goto out;
rv = sanlock_rem_lockspace(&lms->ss, 0);
if (rv < 0) {
if (rv < 0)
log_error("S %s rem_lockspace_san error %d", ls->name, rv);
return rv;
}
if (free_vg) {
/*
@ -1575,7 +1586,7 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
* This shouldn't be generally necessary, but there may some races
* between nodes starting and removing a vg which this could help.
*/
strcpy_name_len(lms->ss.name, "#unused", SANLK_NAME_LEN);
strcpy_name_len(lms->ss.name, (char *)"#unused", SANLK_NAME_LEN);
rv = sanlock_write_lockspace(&lms->ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
@ -1616,17 +1627,12 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
/* LD_RT_LV offset is set in each lm_lock call from lv_args. */
/*
* Disable sanlock lvb since lock versions are not currently used for
* anything, and it's nice to avoid the extra i/o used for lvb's.
*/
#if LVMLOCKD_USE_SANLOCK_LVB
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
rds->vb = zalloc(sizeof(struct val_blk));
if (!rds->vb)
return -ENOMEM;
}
#endif
return 0;
}
@ -1635,16 +1641,16 @@ int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r)
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
/* FIXME: assert r->mode == UN or unlock if it's not? */
#ifdef LVMLOCKD_USE_SANLOCK_LVB
free(rds->vb);
#endif
memset(rds, 0, sizeof(struct rd_sanlock));
r->lm_init = 0;
return 0;
}
int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, int *retry, int adopt_only, int adopt_ok)
struct val_blk *vb_out, int *retry, int adopt)
{
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
@ -1684,20 +1690,20 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
rv = check_args_version(r->lv_args, LV_LOCK_ARGS_MAJOR);
if (rv < 0) {
log_error("%s:%s lock_san wrong lv_args version %s",
log_error("S %s R %s lock_san wrong lv_args version %s",
ls->name, r->name, r->lv_args);
return rv;
}
rv = lock_lv_offset_from_args(r->lv_args, &lock_lv_offset);
if (rv < 0) {
log_error("%s:%s lock_san lv_offset_from_args error %d %s",
log_error("S %s R %s lock_san lv_offset_from_args error %d %s",
ls->name, r->name, rv, r->lv_args);
return rv;
}
if (!added && (rds->rs.disks[0].offset != lock_lv_offset)) {
log_debug("%s:%s lock_san offset old %llu new %llu",
log_debug("S %s R %s lock_san offset old %llu new %llu",
ls->name, r->name,
(unsigned long long)rds->rs.disks[0].offset,
(unsigned long long)lock_lv_offset);
@ -1723,7 +1729,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
rs->flags |= SANLK_RES_PERSISTENT;
log_debug("%s:%s lock_san %s at %s:%llu",
log_debug("S %s R %s lock_san %s at %s:%llu",
ls->name, r->name, mode_str(ld_mode), rs->disks[0].path,
(unsigned long long)rs->disks[0].offset);
@ -1738,10 +1744,8 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
if (rds->vb)
flags |= SANLK_ACQUIRE_LVB;
if (adopt_only)
if (adopt)
flags |= SANLK_ACQUIRE_ORPHAN_ONLY;
if (adopt_ok)
flags |= SANLK_ACQUIRE_ORPHAN;
/*
* Don't block waiting for a failed lease to expire since it causes
@ -1767,7 +1771,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
* a shared lock but the lock is held ex by another host.
* There's no point in retrying this case, just return an error.
*/
log_debug("%s:%s lock_san acquire mode %d rv EAGAIN", ls->name, r->name, ld_mode);
log_debug("S %s R %s lock_san acquire mode %d rv EAGAIN", ls->name, r->name, ld_mode);
*retry = 0;
return -EAGAIN;
}
@ -1781,31 +1785,31 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
* The lvm command will see this error, refresh the lvmlock
* lv, and try again.
*/
log_debug("%s:%s lock_san acquire offset %llu rv EMSGSIZE",
log_debug("S %s R %s lock_san acquire offset %llu rv EMSGSIZE",
ls->name, r->name, (unsigned long long)rs->disks[0].offset);
*retry = 0;
return -EMSGSIZE;
}
if ((adopt_only || adopt_ok) && (rv == -EUCLEAN)) {
if (adopt && (rv == -EUCLEAN)) {
/*
* The orphan lock exists but in a different mode than we asked
* for, so the caller should try again with the other mode.
*/
log_debug("%s:%s lock_san adopt mode %d try other mode",
log_debug("S %s R %s lock_san adopt mode %d try other mode",
ls->name, r->name, ld_mode);
*retry = 0;
return -EADOPT_RETRY;
return -EUCLEAN;
}
if (adopt_only && (rv == -ENOENT)) {
if (adopt && (rv == -ENOENT)) {
/*
* No orphan lock exists.
*/
log_debug("%s:%s lock_san adopt_only mode %d no orphan found",
log_debug("S %s R %s lock_san adopt mode %d no orphan found",
ls->name, r->name, ld_mode);
*retry = 0;
return -EADOPT_NONE;
return -ENOENT;
}
if (rv == SANLK_ACQUIRE_IDLIVE || rv == SANLK_ACQUIRE_OWNED || rv == SANLK_ACQUIRE_OTHER) {
@ -1824,7 +1828,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
* so if requesting a sh lock, retry a couple times,
* otherwise don't.
*/
log_debug("%s:%s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
*retry = (ld_mode == LD_LK_SH) ? 1 : 0;
return -EAGAIN;
}
@ -1834,7 +1838,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
* sanlock got an i/o timeout when trying to acquire the
* lease on disk.
*/
log_debug("%s:%s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
*retry = 0;
return -EAGAIN;
}
@ -1844,7 +1848,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
* There was contention with another host for the lease,
* and we lost.
*/
log_debug("%s:%s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
*retry = 0;
return -EAGAIN;
}
@ -1863,19 +1867,19 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
* command can print an different error indicating that the
* owner of the lease is in the process of expiring?
*/
log_debug("%s:%s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
log_debug("S %s R %s lock_san acquire mode %d rv %d", ls->name, r->name, ld_mode, rv);
*retry = 0;
return -EAGAIN;
}
if (rv < 0) {
log_error("%s:%s lock_san acquire error %d",
log_error("S %s R %s lock_san acquire error %d",
ls->name, r->name, rv);
/* if the gl has been disabled, remove and free the gl resource */
if ((rv == SANLK_LEADER_RESOURCE) && (r->type == LD_RT_GL)) {
if (!lm_gl_is_enabled(ls)) {
log_error("%s:%s lock_san gl has been disabled",
log_error("S %s R %s lock_san gl has been disabled",
ls->name, r->name);
if (!strcmp(gl_lsname_sanlock, ls->name))
memset(gl_lsname_sanlock, 0, sizeof(gl_lsname_sanlock));
@ -1888,7 +1892,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
/* sanlock gets i/o errors trying to read/write the leases. */
if (rv == -EIO)
return -ELOCKIO;
rv = -ELOCKIO;
/*
* The sanlock lockspace can disappear if the lease storage fails,
@ -1897,11 +1901,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
* stop and free the lockspace.
*/
if (rv == -ENOSPC)
return -ELOCKIO;
/* The request conflicted with an orphan lock. */
if (rv == -EUCLEAN)
return -EORPHAN;
rv = -ELOCKIO;
/*
* generic error number for sanlock errors that we are not
@ -1917,7 +1917,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
if (rds->vb) {
rv = sanlock_get_lvb(0, rs, (char *)&vb, sizeof(vb));
if (rv < 0) {
log_error("%s:%s lock_san get_lvb error %d", ls->name, r->name, rv);
log_error("S %s R %s lock_san get_lvb error %d", ls->name, r->name, rv);
memset(rds->vb, 0, sizeof(struct val_blk));
memset(vb_out, 0, sizeof(struct val_blk));
/* the lock is still acquired, the vb values considered invalid */
@ -1952,7 +1952,7 @@ int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
uint32_t flags = 0;
int rv;
log_debug("%s:%s convert_san %s to %s",
log_debug("S %s R %s convert_san %s to %s",
ls->name, r->name, mode_str(r->mode), mode_str(ld_mode));
if (daemon_test)
@ -1967,12 +1967,12 @@ int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
rds->vb->r_version = cpu_to_le32(r_version);
memcpy(&vb, rds->vb, sizeof(vb));
log_debug("%s:%s convert_san set r_version %u",
log_debug("S %s R %s convert_san set r_version %u",
ls->name, r->name, r_version);
rv = sanlock_set_lvb(0, rs, (char *)&vb, sizeof(vb));
if (rv < 0) {
log_error("%s:%s convert_san set_lvb error %d",
log_error("S %s R %s convert_san set_lvb error %d",
ls->name, r->name, rv);
return -ELMERR;
}
@ -2011,10 +2011,10 @@ int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
case SANLK_DBLOCK_LVER:
case SANLK_DBLOCK_MBAL:
/* expected errors from known/normal cases like lock contention or io timeouts */
log_debug("%s:%s convert_san error %d", ls->name, r->name, rv);
log_debug("S %s R %s convert_san error %d", ls->name, r->name, rv);
return -EAGAIN;
default:
log_error("%s:%s convert_san convert error %d", ls->name, r->name, rv);
log_error("S %s R %s convert_san convert error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
@ -2032,7 +2032,7 @@ static int release_rename(struct lockspace *ls, struct resource *r)
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
int rv;
log_debug("%s:%s release rename", ls->name, r->name);
log_debug("S %s R %s release rename", ls->name, r->name);
res_args = malloc(2 * sizeof(struct sanlk_resource *));
if (!res_args)
@ -2044,14 +2044,14 @@ static int release_rename(struct lockspace *ls, struct resource *r)
res1 = (struct sanlk_resource *)&rd1;
res2 = (struct sanlk_resource *)&rd2;
strcpy_name_len(res2->name, "invalid_removed", SANLK_NAME_LEN);
strcpy_name_len(res2->name, (char *)"invalid_removed", SANLK_NAME_LEN);
res_args[0] = res1;
res_args[1] = res2;
rv = sanlock_release(lms->sock, -1, SANLK_REL_RENAME, 2, res_args);
if (rv < 0) {
log_error("%s:%s unlock_san release rename error %d", ls->name, r->name, rv);
log_error("S %s R %s unlock_san release rename error %d", ls->name, r->name, rv);
rv = -ELMERR;
}
@ -2080,7 +2080,7 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
struct val_blk vb;
int rv;
log_debug("%s:%s unlock_san %s r_version %u flags %x",
log_debug("S %s R %s unlock_san %s r_version %u flags %x",
ls->name, r->name, mode_str(r->mode), r_version, lmu_flags);
if (daemon_test) {
@ -2102,12 +2102,12 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
rds->vb->r_version = cpu_to_le32(r_version);
memcpy(&vb, rds->vb, sizeof(vb));
log_debug("%s:%s unlock_san set r_version %u",
log_debug("S %s R %s unlock_san set r_version %u",
ls->name, r->name, r_version);
rv = sanlock_set_lvb(0, rs, (char *)&vb, sizeof(vb));
if (rv < 0) {
log_error("%s:%s unlock_san set_lvb error %d",
log_error("S %s R %s unlock_san set_lvb error %d",
ls->name, r->name, rv);
return -ELMERR;
}
@ -2124,7 +2124,7 @@ int lm_unlock_sanlock(struct lockspace *ls, struct resource *r,
rv = sanlock_release(lms->sock, -1, 0, 1, &rs);
if (rv < 0)
log_error("%s:%s unlock_san release error %d", ls->name, r->name, rv);
log_error("S %s R %s unlock_san release error %d", ls->name, r->name, rv);
/*
* sanlock may return an error here if it fails to release the lease on

View File

@ -32,11 +32,11 @@ LDFLAGS += $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS)
LIBS += $(DAEMON_LIBS) $(PTHREAD_LIBS)
lvmpolld: $(OBJECTS) $(top_builddir)/libdaemon/server/libdaemonserver.a $(INTERNAL_LIBS)
$(SHOW) " [CC] $@"
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
install_lvmpolld: lvmpolld
$(SHOW) " [INSTALL] $<"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(sbindir)/$(<F)
install_lvm2: install_lvmpolld

View File

@ -19,7 +19,7 @@
#define MIN_ARGV_SIZE 8
static const char *const _polling_ops[] = {
static const char *const polling_ops[] = {
[PVMOVE] = LVMPD_REQ_PVMOVE,
[CONVERT] = LVMPD_REQ_CONVERT,
[MERGE] = LVMPD_REQ_MERGE,
@ -28,7 +28,7 @@ static const char *const _polling_ops[] = {
const char *polling_op(enum poll_type type)
{
return type < POLL_TYPE_MAX ? _polling_ops[type] : "<undefined>";
return type < POLL_TYPE_MAX ? polling_ops[type] : "<undefined>";
}
static int add_to_cmd_arr(const char ***cmdargv, const char *str, unsigned *ind)
@ -81,7 +81,7 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary,
/* one of: "convert", "pvmove", "merge", "merge_thin" */
if (!add_to_cmd_arr(&cmd_argv, "--polloperation", &i) ||
!add_to_cmd_arr(&cmd_argv, _polling_ops[pdlv->type], &i))
!add_to_cmd_arr(&cmd_argv, polling_ops[pdlv->type], &i))
goto err;
/* vg/lv name */

View File

@ -781,7 +781,7 @@ struct log_line_baton {
const char *prefix;
};
static daemon_handle _lvmpolld = { .error = 0 };
daemon_handle _lvmpolld = { .error = 0 };
static daemon_handle _lvmpolld_open(const char *socket)
{
@ -867,14 +867,14 @@ enum action_index {
ACTION_MAX /* keep at the end */
};
static const action_fn_t actions[ACTION_MAX] = { [ACTION_DUMP] = action_dump };
static int _make_action(enum action_index idx, void *args)
{
static const action_fn_t _actions[ACTION_MAX] = { [ACTION_DUMP] = action_dump };
return idx < ACTION_MAX ? _actions[idx](args) : 0;
return idx < ACTION_MAX ? actions[idx](args) : 0;
}
static int _lvmpolld_client(const char *socket, enum action_index action)
static int _lvmpolld_client(const char *socket, unsigned action)
{
int r;
@ -892,9 +892,10 @@ static int _lvmpolld_client(const char *socket, enum action_index action)
return r ? EXIT_SUCCESS : EXIT_FAILURE;
}
static const struct option _long_options[] = {
static int action_idx = ACTION_MAX;
static struct option long_options[] = {
/* Have actions always at the beginning of the array. */
{"dump", no_argument, 0, ACTION_DUMP }, /* or an option_index ? */
{"dump", no_argument, &action_idx, ACTION_DUMP }, /* or an option_index ? */
/* other options */
{"binary", required_argument, 0, 'B' },
@ -913,7 +914,7 @@ int main(int argc, char *argv[])
int opt;
int option_index = 0;
int client = 0, server = 0;
enum action_index action = ACTION_MAX;
unsigned action = ACTION_MAX;
struct timespec timeout;
daemon_idle di = { .ptimeout = &timeout };
struct lvmpolld_state ls = { .log_config = "" };
@ -929,16 +930,16 @@ int main(int argc, char *argv[])
.socket_path = getenv("LVM_LVMPOLLD_SOCKET") ?: LVMPOLLD_SOCKET,
};
while ((opt = getopt_long(argc, argv, "fhVl:p:s:B:t:", _long_options, &option_index)) != -1) {
while ((opt = getopt_long(argc, argv, "fhVl:p:s:B:t:", long_options, &option_index)) != -1) {
switch (opt) {
case 0 :
if (action != ACTION_MAX) {
if (action < ACTION_MAX) {
fprintf(stderr, "Can't perform more actions. Action already requested: %s\n",
_long_options[action].name);
long_options[action].name);
_usage(argv[0], stderr);
exit(EXIT_FAILURE);
}
action = ACTION_DUMP;
action = action_idx;
client = 1;
break;
case '?':

View File

@ -45,18 +45,18 @@ struct lvmpolld_lv {
* accessing following vars doesn't
* require struct lvmpolld_lv lock
*/
struct lvmpolld_state *ls;
enum poll_type type;
const char *lvid;
const char *lvmpolld_id;
const char *devicesfile;
const char *lvname; /* full vg/lv name */
unsigned pdtimeout; /* in seconds */
const char *sinterval;
const char *lvm_system_dir_env;
struct lvmpolld_store *pdst;
const char **cmdargv;
const char **cmdenvp;
struct lvmpolld_state *const ls;
const enum poll_type type;
const char *const lvid;
const char *const lvmpolld_id;
const char *const devicesfile;
const char *const lvname; /* full vg/lv name */
const unsigned pdtimeout; /* in seconds */
const char *const sinterval;
const char *const lvm_system_dir_env;
struct lvmpolld_store *const pdst;
const char *const *cmdargv;
const char *const *cmdenvp;
/* only used by write */
pid_t cmd_pid;
@ -66,7 +66,7 @@ struct lvmpolld_lv {
/* block of shared variables protected by lock */
struct lvmpolld_cmd_stat cmd_state;
unsigned init_rq_count; /* for debugging purposes only */
unsigned init_rq_count; /* for debuging purposes only */
unsigned polling_finished:1; /* no more updates */
unsigned error:1; /* unrecoverable error occured in lvmpolld */
};

View File

@ -44,10 +44,10 @@ CLEAN_TARGETS += $(DEVICE_MAPPER_DEPENDS) $(DEVICE_MAPPER_OBJECTS) \
#$(DEVICE_MAPPER_OBJECTS): INCLUDES+=$(VDO_INCLUDES)
$(DEVICE_MAPPER_TARGET): $(DEVICE_MAPPER_OBJECTS)
$(SHOW) " [AR] $@"
@echo " [AR] $@"
$(Q) $(RM) $@
$(Q) $(AR) rsv $@ $(DEVICE_MAPPER_OBJECTS) > /dev/null
ifeq ("$(USE_TRACKING)","yes")
ifeq ("$(DEPENDS)","yes")
-include $(DEVICE_MAPPER_DEPENDS)
endif

View File

@ -175,11 +175,12 @@ struct dm_names {
struct dm_active_device {
struct dm_list list;
dev_t devno;
const char *name; /* device name */
int major;
int minor;
char *name; /* device name */
uint32_t event_nr; /* valid when DM_DEVICE_LIST_HAS_EVENT_NR is set */
const char *uuid; /* valid uuid when DM_DEVICE_LIST_HAS_UUID is set */
char *uuid; /* valid uuid when DM_DEVICE_LIST_HAS_UUID is set */
};
struct dm_versions {
@ -229,6 +230,13 @@ struct dm_names *dm_task_get_names(struct dm_task *dmt);
#define DM_DEVICE_LIST_HAS_UUID 2
int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
unsigned *devs_features);
/*
* -1: no idea about uuid (not provided by DM_DEVICE_LIST ioctl)
* 0: uuid not present
* 1: listed and dm_active_device will be set for not NULL pointer
*/
int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid,
const struct dm_active_device **dev);
/* Release all associated memory with list of active DM devices */
void dm_device_list_destroy(struct dm_list **devs_list);
@ -1867,7 +1875,6 @@ const void *dm_report_value_cache_get(struct dm_report *rh, const char *name);
#define DM_REPORT_OUTPUT_FIELD_UNQUOTED 0x00000010
#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS 0x00000020
#define DM_REPORT_OUTPUT_MULTIPLE_TIMES 0x00000040
#define DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS 0x00000080
struct dm_report *dm_report_init(uint32_t *report_types,
const struct dm_report_object_type *types,
@ -2236,7 +2243,7 @@ struct dm_pool *dm_config_memory(struct dm_config_tree *cft);
int dm_cookie_supported(void);
/*
* Udev synchronization functions.
* Udev synchronisation functions.
*/
void dm_udev_set_sync_support(int sync_with_udev);
int dm_udev_get_sync_support(void);

View File

@ -87,8 +87,10 @@ static int _version_checked = 0;
static int _version_ok = 1;
static unsigned _ioctl_buffer_double_factor = 0;
const int _dm_compat = 0;
/* *INDENT-OFF* */
static const struct cmd_data _cmd_data_v4[] = {
static struct cmd_data _cmd_data_v4[] = {
{"create", DM_DEV_CREATE, {4, 0, 0}},
{"reload", DM_TABLE_LOAD, {4, 0, 0}},
{"remove", DM_DEV_REMOVE, {4, 0, 0}},
@ -198,7 +200,6 @@ static int _get_proc_number(const char *file, const char *name,
char *line = NULL;
size_t len;
uint32_t num;
unsigned blocksection = (strcmp(file, PROC_DEVICES) == 0) ? 0 : 1;
if (!(fl = fopen(file, "r"))) {
log_sys_error("fopen", file);
@ -206,9 +207,7 @@ static int _get_proc_number(const char *file, const char *name,
}
while (getline(&line, &len, fl) != -1) {
if (!blocksection && (line[0] == 'B'))
blocksection = 1;
else if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
if (!strcmp(name, nm)) {
if (number) {
*number = num;
@ -248,16 +247,6 @@ static int _control_device_number(uint32_t *major, uint32_t *minor)
return 1;
}
static int _control_unlink(const char *control)
{
if (unlink(control) && (errno != ENOENT)) {
log_sys_error("unlink", control);
return -1;
}
return 0;
}
/*
* Returns 1 if it exists on returning; 0 if it doesn't; -1 if it's wrong.
*/
@ -273,7 +262,10 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
if (!S_ISCHR(buf.st_mode)) {
log_verbose("%s: Wrong inode type", control);
return _control_unlink(control);
if (!unlink(control))
return 0;
log_sys_error("unlink", control);
return -1;
}
if (major && buf.st_rdev != MKDEV(major, minor)) {
@ -281,7 +273,10 @@ static int _control_exists(const char *control, uint32_t major, uint32_t minor)
"(%u, %u)", control,
MAJOR(buf.st_mode), MINOR(buf.st_mode),
major, minor);
return _control_unlink(control);
if (!unlink(control))
return 0;
log_sys_error("unlink", control);
return -1;
}
return 1;
@ -317,13 +312,8 @@ static int _create_control(const char *control, uint32_t major, uint32_t minor)
old_umask = umask(DM_CONTROL_NODE_UMASK);
if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
MKDEV(major, minor)) < 0) {
if (errno != EEXIST) {
log_sys_error("mknod", control);
ret = 0;
} else if (_control_exists(control, major, minor) != 1) {
stack; /* Invalid control node created by parallel command ? */
ret = 0;
}
log_sys_error("mknod", control);
ret = 0;
}
umask(old_umask);
(void) dm_prepare_selinux_context(NULL, 0);
@ -409,7 +399,7 @@ static void _close_control_fd(void)
{
if (_control_fd != -1) {
if (close(_control_fd) < 0)
log_sys_debug("close", "_control_fd");
log_sys_error("close", "_control_fd");
_control_fd = -1;
}
}
@ -598,9 +588,23 @@ int dm_check_version(void)
_version_checked = 1;
if (_check_version(dmversion, sizeof(dmversion), 0))
if (_check_version(dmversion, sizeof(dmversion), _dm_compat))
return 1;
if (!_dm_compat)
goto_bad;
log_verbose("device-mapper ioctl protocol version %u failed. "
"Trying protocol version 1.", _dm_version);
_dm_version = 1;
if (_check_version(dmversion, sizeof(dmversion), 0)) {
log_verbose("Using device-mapper ioctl protocol version 1");
return 1;
}
compat = "(compat)";
bad:
dm_get_library_version(libversion, sizeof(libversion));
log_error("Incompatible libdevmapper %s%s and kernel driver %s.",
@ -748,11 +752,6 @@ uint32_t dm_task_get_read_ahead(const struct dm_task *dmt, uint32_t *read_ahead)
struct dm_deps *dm_task_get_deps(struct dm_task *dmt)
{
if (!dmt) {
log_error(INTERNAL_ERROR "Missing dm_task.");
return NULL;
}
return (struct dm_deps *) (((char *) dmt->dmi.v4) +
dmt->dmi.v4->data_start);
}
@ -782,12 +781,19 @@ static int _check_has_event_nr(void) {
return _has_event_nr;
}
struct dm_device_list {
struct dm_list list;
unsigned count;
unsigned features;
struct dm_hash_table *uuids;
};
int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
unsigned *devs_features)
{
struct dm_names *names, *names1;
struct dm_active_device *dm_dev, *dm_new_dev;
struct dm_list *devs;
struct dm_device_list *devs;
unsigned next = 0;
uint32_t *event_nr;
char *uuid_ptr;
@ -808,12 +814,12 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
} while (next);
}
/* buffer for devs + sorted ptrs + dm_devs + aligned strings */
if (!(devs = malloc(sizeof(*devs) + cnt * (2 * sizeof(void*) + sizeof(*dm_dev)) +
(cnt ? (char*)names1 - (char*)names + 256 : 0))))
if (!(devs = malloc(sizeof(*devs) + (cnt ? cnt * sizeof(*dm_dev) + (char*)names1 - (char*)names + 256 : 0))))
return_0;
dm_list_init(devs);
dm_list_init(&devs->list);
devs->count = cnt;
devs->uuids = NULL;
if (!cnt) {
/* nothing in the list -> mark all features present */
@ -821,22 +827,27 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
goto out; /* nothing else to do */
}
/* Shift position where to store individual dm_devs */
dm_dev = (struct dm_active_device *) ((long*) (devs + 1) + cnt);
dm_dev = (struct dm_active_device *) (devs + 1);
do {
names = (struct dm_names *)((char *) names + next);
dm_dev->devno = (dev_t) names->dev;
dm_dev->name = (const char *)(dm_dev + 1);
dm_dev->major = MAJOR(names->dev);
dm_dev->minor = MINOR(names->dev);
dm_dev->name = (char*)(dm_dev + 1);
dm_dev->event_nr = 0;
dm_dev->uuid = "";
dm_dev->uuid = NULL;
strcpy(dm_dev->name, names->name);
len = strlen(names->name) + 1;
memcpy((char*)dm_dev->name, names->name, len);
dm_new_dev = _align_ptr((char*)(dm_dev + 1) + len);
if (_check_has_event_nr()) {
/* Hash for UUIDs with some more bits to reduce colision count */
if (!devs->uuids && !(devs->uuids = dm_hash_create(cnt * 8))) {
free(devs);
return_0;
}
*devs_features |= DM_DEVICE_LIST_HAS_EVENT_NR;
event_nr = _align_ptr(names->name + len);
@ -845,29 +856,54 @@ int dm_task_get_device_list(struct dm_task *dmt, struct dm_list **devs_list,
if ((event_nr[1] & DM_NAME_LIST_FLAG_HAS_UUID)) {
*devs_features |= DM_DEVICE_LIST_HAS_UUID;
uuid_ptr = _align_ptr(event_nr + 2);
len = strlen(uuid_ptr) + 1;
memcpy(dm_new_dev, uuid_ptr, len);
dm_dev->uuid = (const char *) dm_new_dev;
dm_new_dev = _align_ptr((char*)dm_new_dev + len);
dm_dev->uuid = (char*) dm_new_dev;
dm_new_dev = _align_ptr((char*)dm_new_dev + strlen(uuid_ptr) + 1);
strcpy(dm_dev->uuid, uuid_ptr);
if (!dm_hash_insert(devs->uuids, dm_dev->uuid, dm_dev))
return_0; // FIXME
#if 0
log_debug("Active %s (%s) %d:%d event:%u",
dm_dev->name, dm_dev->uuid,
dm_dev->major, dm_dev->minor, dm_dev->event_nr);
#endif
}
}
dm_list_add(devs, &dm_dev->list);
dm_list_add(&devs->list, &dm_dev->list);
dm_dev = dm_new_dev;
next = names->next;
} while (next);
out:
*devs_list = devs;
*devs_list = (struct dm_list *)devs;
return 1;
}
int dm_device_list_find_by_uuid(struct dm_list *devs_list, const char *uuid,
const struct dm_active_device **dev)
{
struct dm_device_list *devs = (struct dm_device_list *) devs_list;
struct dm_active_device *dm_dev;
if (devs->uuids &&
(dm_dev = dm_hash_lookup(devs->uuids, uuid))) {
if (dev)
*dev = dm_dev;
return 1;
}
return 0;
}
void dm_device_list_destroy(struct dm_list **devs_list)
{
struct dm_device_list *devs = (struct dm_device_list *) *devs_list;
if (devs) {
if (devs->uuids)
dm_hash_destroy(devs->uuids);
free(devs);
*devs_list = NULL;
}
@ -1160,10 +1196,9 @@ static char *_add_target(struct target *t, char *out, char *end)
while (*pt)
if (*pt++ == '\\')
backslash_count++;
len = strlen(t->params) + backslash_count;
len = strlen(t->params) + 1;
if ((out >= end) || (out + len + backslash_count) >= end) {
if ((out >= end) || (out + len + 1) >= end) {
log_error("Ran out of memory building ioctl parameter");
return NULL;
}
@ -1179,8 +1214,8 @@ static char *_add_target(struct target *t, char *out, char *end)
*out++ = '\0';
}
else {
memcpy(out, t->params, len);
out += len + backslash_count;
strcpy(out, t->params);
out += len + 1;
}
/* align next block */
@ -1214,7 +1249,7 @@ static int _lookup_dev_name(uint64_t dev, char *buf, size_t len)
do {
names = (struct dm_names *)((char *) names + next);
if (names->dev == dev) {
memccpy(buf, names->name, 0, len);
strncpy(buf, names->name, len);
r = 1;
break;
}
@ -1251,7 +1286,6 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
struct target *t;
struct dm_target_msg *tmsg;
size_t len = sizeof(struct dm_ioctl);
size_t message_len = 0, newname_len = 0, geometry_len = 0;
char *b, *e;
int count = 0;
@ -1312,20 +1346,14 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
return NULL;
}
if (dmt->newname) {
newname_len = strlen(dmt->newname) + 1;
len += newname_len;
}
if (dmt->newname)
len += strlen(dmt->newname) + 1;
if (dmt->message) {
message_len = strlen(dmt->message) + 1;
len += sizeof(struct dm_target_msg) + message_len;
}
if (dmt->message)
len += sizeof(struct dm_target_msg) + strlen(dmt->message) + 1;
if (dmt->geometry) {
geometry_len = strlen(dmt->geometry) + 1;
len += geometry_len;
}
if (dmt->geometry)
len += strlen(dmt->geometry) + 1;
/*
* Give len a minimum size so that we have space to store
@ -1383,10 +1411,12 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
/* FIXME Until resume ioctl supplies name, use dev_name for readahead */
if (DEV_NAME(dmt) && (dmt->type != DM_DEVICE_RESUME || dmt->minor < 0 ||
dmt->major < 0))
memccpy(dmi->name, DEV_NAME(dmt), 0, sizeof(dmi->name));
/* coverity[buffer_size_warning] */
strncpy(dmi->name, DEV_NAME(dmt), sizeof(dmi->name));
if (DEV_UUID(dmt))
memccpy(dmi->uuid, DEV_UUID(dmt), 0, sizeof(dmi->uuid));
/* coverity[buffer_size_warning] */
strncpy(dmi->uuid, DEV_UUID(dmt), sizeof(dmi->uuid));
if (dmt->type == DM_DEVICE_SUSPEND)
dmi->flags |= DM_SUSPEND_FLAG;
@ -1445,16 +1475,16 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
goto_bad;
if (dmt->newname)
memcpy(b, dmt->newname, newname_len);
strcpy(b, dmt->newname);
if (dmt->message) {
tmsg = (struct dm_target_msg *) b;
tmsg->sector = dmt->sector;
memcpy(tmsg->message, dmt->message, message_len);
strcpy(tmsg->message, dmt->message);
}
if (dmt->geometry)
memcpy(b, dmt->geometry, geometry_len);
strcpy(b, dmt->geometry);
return dmi;
@ -1576,7 +1606,7 @@ static int _check_uevent_generated(struct dm_ioctl *dmi)
static int _create_and_load_v4(struct dm_task *dmt)
{
struct dm_task *task;
int r, ioctl_errno = 0;
int r;
uint32_t cookie;
/* Use new task struct to create the device */
@ -1602,10 +1632,8 @@ static int _create_and_load_v4(struct dm_task *dmt)
task->cookie_set = dmt->cookie_set;
task->add_node = dmt->add_node;
if (!dm_task_run(task)) {
ioctl_errno = task->ioctl_errno;
if (!dm_task_run(task))
goto_bad;
}
dm_task_destroy(task);
@ -1631,8 +1659,6 @@ static int _create_and_load_v4(struct dm_task *dmt)
task->ima_measurement = dmt->ima_measurement;
r = dm_task_run(task);
if (!r)
ioctl_errno = task->ioctl_errno;
task->head = NULL;
task->tail = NULL;
@ -1650,7 +1676,6 @@ static int _create_and_load_v4(struct dm_task *dmt)
dmt->uuid = NULL;
free(dmt->mangled_uuid);
dmt->mangled_uuid = NULL;
/* coverity[double_free] recursive function call */
_dm_task_free_targets(dmt);
if (dm_task_run(dmt))
@ -1662,7 +1687,6 @@ static int _create_and_load_v4(struct dm_task *dmt)
dmt->uuid = NULL;
free(dmt->mangled_uuid);
dmt->mangled_uuid = NULL;
/* coverity[double_free] recursive function call */
_dm_task_free_targets(dmt);
/*
@ -1681,18 +1705,12 @@ static int _create_and_load_v4(struct dm_task *dmt)
if (!dm_task_run(dmt))
log_error("Failed to revert device creation.");
if (ioctl_errno != 0)
dmt->ioctl_errno = ioctl_errno;
return 0;
bad:
dm_task_destroy(task);
_udev_complete(dmt);
if (ioctl_errno != 0)
dmt->ioctl_errno = ioctl_errno;
return 0;
}
@ -2034,7 +2052,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
/*
* Prevent udev vs. libdevmapper race when processing nodes
* and symlinks. This can happen when the udev rules are
* installed and udev synchronization code is enabled in
* installed and udev synchronisation code is enabled in
* libdevmapper but the software using libdevmapper does not
* make use of it (by not calling dm_task_set_cookie before).
* We need to instruct the udev rules not to be applied at
@ -2044,7 +2062,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
if (!dmt->cookie_set && dm_udev_get_sync_support()) {
log_debug_activation("Cookie value is not set while trying to call %s "
"ioctl. Please, consider using libdevmapper's udev "
"synchronization interface or disable it explicitly "
"synchronisation interface or disable it explicitly "
"by calling dm_udev_set_sync_support(0).",
dmt->type == DM_DEVICE_RESUME ? "DM_DEVICE_RESUME" :
dmt->type == DM_DEVICE_REMOVE ? "DM_DEVICE_REMOVE" :

View File

@ -79,7 +79,7 @@ struct dm_task {
};
struct cmd_data {
const char name[16];
const char *name;
const unsigned cmd;
const int version[3];
};

View File

@ -537,8 +537,7 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
}
if (str[i] == '\\' && str[i+1] == 'x') {
if (!sscanf(&str[i+2], "%2x%" DM_TO_STRING(DM_NAME_LEN) "s",
&code, str_rest)) {
if (!sscanf(&str[i+2], "%2x%s", &code, str_rest)) {
log_debug_activation("Hex encoding mismatch detected in %s \"%s\" "
"while trying to unmangle it.", str_name, str);
goto out;
@ -1061,8 +1060,9 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
if (info.st_rdev == dev)
return 1;
if (unlink(path) && (errno != ENOENT)) {
log_sys_error("unlink", path);
if (unlink(path) < 0) {
log_error("Unable to unlink device node for '%s'",
dev_name);
return 0;
}
} else if (_warn_if_op_needed(warn_if_udev_failed))
@ -1106,8 +1106,8 @@ static int _rm_dev_node(const char *dev_name, int warn_if_udev_failed)
"Falling back to direct node removal.", path);
/* udev may already have deleted the node. Ignore ENOENT. */
if (unlink(path) && (errno != ENOENT)) {
log_sys_error("unlink", path);
if (unlink(path) < 0 && errno != ENOENT) {
log_error("Unable to unlink device node for '%s'", dev_name);
return 0;
}
@ -1451,10 +1451,9 @@ struct node_op_parms {
static void _store_str(char **pos, char **ptr, const char *str)
{
size_t len = strlen(str) + 1;
memcpy(*pos, str, len);
strcpy(*pos, str);
*ptr = *pos;
*pos += len;
*pos += strlen(*ptr) + 1;
}
static void _del_node_op(struct node_op_parms *nop)
@ -1704,17 +1703,15 @@ const char *dm_sysfs_dir(void)
*/
int dm_set_uuid_prefix(const char *uuid_prefix)
{
size_t len;
if (!uuid_prefix)
return_0;
if ((len = strlen(uuid_prefix)) > DM_MAX_UUID_PREFIX_LEN) {
if (strlen(uuid_prefix) > DM_MAX_UUID_PREFIX_LEN) {
log_error("New uuid prefix %s too long.", uuid_prefix);
return 0;
}
memcpy(_default_uuid_prefix, uuid_prefix, len + 1);
strcpy(_default_uuid_prefix, uuid_prefix);
return 1;
}
@ -1743,9 +1740,6 @@ static void _unmangle_mountinfo_string(const char *src, char *buf)
*buf = '\0';
}
/* coverity[+tainted_string_sanitize_content:arg-0] */
static int _sanitize_line(const char *line) { return 1; }
/* Parse one line of mountinfo and unmangled target line */
static int _mountinfo_parse_line(const char *line, unsigned *maj, unsigned *min, char *buf)
{
@ -1816,8 +1810,7 @@ int dm_mountinfo_read(dm_mountinfo_line_callback_fn read_fn, void *cb_data)
}
while (!feof(minfo) && fgets(buffer, sizeof(buffer), minfo))
if (!_sanitize_line(buffer) ||
!_mountinfo_parse_line(buffer, &maj, &min, target) ||
if (!_mountinfo_parse_line(buffer, &maj, &min, target) ||
!read_fn(buffer, maj, min, target, cb_data)) {
stack;
r = 0;
@ -2318,7 +2311,7 @@ static int _check_semaphore_is_supported(void)
if (maxid < 0) {
log_warn("Kernel not configured for semaphores (System V IPC). "
"Not using udev synchronization code.");
"Not using udev synchronisation code.");
return 0;
}
@ -2341,7 +2334,7 @@ static int _check_udev_is_running(void)
if (!(r = udev_queue_get_udev_is_active(udev_queue)))
log_debug_activation("Udev is not running. "
"Not using udev synchronization code.");
"Not using udev synchronisation code.");
udev_queue_unref(udev_queue);
udev_unref(udev);

View File

@ -74,6 +74,8 @@ static struct dm_config_node *_create_node(struct dm_pool *mem);
static char *_dup_tok(struct parser *p);
static char *_dup_token(struct dm_pool *mem, const char *b, const char *e);
static const int _sep = '/';
#define MAX_INDENT 32
#define match(t) do {\
@ -175,18 +177,19 @@ static int _do_dm_config_parse(struct dm_config_tree *cft, const char *start, co
{
/* TODO? if (start == end) return 1; */
struct parser p = {
.mem = cft->mem,
.tb = start,
.te = start,
.fb = start,
.fe = end,
.line = 1,
.no_dup_node_check = no_dup_node_check
};
struct parser *p;
if (!(p = dm_pool_zalloc(cft->mem, sizeof(*p))))
return_0;
_get_token(&p, TOK_SECTION_E);
if (!(cft->root = _file(&p)))
p->mem = cft->mem;
p->fb = start;
p->fe = end;
p->tb = p->te = p->fb;
p->line = 1;
p->no_dup_node_check = no_dup_node_check;
_get_token(p, TOK_SECTION_E);
if (!(cft->root = _file(p)))
return_0;
cft->root = _config_reverse(cft->root);
@ -523,18 +526,17 @@ static struct dm_config_node *_find_or_make_node(struct dm_pool *mem,
const char *path,
int no_dup_node_check)
{
const int sep = '/';
const char *e;
struct dm_config_node *cn = parent ? parent->child : NULL;
struct dm_config_node *cn_found = NULL;
while (cn || mem) {
/* trim any leading slashes */
while (*path && (*path == sep))
while (*path && (*path == _sep))
path++;
/* find the end of this segment */
for (e = path; *e && (*e != sep); e++) ;
for (e = path; *e && (*e != _sep); e++) ;
/* hunt for the node */
cn_found = NULL;

View File

@ -171,7 +171,7 @@ struct load_segment {
uint32_t region_size; /* Mirror + raid */
unsigned clustered; /* Mirror */
unsigned mirror_area_count; /* Mirror */
uint64_t flags; /* Mirror + Raid + Cache */
uint32_t flags; /* Mirror + raid + Cache */
char *uuid; /* Clustered mirror log */
const char *policy_name; /* Cache */
@ -294,10 +294,6 @@ struct load_properties {
unsigned send_messages;
/* Skip suspending node's children, used when sending messages to thin-pool */
int skip_suspend;
/* Suspend and Resume siblings after node activation with udev flags*/
unsigned reactivate_siblings;
uint16_t reactivate_udev_flags;
};
/* Two of these used to join two nodes with uses and used_by. */
@ -348,7 +344,7 @@ struct dm_tree {
int retry_remove; /* 1 retries remove if not successful */
uint32_t cookie;
char buf[DM_NAME_LEN + 32]; /* print buffer for device_name (major:minor) */
const char * const *optional_uuid_suffixes; /* uuid suffixes ignored when matching */
const char **optional_uuid_suffixes; /* uuid suffixes ignored when matching */
};
/*
@ -590,7 +586,6 @@ void dm_tree_set_optional_uuid_suffixes(struct dm_tree *dtree, const char **opti
dtree->optional_uuid_suffixes = optional_uuid_suffixes;
}
static const char *_node_name(struct dm_tree_node *dnode);
static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
const char *uuid)
{
@ -598,26 +593,28 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
const char *default_uuid_prefix;
size_t default_uuid_prefix_len;
const char *suffix, *suffix_position;
char uuid_without_suffix[DM_UUID_LEN + 1];
char uuid_without_suffix[DM_UUID_LEN];
unsigned i = 0;
const char * const *suffix_list = dtree->optional_uuid_suffixes;
const char **suffix_list = dtree->optional_uuid_suffixes;
if ((node = dm_hash_lookup(dtree->uuids, uuid))) {
log_debug_activation("Matched uuid %s %s in deptree.", uuid, _node_name(node));
log_debug("Matched uuid %s in deptree.", uuid);
return node;
}
default_uuid_prefix = dm_uuid_prefix();
default_uuid_prefix_len = strlen(default_uuid_prefix);
if (suffix_list && (suffix_position = strrchr(uuid, '-'))) {
while ((suffix = suffix_list[i++])) {
if (strcmp(suffix_position + 1, suffix))
continue;
dm_strncpy(uuid_without_suffix, uuid, sizeof(uuid_without_suffix));
(void) strncpy(uuid_without_suffix, uuid, sizeof(uuid_without_suffix));
uuid_without_suffix[suffix_position - uuid] = '\0';
if ((node = dm_hash_lookup(dtree->uuids, uuid_without_suffix))) {
log_debug_activation("Matched uuid %s %s (missing suffix -%s) in deptree.",
uuid_without_suffix, _node_name(node), suffix);
log_debug("Matched uuid %s (missing suffix -%s) in deptree.", uuid_without_suffix, suffix);
return node;
}
@ -625,17 +622,15 @@ static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
};
}
default_uuid_prefix = dm_uuid_prefix();
default_uuid_prefix_len = strlen(default_uuid_prefix);
if (strncmp(uuid, default_uuid_prefix, default_uuid_prefix_len))
return NULL;
if ((strncmp(uuid, default_uuid_prefix, default_uuid_prefix_len) == 0) &&
(node = dm_hash_lookup(dtree->uuids, uuid + default_uuid_prefix_len))) {
log_debug_activation("Matched uuid %s %s (missing prefix) in deptree.",
uuid + default_uuid_prefix_len, _node_name(node));
if ((node = dm_hash_lookup(dtree->uuids, uuid + default_uuid_prefix_len))) {
log_debug("Matched uuid %s (missing prefix) in deptree.", uuid + default_uuid_prefix_len);
return node;
}
log_debug_activation("Not matched uuid %s in deptree.", uuid);
log_debug("Not matched uuid %s in deptree.", uuid);
return NULL;
}
@ -2035,68 +2030,6 @@ static int _rename_conflict_exists(struct dm_tree_node *parent,
return 0;
}
/*
* Reactivation of sibling nodes
*
* Function is used when activating origin and its thick snapshots
* to ensure udev is processing first the origin LV and all the
* snapshot LVs are processed afterwards.
*/
static int _reactivate_siblings(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
{
struct dm_tree_node *child;
const char *uuid;
void *handle = NULL;
int r = 1;
/* Wait for udev before reactivating siblings */
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
stack;
dm_tree_set_cookie(dnode, 0);
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
if (child->props.reactivate_siblings) {
/* Skip 'leading' device in this group, marked with flag */
child->props.reactivate_siblings = 0;
continue;
}
if (!(uuid = dm_tree_node_get_uuid(child))) {
stack;
continue;
}
if (!_uuid_prefix_matches(uuid, uuid_prefix, uuid_prefix_len))
continue;
if (!_suspend_node(child->name, child->info.major, child->info.minor,
child->dtree->skip_lockfs,
child->dtree->no_flush, &child->info)) {
log_error("Unable to suspend %s (" FMTu32
":" FMTu32 ")", child->name,
child->info.major, child->info.minor);
r = 0;
continue;
}
if (!_resume_node(child->name, child->info.major, child->info.minor,
child->props.read_ahead, child->props.read_ahead_flags,
&child->info, &child->dtree->cookie,
child->props.reactivate_udev_flags, // use these flags
child->info.suspended)) {
log_error("Failed to suspend %s (" FMTu32
":" FMTu32 ")", child->name,
child->info.major, child->info.minor);
r = 0;
continue;
}
}
return r;
}
int dm_tree_activate_children(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
@ -2107,7 +2040,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
struct dm_tree_node *child = dnode;
const char *name;
const char *uuid;
int priority, next_priority;
int priority;
/* Activate children first */
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
@ -2125,16 +2058,12 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
}
handle = NULL;
for (priority = 0; priority < 3; priority++) {
awaiting_peer_rename = 0;
next_priority = 0;
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
if (priority != child->activation_priority) {
if ((next_priority < child->activation_priority) &&
(child->activation_priority > priority))
next_priority = child->activation_priority;
if (priority != child->activation_priority)
continue;
}
if (!(uuid = dm_tree_node_get_uuid(child))) {
stack;
@ -2189,16 +2118,9 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
if (r && (child->props.send_messages > 1) &&
!(r = _node_send_messages(child, uuid_prefix, uuid_prefix_len, 1)))
stack;
/* Reactivate only for fresh activated origin */
if (r && child->props.reactivate_siblings &&
(!(r = _reactivate_siblings(dnode, uuid_prefix, uuid_prefix_len))))
stack;
}
if (awaiting_peer_rename)
priority--; /* redo priority level */
else if (!next_priority)
break; /* no more work, higher priority was not found in the chain */
}
return r;
@ -3527,10 +3449,6 @@ int dm_tree_node_add_snapshot_origin_target(struct dm_tree_node *dnode,
/* Resume snapshot origins after new snapshots */
dnode->activation_priority = 1;
if (!dnode->info.exists)
/* Reactivate siblings for this origin after being resumed */
dnode->props.reactivate_siblings = 1;
/*
* Don't resume the origin immediately in case it is a non-trivial
* target that must not be active more than once concurrently!
@ -3593,20 +3511,6 @@ static int _add_snapshot_target(struct dm_tree_node *node,
/* Resume merging snapshot after snapshot-merge */
seg->merge->activation_priority = 2;
}
} else if (!origin_node->info.exists) {
/* Keep original udev_flags for reactivation. */
node->props.reactivate_udev_flags = node->udev_flags;
/* Reactivation is needed if the origin's -real device is not in DM table.
* For this case after the resume of its origin LV we resume its snapshots
* with updated udev_flags to completely avoid udev scanning for the first resume.
* Reactivation then resumes snapshots with original udev_flags.
*/
node->udev_flags |= DM_SUBSYSTEM_UDEV_FLAG0 |
DM_UDEV_DISABLE_DISK_RULES_FLAG |
DM_UDEV_DISABLE_OTHER_RULES_FLAG;
log_debug_activation("Using udev_flags 0x%x for activation of %s.",
node->udev_flags, node->name);
}
return 1;
@ -3864,7 +3768,7 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
{
struct dm_config_node *cn;
struct load_segment *seg;
const uint64_t modemask =
static const uint64_t _modemask =
DM_CACHE_FEATURE_PASSTHROUGH |
DM_CACHE_FEATURE_WRITETHROUGH |
DM_CACHE_FEATURE_WRITEBACK;
@ -3876,12 +3780,12 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node,
return 0;
}
switch (feature_flags & modemask) {
switch (feature_flags & _modemask) {
case DM_CACHE_FEATURE_PASSTHROUGH:
case DM_CACHE_FEATURE_WRITEBACK:
if (strcmp(policy_name, "cleaner") == 0) {
/* Enforce writethrough mode for cleaner policy */
feature_flags = ~modemask;
feature_flags = ~_modemask;
feature_flags |= DM_CACHE_FEATURE_WRITETHROUGH;
}
/* Fall through */
@ -4364,12 +4268,6 @@ int dm_tree_node_set_thin_external_origin(struct dm_tree_node *node,
seg->external = external;
if (!external->info.minor) {
log_debug_activation("Delaying resume for new external origin %s.",
external->name);
external->props.delay_resume_if_new = 1;
}
return 1;
}

View File

@ -223,6 +223,7 @@ retry_fcntl:
}
/* coverity[leaked_handle] intentional leak of fd handle here */
return 1;
fail_close_unlink:

View File

@ -153,7 +153,7 @@ struct op_def {
* shorter one if one is a prefix of another!
* (e.g. =~ comes before =)
*/
static const struct op_def _op_cmp[] = {
static struct op_def _op_cmp[] = {
{ "=~", FLD_CMP_REGEX, "Matching regular expression. [regex]" },
{ "!~", FLD_CMP_REGEX|FLD_CMP_NOT, "Not matching regular expression. [regex]" },
{ "=", FLD_CMP_EQUAL, "Equal to. [number, size, percent, string, string list, time]" },
@ -187,7 +187,7 @@ static const struct op_def _op_cmp[] = {
#define SEL_LIST_SUBSET_LS 0x00040000
#define SEL_LIST_SUBSET_LE 0x00080000
static const struct op_def _op_log[] = {
static struct op_def _op_log[] = {
{ "&&", SEL_AND, "All fields must match" },
{ ",", SEL_AND, "All fields must match" },
{ "||", SEL_OR, "At least one field must match" },
@ -796,11 +796,11 @@ static const char *_get_field_type_name(unsigned field_type)
static size_t _get_longest_field_id_len(const struct dm_report_field_type *fields)
{
uint32_t f;
size_t l, id_len = 0;
size_t id_len = 0;
for (f = 0; fields[f].report_fn; f++)
if ((l = strlen(fields[f].id)) > id_len)
id_len = l;
if (strlen(fields[f].id) > id_len)
id_len = strlen(fields[f].id);
return id_len;
}
@ -811,17 +811,16 @@ static void _display_fields_more(struct dm_report *rh,
int display_field_types)
{
uint32_t f;
size_t l;
const struct dm_report_object_type *type;
const char *desc, *last_desc = "";
for (f = 0; fields[f].report_fn; f++)
if ((l = strlen(fields[f].id)) > id_len)
id_len = l;
if (strlen(fields[f].id) > id_len)
id_len = strlen(fields[f].id);
for (type = rh->types; type->data_fn; type++)
if ((l = strlen(type->prefix) + 3) > id_len)
id_len = l;
if (strlen(type->prefix) + 3 > id_len)
id_len = strlen(type->prefix) + 3;
for (f = 0; fields[f].report_fn; f++) {
if (!(type = _find_type(rh, fields[f].type))) {
@ -965,13 +964,16 @@ static int _get_canonical_field_name(const char *field,
* Both names are always null-terminated.
*/
static int _is_same_field(const char *canonical_name1, const char *canonical_name2,
const char *prefix, size_t prefix_len)
const char *prefix)
{
size_t prefix_len;
/* Exact match? */
if (!strcasecmp(canonical_name1, canonical_name2))
return 1;
/* Match including prefix? */
prefix_len = strlen(prefix) - 1;
if (!strncasecmp(prefix, canonical_name1, prefix_len) &&
!strcasecmp(canonical_name1 + prefix_len, canonical_name2))
return 1;
@ -1047,7 +1049,6 @@ static int _get_field(struct dm_report *rh, const char *field, size_t flen,
{
char field_canon[DM_REPORT_FIELD_TYPE_ID_LEN];
uint32_t f;
size_t prefix_len;
if (!flen)
return 0;
@ -1055,9 +1056,8 @@ static int _get_field(struct dm_report *rh, const char *field, size_t flen,
if (!_get_canonical_field_name(field, flen, field_canon, sizeof(field_canon), NULL))
return_0;
prefix_len = strlen(rh->field_prefix) - 1;
for (f = 0; _implicit_report_fields[f].report_fn; f++) {
if (_is_same_field(_implicit_report_fields[f].id, field_canon, rh->field_prefix, prefix_len)) {
if (_is_same_field(_implicit_report_fields[f].id, field_canon, rh->field_prefix)) {
*f_ret = f;
*implicit = 1;
return 1;
@ -1065,7 +1065,7 @@ static int _get_field(struct dm_report *rh, const char *field, size_t flen,
}
for (f = 0; rh->fields[f].report_fn; f++) {
if (_is_same_field(rh->canonical_field_ids[f], field_canon, rh->field_prefix, prefix_len)) {
if (_is_same_field(rh->canonical_field_ids[f], field_canon, rh->field_prefix)) {
*f_ret = f;
*implicit = 0;
return 1;
@ -1146,7 +1146,7 @@ static int _add_sort_key(struct dm_report *rh, uint32_t field_num, int implicit,
static int _key_match(struct dm_report *rh, const char *key, size_t len,
unsigned report_type_only)
{
int implicit;
char key_canon[DM_REPORT_FIELD_TYPE_ID_LEN];
uint32_t f;
uint32_t flags;
@ -1169,8 +1169,16 @@ static int _key_match(struct dm_report *rh, const char *key, size_t len,
return 0;
}
if (_get_field(rh, key, len, &f, &implicit))
return _add_sort_key(rh, f, implicit, flags, report_type_only);
if (!_get_canonical_field_name(key, len, key_canon, sizeof(key_canon), NULL))
return_0;
for (f = 0; _implicit_report_fields[f].report_fn; f++)
if (_is_same_field(_implicit_report_fields[f].id, key_canon, rh->field_prefix))
return _add_sort_key(rh, f, 1, flags, report_type_only);
for (f = 0; rh->fields[f].report_fn; f++)
if (_is_same_field(rh->canonical_field_ids[f], key_canon, rh->field_prefix))
return _add_sort_key(rh, f, 0, flags, report_type_only);
return 0;
}
@ -1453,14 +1461,9 @@ static void *_report_get_field_data(struct dm_report *rh,
const struct dm_report_field_type *fields = fp->implicit ? _implicit_report_fields
: rh->fields;
char *ret;
char *ret = fp->type->data_fn(object);
if (!object) {
log_error(INTERNAL_ERROR "_report_get_field_data: missing object.");
return NULL;
}
if (!(ret = fp->type->data_fn(object)))
if (!ret)
return NULL;
return (void *)(ret + fields[fp->field_num].offset);
@ -2261,7 +2264,7 @@ static const char * _skip_space(const char *s)
return s;
}
static int _tok_op(const struct op_def *t, const char *s, const char **end,
static int _tok_op(struct op_def *t, const char *s, const char **end,
uint32_t expect)
{
size_t len;
@ -2502,7 +2505,7 @@ float dm_percent_to_float(dm_percent_t percent)
float dm_percent_to_round_float(dm_percent_t percent, unsigned digits)
{
const float power10[] = {
static const float power10[] = {
1.f, .1f, .01f, .001f, .0001f, .00001f, .000001f,
.0000001f, .00000001f, .000000001f,
.0000000001f
@ -2568,12 +2571,12 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
const struct dm_report_reserved_value *iter;
const struct dm_report_field_reserved_value *field_res;
const struct dm_report_field_type *field;
const uint32_t supported_reserved_types = DM_REPORT_FIELD_TYPE_NUMBER |
static uint32_t supported_reserved_types = DM_REPORT_FIELD_TYPE_NUMBER |
DM_REPORT_FIELD_TYPE_SIZE |
DM_REPORT_FIELD_TYPE_PERCENT |
DM_REPORT_FIELD_TYPE_STRING |
DM_REPORT_FIELD_TYPE_TIME;
const uint32_t supported_reserved_types_with_range = DM_REPORT_FIELD_RESERVED_VALUE_RANGE |
static uint32_t supported_reserved_types_with_range = DM_REPORT_FIELD_RESERVED_VALUE_RANGE |
DM_REPORT_FIELD_TYPE_NUMBER |
DM_REPORT_FIELD_TYPE_SIZE |
DM_REPORT_FIELD_TYPE_PERCENT |
@ -2589,8 +2592,7 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
if (iter->type & DM_REPORT_FIELD_TYPE_MASK) {
if (!(iter->type & supported_reserved_types) ||
((iter->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE) &&
!(iter->type & (supported_reserved_types_with_range &
~DM_REPORT_FIELD_RESERVED_VALUE_RANGE)))) {
!(iter->type & supported_reserved_types_with_range))) {
log_error(INTERNAL_ERROR "_check_reserved_values_supported: "
"global reserved value for type 0x%x not supported",
iter->type);
@ -2600,9 +2602,8 @@ static int _check_reserved_values_supported(const struct dm_report_field_type fi
field_res = (const struct dm_report_field_reserved_value *) iter->value;
field = &fields[field_res->field_num];
if (!(field->flags & supported_reserved_types) ||
((field->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE) &&
!(field->type & (supported_reserved_types_with_range &
~DM_REPORT_FIELD_RESERVED_VALUE_RANGE)))) {
((iter->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE) &&
!(iter->type & supported_reserved_types_with_range))) {
log_error(INTERNAL_ERROR "_check_reserved_values_supported: "
"field-specific reserved value of type 0x%x for "
"field %s not supported",
@ -2842,7 +2843,7 @@ struct time_value {
time_t t2;
};
static const char _out_of_range_msg[] = "Field selection value %s out of supported range for field %s.";
static const char *_out_of_range_msg = "Field selection value %s out of supported range for field %s.";
/*
* Standard formatted date and time - ISO8601.
@ -2867,7 +2868,7 @@ static const char _out_of_range_msg[] = "Field selection value %s out of support
#define DELIM_DATE '-'
#define DELIM_TIME ':'
static const int _days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int _days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int _is_leap_year(long year)
{
@ -2892,6 +2893,7 @@ typedef enum {
static char *_get_date(char *str, struct tm *tm, time_range_t *range)
{
static const char incorrect_date_format_msg[] = "Incorrect date format.";
time_range_t tmp_range = RANGE_NONE;
long n1, n2 = -1, n3 = -1;
char *s = str, *end;
@ -2937,15 +2939,19 @@ static char *_get_date(char *str, struct tm *tm, time_range_t *range)
n3 = n1 % 100;
n2 = (n1 / 100) % 100;
n1 = n1 / 10000;
} else
goto_bad;
} else {
log_error(incorrect_date_format_msg);
return NULL;
}
} else {
if (len == 7) {
tmp_range = RANGE_MONTH;
/* YYYY-MM */
n3 = 1;
} else
goto_bad;
} else {
log_error(incorrect_date_format_msg);
return NULL;
}
}
}
@ -2968,15 +2974,11 @@ static char *_get_date(char *str, struct tm *tm, time_range_t *range)
*range = tmp_range;
return (char *) _skip_space(end);
bad:
log_error("Incorrect date format.");
return NULL;
}
static char *_get_time(char *str, struct tm *tm, time_range_t *range)
{
static const char incorrect_time_format_msg[] = "Incorrect time format.";
time_range_t tmp_range = RANGE_NONE;
long n1, n2 = -1, n3 = -1;
char *s = str, *end;
@ -3024,15 +3026,19 @@ static char *_get_time(char *str, struct tm *tm, time_range_t *range)
n3 = n1 % 100;
n2 = (n1 / 100) % 100;
n1 = n1 / 10000;
} else
goto_bad;
} else {
log_error(incorrect_time_format_msg);
return NULL;
}
} else {
if (len == 5) {
/* HH:MM */
tmp_range = RANGE_MINUTE;
n3 = 0;
} else
goto_bad;
} else {
log_error(incorrect_time_format_msg);
return NULL;
}
}
}
@ -3063,11 +3069,6 @@ static char *_get_time(char *str, struct tm *tm, time_range_t *range)
*range = tmp_range;
return (char *) _skip_space(end);
bad:
log_error("Incorrect time format.");
return NULL;
}
/* The offset is always an absolute offset against GMT! */
@ -3516,6 +3517,7 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
struct reserved_value_wrapper *rvw,
void *custom)
{
static const char *_field_selection_value_alloc_failed_msg = "dm_report: struct field_selection_value allocation failed for selection field %s";
const struct dm_report_field_type *fields = implicit ? _implicit_report_fields
: rh->fields;
struct field_properties *fp, *found = NULL;
@ -3563,8 +3565,8 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
}
if (!(fs->value = dm_pool_zalloc(rh->selection->mem, sizeof(struct field_selection_value)))) {
stack;
goto error_field_id;
log_error(_field_selection_value_alloc_failed_msg, field_id);
goto error;
}
if (((rvw->reserved && (rvw->reserved->type & DM_REPORT_FIELD_RESERVED_VALUE_RANGE)) ||
@ -3572,8 +3574,8 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
custom && ((struct time_value *) custom)->range))
&&
!(fs->value->next = dm_pool_zalloc(rh->selection->mem, sizeof(struct field_selection_value)))) {
stack;
goto error_field_id;
log_error(_field_selection_value_alloc_failed_msg, field_id);
goto error;
}
fs->fp = found;
@ -3722,10 +3724,6 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
}
return fs;
error_field_id:
log_error("dm_report: struct field_selection_value allocation failed for selection field %s",
field_id);
goto error;
bad:
log_error(INTERNAL_ERROR "Forbiden NULL custom detected.");
error:
@ -3754,7 +3752,7 @@ static struct selection_node *_alloc_selection_node(struct dm_pool *mem, uint32_
static void _display_selection_help(struct dm_report *rh)
{
static const char _grow_object_failed_msg[] = "_display_selection_help: dm_pool_grow_object failed";
const struct op_def *t;
struct op_def *t;
const struct dm_report_reserved_value *rv;
size_t len_all, len_final = 0;
const char **rvs;
@ -4107,7 +4105,7 @@ static int _alloc_rh_selection(struct dm_report *rh)
static int _report_set_selection(struct dm_report *rh, const char *selection, int add_new_fields)
{
struct selection_node *root = NULL;
const char *fin = NULL, *next;
const char *fin, *next;
if (rh->selection) {
if (rh->selection->selection_root)
@ -4127,7 +4125,7 @@ static int _report_set_selection(struct dm_report *rh, const char *selection, in
if (!(root = _alloc_selection_node(rh->selection->mem, SEL_OR)))
return 0;
if (!_parse_or_ex(rh, selection, &fin, root) || !fin)
if (!_parse_or_ex(rh, selection, &fin, root))
goto_bad;
next = _skip_space(fin);
@ -4265,9 +4263,7 @@ static int _report_headings(struct dm_report *rh)
fields = fp->implicit ? _implicit_report_fields : rh->fields;
heading = rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS ?
fields[fp->field_num].id : fields[fp->field_num].heading;
heading = fields[fp->field_num].heading;
if (rh->flags & DM_REPORT_OUTPUT_ALIGNED) {
if (dm_snprintf(buf, buf_size, "%-*.*s",
fp->width, fp->width, heading) < 0) {
@ -4319,7 +4315,6 @@ static void _recalculate_fields(struct dm_report *rh)
struct row *row;
struct dm_report_field *field;
int len;
int id_len;
dm_list_iterate_items(row, &rh->rows) {
dm_list_iterate_items(field, &row->fields) {
@ -4334,12 +4329,6 @@ static void _recalculate_fields(struct dm_report *rh)
field->props->width = len;
}
if (rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS) {
id_len = (int) strlen(rh->fields[field->props->field_num].id);
if (field->props->width < id_len)
field->props->width = id_len;
}
}
}
@ -4426,9 +4415,8 @@ static int _sort_rows(struct dm_report *rh)
qsort(rows, count, sizeof(**rows), _row_compare);
dm_list_init(&rh->rows);
while (count > 0)
dm_list_add_h(&rh->rows, &(*rows)[--count]->list);
while (count--)
dm_list_add_h(&rh->rows, &(*rows)[count]->list);
return 1;
}
@ -4752,7 +4740,6 @@ static int _output_as_rows(struct dm_report *rh)
struct field_properties *fp;
struct dm_report_field *field;
struct row *row;
const char *heading;
dm_list_iterate_items(fp, &rh->field_props) {
if (fp->flags & FLD_HIDDEN) {
@ -4771,10 +4758,7 @@ static int _output_as_rows(struct dm_report *rh)
}
if ((rh->flags & DM_REPORT_OUTPUT_HEADINGS)) {
heading = rh->flags & DM_REPORT_OUTPUT_FIELD_IDS_IN_HEADINGS ?
fields[fp->field_num].id : fields[fp->field_num].heading;
if (!dm_pool_grow_object(rh->mem, heading, 0)) {
if (!dm_pool_grow_object(rh->mem, fields[fp->field_num].heading, 0)) {
log_error("dm_report: Failed to extend row for field name");
goto bad;
}
@ -4814,36 +4798,12 @@ static int _output_as_rows(struct dm_report *rh)
return 0;
}
static struct dm_list *_get_last_displayed_rowh(struct dm_report *rh)
{
struct dm_list *rowh;
struct row *row;
/*
* We need to find 'last displayed row', not just 'last row'.
*
* This is because the report may be marked with
* DM_REPORT_OUTPUT_MULTIPLE_TIMES flag. In that case, the report
* may be used more than once and with different selection
* criteria each time. Therefore, such report may also contain
* rows which we do not display on output with current selection
* criteria.
*/
for (rowh = dm_list_last(&rh->rows); rowh; rowh = dm_list_prev(&rh->rows, rowh)) {
row = dm_list_item(rowh, struct row);
if (_should_display_row(row))
return rowh;
}
return NULL;
}
static int _output_as_columns(struct dm_report *rh)
{
struct dm_list *fh, *rowh, *ftmp, *rtmp;
struct row *row = NULL;
struct dm_report_field *field;
struct dm_list *last_rowh;
struct dm_list *last_row;
int do_field_delim;
char *line;
@ -4852,7 +4812,7 @@ static int _output_as_columns(struct dm_report *rh)
_report_headings(rh);
/* Print and clear buffer */
last_rowh = _get_last_displayed_rowh(rh);
last_row = dm_list_last(&rh->rows);
dm_list_iterate_safe(rowh, rtmp, &rh->rows) {
row = dm_list_item(rowh, struct row);
@ -4906,7 +4866,7 @@ static int _output_as_columns(struct dm_report *rh)
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
goto bad;
}
if (rowh != last_rowh &&
if (rowh != last_row &&
!dm_pool_grow_object(rh->mem, JSON_SEPARATOR, 0)) {
log_error(UNABLE_TO_EXTEND_OUTPUT_LINE_MSG);
goto bad;

View File

@ -192,7 +192,7 @@ int dm_asprintf(char **result, const char *format, ...)
}
/*
* Count occurrences of 'c' in 'str' until we reach a null char.
* Count occurences of 'c' in 'str' until we reach a null char.
*
* Returns:
* len - incremented for each char we encounter.
@ -385,7 +385,7 @@ char *dm_build_dm_uuid(struct dm_pool *mem, const char *uuid_prefix, const char
return NULL;
}
snprintf(dmuuid, len, "%s%s%s%s", uuid_prefix, lvid, (*layer) ? "-" : "", layer);
sprintf(dmuuid, "%s%s%s%s", uuid_prefix, lvid, (*layer) ? "-" : "", layer);
return dmuuid;
}
@ -552,7 +552,7 @@ const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
if (size == UINT64_C(0)) {
if (base == BASE_UNKNOWN)
s = 0;
snprintf(size_buf, SIZE_BUF, "0%s", include_suffix ? size_str[base + s][suffix_type] : "");
sprintf(size_buf, "0%s", include_suffix ? size_str[base + s][suffix_type] : "");
return size_buf;
}

View File

@ -106,31 +106,26 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
/* Second field holds the device count */
msg_fields = "<#devs> ";
if (!(pp = _skip_fields(params, 1)) || (sscanf(pp, "%d", &i) != 1) || !(p = _skip_fields(pp, 1)))
if (!(p = _skip_fields(params, 1)) || (sscanf(p, "%d", &i) != 1))
goto_bad;
msg_fields = "";
if (!(s = dm_pool_zalloc(mem, sizeof(struct dm_status_raid))))
goto_bad;
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
if (!(s->raid_type = dm_pool_strndup(mem, params, pp - params - 1)))
if (!(s->raid_type = dm_pool_zalloc(mem, p - params)))
goto_bad; /* memory is freed when pool is destroyed */
if (!(pp = _skip_fields(p, 1)))
if (!(s->dev_health = dm_pool_zalloc(mem, i + 1))) /* Space for health chars */
goto_bad;
/* 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;
if (!(s->dev_health = dm_pool_strndup(mem, p, i))) /* health chars */
goto_bad;
p = pp;
s->dev_count = i;
if (sscanf(p, FMTu64 "/" FMTu64, &s->insync_regions, &s->total_regions) != 2)
msg_fields = "<raid_type> <#devices> <health_chars> and <sync_ratio> ";
if (sscanf(params, "%s %u %s " FMTu64 "/" FMTu64,
s->raid_type,
&s->dev_count,
s->dev_health,
&s->insync_regions,
&s->total_regions) != 5)
goto_bad;
/*
@ -146,13 +141,13 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
msg_fields = "<sync_action> and <mismatch_cnt> ";
/* Skip pre-1.5.0 params */
if (!(pp = _skip_fields(params, 4)) || !(p = _skip_fields(pp, 1)))
if (!(p = _skip_fields(params, 4)) || !(pp = _skip_fields(p, 1)))
goto_bad;
if (!(s->sync_action = dm_pool_strndup(mem, pp, p - pp - 1)))
if (!(s->sync_action = dm_pool_zalloc(mem, pp - p)))
goto_bad;
if (sscanf(p, FMTu64, &s->mismatch_count) != 1)
if (sscanf(p, "%s " FMTu64, s->sync_action, &s->mismatch_count) != 2)
goto_bad;
if (num_fields < 7)
@ -171,35 +166,23 @@ int dm_get_status_raid(struct dm_pool *mem, const char *params,
if (sscanf(p, FMTu64, &s->data_offset) != 1)
goto bad;
/* <journal_char> - 'A' - active write-through journal device.
* - 'a' - active write-back journal device.
* - 'D' - dead journal device.
* - '-' - no journal device.
*/
out:
*status = s;
while (i-- > 0)
if (s->dev_health[i] == 'a')
a++; /* Count number of 'a' */
if (s->insync_regions == s->total_regions) {
/* FIXME: kernel gives misleading info here
* Trying to recognize a true state */
while (i-- > 0)
if (s->dev_health[i] == 'a')
a++; /* Count number of 'a' */
if (a) {
if ((a < s->dev_count) && /* SOME legs are in 'a' */
/* FIXME: kernel gives misleading info here
* Trying to recognize a true state */
(s->insync_regions == s->total_regions) &&
(!strcasecmp(s->sync_action, "recover") ||
!strcasecmp(s->sync_action, "idle"))) {
/* Kernel may possibly start some action
* in near-by future, do not report 100% */
s->insync_regions--;
}
if ((a == s->dev_count) && /* all legs are in 'a' */
(!strcasecmp(s->sync_action, "resync") ||
!strcasecmp(s->sync_action, "idle"))) {
/* Mark 1st. leg in sync */
s->dev_health[0] = 'A';
if (a && a < s->dev_count) {
/* SOME legs are in 'a' */
if (!strcasecmp(s->sync_action, "recover")
|| !strcasecmp(s->sync_action, "idle"))
/* Kernel may possibly start some action
* in near-by future, do not report 100% */
s->insync_regions--;
}
}
@ -528,21 +511,6 @@ int dm_get_status_thin(struct dm_pool *mem, const char *params,
return 1;
}
static dm_status_mirror_health_t _get_health(char c)
{
switch (c) {
case 'A': return DM_STATUS_MIRROR_ALIVE;
case 'F': return DM_STATUS_MIRROR_FLUSH_FAILED;
case 'D': return DM_STATUS_MIRROR_WRITE_FAILED;
case 'S': return DM_STATUS_MIRROR_SYNC_FAILED;
case 'R': return DM_STATUS_MIRROR_READ_FAILED;
default:
log_warn("WARNING: Unknown mirror health status char: %c", c);
/* fall through */
case 'U': return DM_STATUS_MIRROR_UNCLASSIFIED;
}
}
/*
* dm core parms: 0 409600 mirror
* Mirror core parms: 2 253:4 253:5 400/400
@ -596,7 +564,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
pos += used;
for (i = 0; i < num_devs ; ++i)
s->devs[i].health = _get_health(pos[i]);
s->devs[i].health = pos[i];
if (!(pos = _skip_fields(pos, argc)))
goto_out;
@ -641,7 +609,7 @@ int dm_get_status_mirror(struct dm_pool *mem, const char *params,
goto_out;
for (i = 0; i < s->log_count; ++i)
s->logs[i].health = _get_health(pos[i]);
s->logs[i].health = pos[i];
}
}

View File

@ -81,6 +81,7 @@ struct dm_vdo_target_params {
uint32_t block_map_era_length; // format period
uint32_t block_map_period; // supported alias
};
uint32_t check_point_frequency;
uint32_t index_memory_size_mb; // format
uint32_t slab_size_mb; // format

View File

@ -128,14 +128,6 @@ struct vdo_volume_geometry {
struct vdo_index_config index_config;
} __packed;
struct vdo_volume_geometry_4 {
uint32_t release_version;
uint64_t nonce;
uuid_t uuid;
struct vdo_volume_region regions[VDO_VOLUME_REGION_COUNT];
struct vdo_index_config index_config;
} __packed;
/* Decoding mostly only some used stucture members */
static void _vdo_decode_version(struct vdo_version_number *v)
@ -154,24 +146,13 @@ static void _vdo_decode_header(struct vdo_header *h)
static void _vdo_decode_geometry_region(struct vdo_volume_region *vr)
{
vr->id = le32_to_cpu(vr->id);
vr->start_block = le64_to_cpu(vr->start_block);
vr->start_block = le32_to_cpu(vr->start_block);
}
static void _vdo_decode_volume_geometry(struct vdo_volume_geometry *vg)
{
vg->release_version = le32_to_cpu(vg->release_version);
vg->release_version = le64_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 = 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]);
}
@ -193,8 +174,9 @@ static void _vdo_decode_pvc(struct vdo_component_41_0 *pvc)
bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
{
char buffer[4096];
int fh;
int fh, n;
bool r = false;
off_t l;
struct stat st;
uint64_t size;
uint64_t regpos;
@ -202,7 +184,6 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
struct vdo_header h;
struct vdo_version_number vn;
struct vdo_volume_geometry vg;
struct vdo_volume_geometry_4 vg_4;
struct vdo_component_41_0 pvc;
*logical_blocks = 0;
@ -226,7 +207,7 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
size = st.st_size;
}
if (read(fh, buffer, sizeof(buffer)) < 0) {
if ((n = read(fh, buffer, sizeof(buffer))) < 0) {
log_sys_debug("read", vdo_path);
goto err;
}
@ -239,42 +220,32 @@ bool dm_vdo_parse_logical_size(const char *vdo_path, uint64_t *logical_blocks)
memcpy(&h, buffer + MAGIC_NUMBER_SIZE, sizeof(h));
_vdo_decode_header(&h);
if (h.id != 5) {
log_debug_activation("Expected geometry VDO block instead of block %u.", h.id);
goto err;
}
switch (h.version.major_version) {
case 4:
memcpy(&vg_4, buffer + MAGIC_NUMBER_SIZE + sizeof(h), sizeof(vg_4));
_vdo_decode_volume_geometry_4(&vg, &vg_4);
break;
case 5:
memcpy(&vg, buffer + MAGIC_NUMBER_SIZE + sizeof(h), sizeof(vg));
_vdo_decode_volume_geometry(&vg);
break;
default:
if (h.version.major_version != 5) {
log_debug_activation("Unsupported VDO version %u.%u.", h.version.major_version, h.version.minor_version);
goto err;
}
regpos = (vg.regions[VDO_DATA_REGION].start_block - vg.bio_offset) * 4096;
memcpy(&vg, buffer + MAGIC_NUMBER_SIZE + sizeof(h), sizeof(vg));
_vdo_decode_volume_geometry(&vg);
regpos = vg.regions[VDO_DATA_REGION].start_block * 4096;
if ((regpos + sizeof(buffer)) > size) {
log_debug_activation("File/Device is shorter and can't provide requested VDO volume region at " FMTu64 " > " FMTu64 ".", regpos, size);
goto err;
}
if (lseek(fh, regpos, SEEK_SET) < 0) {
if ((l = lseek(fh, regpos, SEEK_SET)) < 0) {
log_sys_debug("lseek", vdo_path);
goto err;
}
if (read(fh, buffer, sizeof(buffer)) < 0) {
if ((n = read(fh, buffer, sizeof(buffer))) < 0) {
log_sys_debug("read", vdo_path);
goto err;
}
memcpy(&vn, buffer + sizeof(struct vdo_geometry_block), sizeof(vn));
_vdo_decode_version(&vn);

View File

@ -1,24 +0,0 @@
# Common problems
## Duplicate PVs in the system
LVM tries to detect the common sources of duplicates, mdadm RAID and multipath,
there are cases where duplicate PV appears on the system.
There are two solutions to this problem:
* Setting a *global_filter* configuration option.
* Using of *devices_file* (See [lvmdevices(8)](https://man7.org/linux/man-pages/man8/lvmdevices.8.html))
## Device Filtering
*filter* and *global_filter* are meant to be used in two ways:
* as an allow list, listing patterns for devices which will be accepted
* `a|/dev/sdX|`, and rejecting the rest `r|.*|`,
* as a reject list, listing only patterns for devices which will be rejected
* `r|/dev/sdX|`,
Even though there are situations where it works, mixing reject and accept
patterns is not recommended.

View File

@ -1,34 +0,0 @@
LVM2 Wiki Documentation
=======================
If you are looking for information about LVM2 visit the [[Index]] page,
There are only some notes about writing stuff under *./doc* here:
* If possible use [[MarkDown]] for formatting, use *.md* (or *.mdwn*) suffix.
* For linking between files, use [[IkiWiki]] syntax `[[FileName]]` or
`[[FileName#Anchor]]`, or `[[link text|FileName]]`
Markdown
--------
* Use `<!-- comment -->` to keep notes, which will not be rendered.
* Use `[[TODO]]` for anything what needs attention. This will be accessible
through the linked [[TODO]] page.
IkiWiki
-------
* Install ikiwiki:
yum install ikiwiki
* To generate the content, run following in the LVM2 top directory:
ikiwiki --setup ikiwiki.setup
Internal Stuff:
---------------
* [[TODO]] Can we have a section which is hidden by default? Like this one?
* [[TODO]] Add basic IkiWiki and MarkDown How To.

View File

@ -1,152 +0,0 @@
# LVM - Logical Volume Manager for Linux
<!--
* TODO: Add banner for Important News: Critical Bugs, Important Announcements,...
-->
<!--
* TODO: Add a feed for latest articles/release-notes on the right
-->
<!--
## About LVM2
-->
LVM aka LVM2 refers to the userspace toolset that provide logical volume
management facilities on linux.
<!--
It is reasonably backwards-compatible with the
original LVM1 toolset.
* TODO: Add information about LVM1 metadata format conversion!
-->
LVM offers more flexibility than using partitions, allowing one to
* grow and, where supported by filesystem, shrink volumes,
* create snapshots of existing volumes,
* mirror data on multiple disks including RAID levels 5 or 6,
* striping data on multiple disks,
* create a read or write cache.
To use LVM2 you need 3 things:
* [device-mapper](https://sourceware.org/dm/) in your kernel (upstream since long ago)
* the userspace device-mapper support library (*libdevmapper*) (part of lvm2)
* and the userspace LVM2 tools.
## Getting LVM
Most of linux distribution offer packaged LVM tools.
Depending on your distribution use
# RPM based distributions (Fedora):
yum install lvm2
# DEB based distributions (Debian, Ubuntu):
apt-get install lvm2
Tarballs of the userspace LVM2 source code releases are available from [sourceware.org](https://sourceware.org/pub/lvm2/) [ftp](ftp://sourceware.org/pub/lvm2/).
List of official [mirror sites](https://sourceware.org/mirrors.html) (including http and rsync protocols).
### LVM Releases
[[!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]]
## Getting Started
<!--
TODO: We are missing a lvm(7) man page explaining this, I think it would be a nic addition!
And perhaps so would be a lvmtroubleshooting(7) guide.
-->
Word of warning first! Even though LVM errs on the side of data safety it is a
tool with low level access and one may seriously harm their data when used
incorrectly!
* Physical Volume (PV) is underlying disk, local or remote, encrypted or even
a mdadm RAID volume. PV is divided into so called Physical Extents (PE) which
are a basic allocation unit.
List PVs using [pvs(8)](https://man7.org/linux/man-pages/man8/pvs.8.html) or
[pvdisplay(8)](https://man7.org/linux/man-pages/man8/pvdisplay.8.html).
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).
Make one by running `vgcreate VGNAME /dev/sdX...`, add PVs to existing one by `vgextend VGNAME /dev/sdX`.
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 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 [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
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
correct order.
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!
## Documentation
## Resolving Problems
* Backup if possible!
* Search the problem first, check the list of [[common problems|Problems]]
* Never run `fsck` on damaged LV, LV must be recovered first!
* When asking for help describe exactly how the system got corrupted. It really
does not help trying to cover one's mistakes in such situation, it takes
longer to get help and also you are likely to get wrong answer making repair
impossible.
## Reporting Bugs
* When you find a problem there is often something specific about your system.
If the problem is reproducible run the failing command(s) with verbose flag
`-vvvv` which gives developers clue where the problem might be.
There is a [lvmdump(8)](https://man7.org/linux/man-pages/man8/lvmdump.8.html)
tool to help collect data about your system, block devices and LVM setup.
* Please report upstream bugs or request features in [Red Hat Bugzilla](https://bugzilla.redhat.com/enter_bug.cgi?product=LVM%20and%20device-mapper)
<!--
TODO:
* Add links to other documentation
* Add links to git
* Add links to mailing lists
* Resolving problems
* Backup if possible!
* Newer run fsck! Do the research first!
* List of Common issues
* Resizing in wrong order
* Thin pool running out of space
* Configuration - duplicates
* Mailing list
* IRC?
* Reporting Bugs
* sosreport/lvmdump
* BZ
* Contributing
* gitlab MR
* Add latest articles
-->

View File

@ -1,4 +0,0 @@
.page {
max-width: 1280px;
margin: auto;
}

View File

@ -51,5 +51,3 @@ In future optional target flags will be given in two situations:
This decision could well be contentious, so could distro maintainers feel
free to comment.
[[!tag legacy]]

View File

@ -1,76 +0,0 @@
<!-- Page title -->
[[!meta title="Version 2.03.24 - Feature and Bug Fix Release"]]
Version 2.03.24
===============
* **Changes in udev rules, new version of systemd is recommended (256).**
* **When using LVs as PVs these are no longer auto activated!**
* Allow creating VDO device for thin data when creating thin pool.
* More devices can be used as external origin for thin snapshot.
* And [[!toggle text="more"]]
[[!toggleable text="""
Features
-----------------------
* Swap properties like hostname, date and time when swapping LVs.
* Allow thin snapshot taken of thin volume from another pool as external origin.
* Allow chaining of external origins.
### Changes to device handling
* **IMPORTANT:** When `devices/scan_lvs` is enabled found LVs are no longer auto
activated, must enable `LVM_PVSCAN_ON_LVS` in udev rules (*69-dm-lvm.rules*.)
* NOTE: It is not recommended to use LVs for PVs. If you have an use case for
this talk to us, please.
* Changes to devices file are now backed up in */etc/lvm/devices/backup/*.
Controlled by `devices/devicesfile_backup_limit` configuration option.
* When `devices/use_devicesfile` is set to `0` existing file is renamed to
*system.devices-unused.YYYYMMDD.HHMMSS* to prevent outdated file to be used
on reenabling.
### Use VDO device for thin pool's data
New option `--pooldatavdo` during lvcreate or lvconvert allows using VDO as backing device.
More options (`--compression {y|n}`, `--deduplication {y|n}`,
`--vdosettings STRING`) to control the options are supported by these commands.
Example of converting a *lvol1* to a thin pool with enabled compression and deduplication:
lvconvert --type thin-pool --pooldatavdo y vg/lvol1
Changes in command line
-----------------------
* Add *--wipesignature* option controlling signature wiping when converting volume to thin-pool.
* Allow *lvcreate --snapshot* without *{-T|--thin}* option when creating snapshot of a thin volume.
* Allow *--raidintegrity{,mode,blocksize}* options with implicit RAID1 (i.e. when *-m1* is used on command line)
./configure options
-------------------
These changes are for packagers:
* Add `--with-default-event-activation` option controlling default for
`global/event_activation`. Default value is unchanged. Useful when creating
builds for testing.
* Add `--with-modulesdir` option.
Changes in udev rules
---------------------
**IMPORTANT:** Rework of udev rules in cooperation with systemd is included in this release.
* `DM_SUSPENDED` and `DM_NOSCAN` are now entirely internal for DM and cannot be used outside of DM rules.
* Upper level rules should consume `DM_UDEV_DISABLE_OTHER_RULES_FLAG` rather than `DM_NOSCAN` and `DM_SUSPENDED`.
Also few more minor improvements:
* Better handling of `DISK_RO` events and suspended devices
"""]]
[[!tag]]
[[!meta date="Thu May 16 12:12:06 2024 +0200"]]

View File

@ -1,22 +0,0 @@
<!-- Page title -->
[[!meta title="Version 2.03.25 - Feature and Bug Fix Release"]]
Version 2.03.25
===============
* Add `vgimportdevices --rootvg [--auto]` adding devices from root VG to devices file.
* Add `lvm-devices-import.{path,service}` service using the above to initialize devices file.
* Handle pruning ids from devices file when lvremove is called and a PV is on top of the LV.
* Change device cache data structures and caching to speed up operations with many LVs.
* Fix infinite loop in lvm shell completion causing out of memory issue (2.03.24).
* Allow forced change of locktype from none.
* Handle OPTIONS defined in /etc/sysconfig/lvmlockd.
* And as usually some clean up, static analysis fixes, etc.
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag draft pending]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
-->

View File

@ -1,9 +0,0 @@
# LVM Releases
This list is incomplete, only releases with a release-note are included.
For releases of legacy branch *2.02* see [[legacy]].
Too see what's cooking see [[pending]].
[[!inline pages="release-notes/2.03.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" rootpage="release-notes"]]

View File

@ -1,8 +0,0 @@
# Legacy 2.02 Releases
This list is incomplete, only releases with a release-note are included.
For releases of stable branch 2.03 see [[index]].
[[!inline pages="release-notes/2.02.* and !*/template and !*/Discussion and !tagged(draft) and !tagged(pending)" limit=2 rootpage="release-notes"]]

View File

@ -1,3 +0,0 @@
# Pending Release
[[!inline pages="release-notes/* and !*/template and !*/Discussion and tagged(pending)" rootpage="release-notes"]]

View File

@ -1,52 +0,0 @@
<!-- Page title -->
[[!meta title="Version 2.03. - Feature and Bug Fix Release"]]
Version 2.03.
===============
* List of important/interesting changes
* And [[!toggle text="more"]]
[[!toggleable text="""
Features
-----------------------
* List new features worth mentioning here in one line.
### New Feature Worth a Paragraph or Two
Write a paragraph or two covering feature where some examples of usage are expected.
<!--
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
-----------------------
Describe important changes in command line tools, especially any chnages of behavior, which user must be aware of:
* New options
* Removed options
* Use a separate page in *./doc* for larger features worth separate article, or a man page
Changes in lvm.conf
-------------------
* New options.
* Change of defaults.
./configure options
-------------------
* New options and features the enable.
"""]]
<!-- remove the pending tag on release, remove draft tag once editing is complete -->
[[!tag draft pending]]
<!--
For old releases add Release Timestamp like this, date from git show $COMMIT is fine.
\[[!meta date="Tue Nov 21 14:26:07 2023 +0100"]]
-->

View File

@ -1,420 +0,0 @@
# IkiWiki::Setup::Yaml - YAML formatted setup file
#
# Setup file for ikiwiki.
#
# Passing this to ikiwiki --setup will make ikiwiki generate
# wrappers and build the wiki.
#
# Remember to re-run ikiwiki --setup any time you edit this file.
#
# name of the wiki
wikiname: LVM
# contact email for wiki
#adminemail: me@example.com
# users who are wiki admins
adminuser: []
# users who are banned from the wiki
banned_users: []
# where the source of the wiki is located
srcdir: ./doc
# where to build the wiki
destdir: ./public
# base url to the wiki
url: https://sourceware.org/lvm2/
# url to the ikiwiki.cgi
cgiurl: ''
# do not adjust cgiurl if CGI is accessed via different URL
reverse_proxy: 0
# filename of cgi wrapper to generate
cgi_wrapper: ''
# mode for cgi_wrapper (can safely be made suid)
cgi_wrappermode: 06755
# number of seconds to delay CGI requests when overloaded
cgi_overload_delay: ''
# message to display when overloaded (may contain html)
cgi_overload_message: ''
# enable optimization of only refreshing committed changes?
only_committed_changes: 0
# rcs backend to use
rcs: ''
# plugins to add to the default configuration
add_plugins:
- sidebar
- tag
- toggle
# plugins to disable
disable_plugins: []
# additional directory to search for template files
templatedir: /usr/share/ikiwiki/templates
# base wiki source location
underlaydir: /usr/share/ikiwiki/basewiki
# display verbose messages?
#verbose: 1
# log to syslog?
#syslog: 1
# create output files named page/index.html?
usedirs: 1
# use '!'-prefixed preprocessor directives?
prefix_directives: 1
# use page/index.mdwn source files
indexpages: 0
# enable Discussion pages?
discussion: 1
# name of Discussion pages
discussionpage: Discussion
# use elements new in HTML5 like <section>?
html5: 0
# only send cookies over SSL connections?
sslcookie: 0
# extension to use for new pages
default_pageext: mdwn
# extension to use for html files
htmlext: html
# strftime format string to display date
timeformat: '%c'
# UTF-8 locale to use
#locale: en_US.UTF-8
# put user pages below specified page
userdir: ''
# how many backlinks to show before hiding excess (0 to show all)
numbacklinks: 10
# attempt to hardlink source files? (optimisation for large files)
hardlink: 0
# force ikiwiki to use a particular umask (keywords public, group or private, or a number)
#umask: public
# group for wrappers to run in
#wrappergroup: ikiwiki
# extra library and plugin directories
libdirs: []
# extra library and plugin directory (searched after libdirs)
libdir: ''
# environment variables
ENV: {}
# time zone name
timezone: :/etc/localtime
# regexp of normally excluded files to include
#include: ^\.htaccess$
# regexp of files that should be skipped
#exclude: ^(*\.private|Makefile)$
# specifies the characters that are allowed in source filenames
wiki_file_chars: -[:alnum:]+/.:_
# allow symlinks in the path leading to the srcdir (potentially insecure)
allow_symlinks_before_srcdir: 0
# cookie control
cookiejar:
file: /home/mcsontos/.ikiwiki/cookies
# set custom user agent string for outbound HTTP requests e.g. when fetching aggregated RSS feeds
useragent: ikiwiki/3.20200202.3
# theme has a responsive layout? (mobile-optimized)
responsive_layout: 1
# try harder to produce deterministic output
deterministic: 0
######################################################################
# core plugins
# (editpage, htmlscrubber, inline, link, meta, parentlinks, templatebody)
######################################################################
# htmlscrubber plugin
# PageSpec specifying pages not to scrub
#htmlscrubber_skip: '!*/Discussion'
# inline plugin
# enable rss feeds by default?
#rss: 0
# enable atom feeds by default?
#atom: 0
# allow rss feeds to be used?
#allowrss: 0
# allow atom feeds to be used?
#allowatom: 0
# urls to ping (using XML-RPC) on feed update
pingurl: []
######################################################################
# auth plugins
# (anonok, blogspam, emailauth, httpauth, lockedit, moderatedcomments,
# opendiscussion, openid, passwordauth, signinedit)
######################################################################
# anonok plugin
# PageSpec to limit which pages anonymous users can edit
#anonok_pagespec: '*/discussion'
# blogspam plugin
# PageSpec of pages to check for spam
#blogspam_pagespec: postcomment(*)
# options to send to blogspam server
#blogspam_options: blacklist=1.2.3.4,blacklist=8.7.6.5,max-links=10
# blogspam server JSON url
#blogspam_server: ''
# emailauth plugin
# email address to send emailauth mails as (default: adminemail)
#emailauth_sender: ''
# httpauth plugin
# url to redirect to when authentication is needed
#cgiauthurl: http://example.com/wiki/auth/ikiwiki.cgi
# PageSpec of pages where only httpauth will be used for authentication
#httpauth_pagespec: '!*/Discussion'
# lockedit plugin
# PageSpec controlling which pages are locked
#locked_pages: '!*/Discussion'
# moderatedcomments plugin
# PageSpec matching users or comment locations to moderate
#moderate_pagespec: '*'
# openid plugin
# url pattern of openid realm (default is cgiurl)
#openid_realm: ''
# url to ikiwiki cgi to use for openid authentication (default is cgiurl)
#openid_cgiurl: ''
# passwordauth plugin
# a password that must be entered when signing up for an account
#account_creation_password: s3cr1t
# cost of generating a password using Authen::Passphrase::BlowfishCrypt
#password_cost: 8
######################################################################
# format plugins
# (creole, highlight, hnb, html, mdwn, otl, po, rawhtml, textile, txt)
######################################################################
# highlight plugin
# types of source files to syntax highlight
#tohighlight: .c .h .cpp .pl .py Makefile:make
# location of highlight's filetypes.conf
#filetypes_conf: /etc/highlight/filetypes.conf
# location of highlight's langDefs directory
#langdefdir: /usr/share/highlight/langDefs
# mdwn plugin
# enable multimarkdown features?
#multimarkdown: 0
# disable use of markdown discount?
#nodiscount: 0
# enable footnotes in Markdown (where supported)?
mdwn_footnotes: 1
# interpret line like 'A. First item' as ordered list when using Discount?
mdwn_alpha_lists: 0
# po plugin
# master language (non-PO files)
#po_master_language: en|English
# slave languages (translated via PO files) format: ll|Langname
#po_slave_languages:
#- fr|Français
#- es|Español
#- de|Deutsch
# PageSpec controlling which pages are translatable
#po_translatable_pages: '* and !*/Discussion'
# internal linking behavior (default/current/negotiated)
#po_link_to: current
######################################################################
# special-purpose plugins
# (osm, underlay)
######################################################################
# osm plugin
# the default zoom when you click on the map link
#osm_default_zoom: 15
# the icon shown on links and on the main map
#osm_default_icon: ikiwiki/images/osm.png
# the alt tag of links, defaults to empty
#osm_alt: ''
# the output format for waypoints, can be KML, GeoJSON or CSV (one or many, comma-separated)
#osm_format: KML
# the icon attached to a tag, displayed on the map for tagged pages
#osm_tag_default_icon: icon.png
# Url for the OpenLayers.js file
#osm_openlayers_url: http://www.openlayers.org/api/OpenLayers.js
# Layers to use in the map. Can be either the 'OSM' string or a type option for Google maps (GoogleNormal, GoogleSatellite, GoogleHybrid or GooglePhysical). It can also be an arbitrary URL in a syntax acceptable for OpenLayers.Layer.OSM.url parameter.
#osm_layers:
# OSM: GoogleSatellite
# Google maps API key, Google layer not used if missing, see https://code.google.com/apis/console/ to get an API key
#osm_google_apikey: ''
# underlay plugin
# extra underlay directories to add
#add_underlays:
#- /home/mcsontos/wiki.underlay
######################################################################
# web plugins
# (404, attachment, comments, editdiff, edittemplate, getsource, google,
# goto, mirrorlist, remove, rename, repolist, search, theme, userlist,
# websetup, wmd)
######################################################################
# attachment plugin
# enhanced PageSpec specifying what attachments are allowed
#allowed_attachments: virusfree() and mimetype(image/*) and maxsize(50kb)
# virus checker program (reads STDIN, returns nonzero if virus found)
#virus_checker: clamdscan -
# comments plugin
# PageSpec of pages where comments are allowed
#comments_pagespec: blog/* and !*/Discussion
# PageSpec of pages where posting new comments is not allowed
#comments_closed_pagespec: blog/controversial or blog/flamewar
# Base name for comments, e.g. "comment_" for pages like "sandbox/comment_12"
#comments_pagename: ''
# Interpret directives in comments?
#comments_allowdirectives: 0
# Allow anonymous commenters to set an author name?
#comments_allowauthor: 0
# commit comments to the VCS
#comments_commit: 1
# Restrict formats for comments to (no restriction if empty)
#comments_allowformats: mdwn txt
# getsource plugin
# Mime type for returned source.
#getsource_mimetype: text/plain; charset=utf-8
# mirrorlist plugin
# list of mirrors
#mirrorlist: {}
# generate links that point to the mirrors' ikiwiki CGI
#mirrorlist_use_cgi: 1
# repolist plugin
# URIs of repositories containing the wiki's source
#repositories:
#- svn://svn.example.org/wiki/trunk
# search plugin
# path to the omega cgi program
#omega_cgi: /usr/lib/cgi-bin/omega/omega
# use google site search rather than internal xapian index?
#google_search: 1
# theme plugin
# name of theme to enable
#theme: actiontabs
# websetup plugin
# list of plugins that cannot be enabled/disabled via the web interface
#websetup_force_plugins: []
# list of additional setup field keys to treat as unsafe
#websetup_unsafe: []
# show unsafe settings, read-only, in web interface?
#websetup_show_unsafe: 1
######################################################################
# widget plugins
# (calendar, color, conditional, cutpaste, date, format, fortune,
# graphviz, haiku, headinganchors, img, linkmap, listdirectives, map,
# more, orphans, pagecount, pagestats, poll, polygen, postsparkline,
# progress, shortcut, sparkline, table, template, teximg, toc, toggle,
# version)
######################################################################
# calendar plugin
# base of the archives hierarchy
#archivebase: archives
# PageSpec of pages to include in the archives, if option `calendar_autocreate` is true.
#archive_pagespec: page(posts/*) and !*/Discussion
# autocreate new calendar pages?
#calendar_autocreate: 1
# if set, when building calendar pages, also build pages of year and month when no pages were published (building empty calendars).
#calendar_fill_gaps: 1
# img plugin
# Image formats to process (jpeg, png, gif, svg, pdf or 'everything' to accept all)
#img_allowed_formats: ''
# listdirectives plugin
# directory in srcdir that contains directive descriptions
#directive_description_dir: ikiwiki/directive
# teximg plugin
# Should teximg use dvipng to render, or dvips and convert?
#teximg_dvipng: ''
# LaTeX prefix for teximg plugin
#teximg_prefix: |
# \documentclass{article}
# \usepackage[utf8]{inputenc}
# \usepackage{amsmath}
# \usepackage{amsfonts}
# \usepackage{amssymb}
# \pagestyle{empty}
# \begin{document}
# LaTeX postfix for teximg plugin
#teximg_postfix: \end{document}
######################################################################
# other plugins
# (aggregate, amazon_s3, autoindex, brokenlinks, camelcase, ddate, embed,
# favicon, filecheck, flattr, goodstuff, htmlbalance, localstyle,
# loginselector, notifyemail, pagetemplate, pingee, pinger, prettydate,
# recentchanges, recentchangesdiff, relativedate, rsync, sidebar,
# smiley, sortnaturally, tag, testpagespec, trail, transient)
######################################################################
# aggregate plugin
# enable aggregation to internal pages?
#aggregateinternal: 1
# allow aggregation to be triggered via the web?
#aggregate_webtrigger: 0
# amazon_s3 plugin
# public access key id
#amazon_s3_key_id: XXXXXXXXXXXXXXXXXXXX
# file holding secret key (must not be readable by others!)
#amazon_s3_key_id: /home/mcsontos/.s3_key
# globally unique name of bucket to store wiki in
#amazon_s3_bucket: mywiki
# a prefix to prepend to each page name
#amazon_s3_prefix: wiki/
# which S3 datacenter to use (leave blank for default)
#amazon_s3_location: EU
# store each index file twice? (allows urls ending in "/index.html" and "/")
#amazon_s3_dupindex: 0
# autoindex plugin
# commit autocreated index pages
#autoindex_commit: 1
# camelcase plugin
# list of words to not turn into links
#camelcase_ignore: []
# flattr plugin
# userid or user name to use by default for Flattr buttons
#flattr_userid: joeyh
# pinger plugin
# how many seconds to try pinging before timing out
#pinger_timeout: 15
# prettydate plugin
# format to use to display date
#prettydateformat: '%X, %B %o, %Y'
# recentchanges plugin
# name of the recentchanges page
recentchangespage: recentchanges
# number of changes to track
recentchangesnum: 100
# rsync plugin
# command to run to sync updated pages
#rsync_command: rsync -qa --delete . user@host:/path/to/docroot/
# sidebar plugin
# show sidebar page on all pages?
#global_sidebars: 1
# tag plugin
# parent page tags are located under
#tagbase: tag
# autocreate new tag pages?
#tag_autocreate: 1
# commit autocreated tag pages
#tag_autocreate_commit: 1

View File

@ -1,6 +1,6 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2023 Red Hat, Inc. All rights reserved.
# Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
@ -18,23 +18,23 @@ top_builddir = @top_builddir@
include $(top_builddir)/make.tmpl
.DELETE_ON_ERROR:
cmds.h: $(top_srcdir)/tools/command-lines.in $(top_srcdir)/tools/license.inc Makefile
$(SHOW) " [GEN] $@"
$(Q) \
cmds.h:
@echo " [GEN] $@"
$(Q) set -o pipefail && \
( cat $(top_srcdir)/tools/license.inc && \
echo "/* Do not edit. This file is generated by the Makefile. */" && \
echo "cmd(CMD_NONE, none)" && \
trap "$(RM) $@-t" EXIT INT QUIT TERM && \
$(AWK) '/^ID:/ {print "cmd(" $$2 "_CMD, " $$2 ")"}' $< >$@-t && \
LC_ALL=C $(SORT) -u $@-t && \
$(GREP) '^ID:' $(top_srcdir)/tools/command-lines.in | LC_ALL=C $(SORT) -u | $(AWK) '{print "cmd(" $$2 "_CMD, " $$2 ")"}' && \
echo "cmd(CMD_COUNT, count)" \
) > $@
all: cmds.h
clean:
rm -f cmds.h
DISTCLEAN_TARGETS += configure.h lvm-version.h
CLEAN_TARGETS += cmds.h cmds.h-t \
CLEAN_TARGETS += \
.symlinks \
.symlinks_created \
activate.h \
@ -86,8 +86,6 @@ CLEAN_TARGETS += cmds.h cmds.h-t \
lvm2app.h \
lvm2cmd.h \
lvmcache.h \
lvmetad-client.h \
lvmetad.h \
lvmlockd-client.h \
lvmlockd.h \
lvmnotify.h \

View File

@ -25,7 +25,7 @@
/* The path to 'cache_restore', if available. */
#undef CACHE_RESTORE_CMD
/* Define to 1 if the 'closedir' function returns void instead of int. */
/* Define to 1 if the `closedir' function returns void instead of int. */
#undef CLOSEDIR_VOID
/* Path to cmirrord pidfile. */
@ -43,9 +43,6 @@
/* Name of default metadata cache subdirectory. */
#undef DEFAULT_CACHE_SUBDIR
/* Path to exit-on dmeventd file. */
#undef DEFAULT_DMEVENTD_EXIT_ON_PATH
/* Define default node creation behavior with dmsetup create */
#undef DEFAULT_DM_ADD_NODE
@ -58,9 +55,6 @@
/* Default system configuration directory. */
#undef DEFAULT_ETC_DIR
/* Default for lvm.conf event_activation. */
#undef DEFAULT_EVENT_ACTIVATION
/* Name of default locking directory. */
#undef DEFAULT_LOCK_DIR
@ -70,9 +64,6 @@
/* Default directory to keep PID files in. */
#undef DEFAULT_PID_DIR
/* Path to /proc. */
#undef DEFAULT_PROC_DIR
/* Name of default configuration profile subdirectory. */
#undef DEFAULT_PROFILE_SUBDIR
@ -142,7 +133,7 @@
/* Define to use GNU versioning in the shared library. */
#undef GNU_SYMVER
/* Define to 1 if you have the 'alarm' function. */
/* Define to 1 if you have the `alarm' function. */
#undef HAVE_ALARM
/* Define to 1 if you have 'alloca', as a function or macro. */
@ -160,28 +151,25 @@
/* Define to 1 if you have the <assert.h> header file. */
#undef HAVE_ASSERT_H
/* Define to 1 if you have the 'atexit' function. */
/* Define to 1 if you have the `atexit' function. */
#undef HAVE_ATEXIT
/* Define if blkid.h has BLKID_SUBLKS_FSINFO */
#undef HAVE_BLKID_SUBLKS_FSINFO
/* Define if ioctl BLKZEROOUT can be used for device zeroing. */
#undef HAVE_BLKZEROOUT
/* Define to 1 if canonicalize_file_name is available. */
#undef HAVE_CANONICALIZE_FILE_NAME
/* Define to 1 if your system has a working 'chown' function. */
/* Define to 1 if your system has a working `chown' function. */
#undef HAVE_CHOWN
/* Define to 1 if you have the 'clock_gettime' function. */
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* Define to 1 if you have the <ctype.h> header file. */
#undef HAVE_CTYPE_H
/* Define to 1 if you have the declaration of 'strerror_r', and to 0 if you
/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
don't. */
#undef HAVE_DECL_STRERROR_R
@ -191,7 +179,7 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you don't have 'vprintf' but do have '_doprnt.' */
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
/* Define to 1 if you have the <editline/readline.h> header file. */
@ -203,19 +191,19 @@
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the 'ffs' function. */
/* Define to 1 if you have the `ffs' function. */
#undef HAVE_FFS
/* Define to 1 if you have the <float.h> header file. */
#undef HAVE_FLOAT_H
/* Define to 1 if you have the 'fork' function. */
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
/* Define to 1 if you have the 'ftruncate' function. */
/* Define to 1 if you have the `ftruncate' function. */
#undef HAVE_FTRUNCATE
/* Define to 1 if you have the 'gethostname' function. */
/* Define to 1 if you have the `gethostname' function. */
#undef HAVE_GETHOSTNAME
/* Define to 1 if getline is available. */
@ -227,10 +215,10 @@
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the 'getpagesize' function. */
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE
/* Define to 1 if you have the 'gettimeofday' function. */
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */
@ -269,60 +257,60 @@
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define to 1 if you have the 'localtime_r' function. */
/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define to 1 if 'lstat' has the bug that it succeeds when given the
/* Define to 1 if `lstat' has the bug that it succeeds when given the
zero-length file name argument. */
#undef HAVE_LSTAT_EMPTY_STRING_BUG
/* Define to 1 if you have the <machine/endian.h> header file. */
#undef HAVE_MACHINE_ENDIAN_H
/* Define to 1 if you have the 'mallinfo2' function. */
/* Define to 1 if you have the `mallinfo2' function. */
#undef HAVE_MALLINFO2
/* Define to 1 if your system has a GNU libc compatible 'malloc' function, and
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
/* Define to 1 if you have the 'memchr' function. */
/* Define to 1 if you have the `memchr' function. */
#undef HAVE_MEMCHR
/* Define to 1 if you have the 'memset' function. */
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define to 1 if you have the 'mkdir' function. */
/* Define to 1 if you have the `mkdir' function. */
#undef HAVE_MKDIR
/* Define to 1 if you have the 'mkfifo' function. */
/* Define to 1 if you have the `mkfifo' function. */
#undef HAVE_MKFIFO
/* Define to 1 if you have a working 'mmap' system call. */
/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define to 1 if you have the 'munmap' function. */
/* Define to 1 if you have the `munmap' function. */
#undef HAVE_MUNMAP
/* Define to 1 if you have the <ndir.h> header file, and it defines 'DIR'. */
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
/* Define to 1 if you have the 'nl_langinfo' function. */
/* Define to 1 if you have the `nl_langinfo' function. */
#undef HAVE_NL_LANGINFO
/* Define to 1 if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
/* Define to 1 if you have the 'prlimit' function. */
/* Define to 1 if you have the `prlimit' function. */
#undef HAVE_PRLIMIT
/* Define to 1 if you have the 'pselect' function. */
/* Define to 1 if you have the `pselect' function. */
#undef HAVE_PSELECT
/* Define to 1 if the system has the type 'ptrdiff_t'. */
/* Define to 1 if the system has the type `ptrdiff_t'. */
#undef HAVE_PTRDIFF_T
/* Define to 1 if you have the <readline/history.h> header file. */
@ -331,20 +319,20 @@
/* Define to 1 if you have the <readline/readline.h> header file. */
#undef HAVE_READLINE_READLINE_H
/* Define to 1 if your system has a GNU libc compatible 'realloc' function,
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#undef HAVE_REALLOC
/* Define to 1 if you have the 'realpath' function. */
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
/* Define to 1 to include support for realtime clock. */
#undef HAVE_REALTIME
/* Define to 1 if you have the 'rl_completion_matches' function. */
/* Define to 1 if you have the `rl_completion_matches' function. */
#undef HAVE_RL_COMPLETION_MATCHES
/* Define to 1 if you have the 'rmdir' function. */
/* Define to 1 if you have the `rmdir' function. */
#undef HAVE_RMDIR
/* Define to 1 to include support for selinux. */
@ -359,16 +347,16 @@
/* Define to 1 if sepol_check_context is available. */
#undef HAVE_SEPOL
/* Define to 1 if you have the 'setenv' function. */
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define to 1 if you have the 'setlocale' function. */
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
/* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
/* Define to 1 if 'stat' has the bug that it succeeds when given the
/* Define to 1 if `stat' has the bug that it succeeds when given the
zero-length file name argument. */
#undef HAVE_STAT_EMPTY_STRING_BUG
@ -393,22 +381,22 @@
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the 'strcasecmp' function. */
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the 'strchr' function. */
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the 'strcspn' function. */
/* Define to 1 if you have the `strcspn' function. */
#undef HAVE_STRCSPN
/* Define to 1 if you have the 'strdup' function. */
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the 'strerror' function. */
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define if you have 'strerror_r'. */
/* Define if you have `strerror_r'. */
#undef HAVE_STRERROR_R
/* Define to 1 if you have the <strings.h> header file. */
@ -417,47 +405,47 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the 'strncasecmp' function. */
/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP
/* Define to 1 if you have the 'strndup' function. */
/* Define to 1 if you have the `strndup' function. */
#undef HAVE_STRNDUP
/* Define to 1 if you have the 'strpbrk' function. */
/* Define to 1 if you have the `strpbrk' function. */
#undef HAVE_STRPBRK
/* Define to 1 if you have the 'strrchr' function. */
/* Define to 1 if you have the `strrchr' function. */
#undef HAVE_STRRCHR
/* Define to 1 if you have the 'strspn' function. */
/* Define to 1 if you have the `strspn' function. */
#undef HAVE_STRSPN
/* Define to 1 if you have the 'strstr' function. */
/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if you have the 'strtol' function. */
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define to 1 if you have the 'strtoul' function. */
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
/* Define to 1 if you have the 'strtoull' function. */
/* Define to 1 if you have the `strtoull' function. */
#undef HAVE_STRTOULL
/* Define to 1 if 'st_blocks' is a member of 'struct stat'. */
/* Define to 1 if `st_blocks' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLOCKS
/* Define to 1 if 'st_rdev' is a member of 'struct stat'. */
/* Define to 1 if `st_rdev' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_RDEV
/* Define to 1 if your 'struct stat' has 'st_blocks'. Deprecated, use
'HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use
`HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
#undef HAVE_ST_BLOCKS
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/dir.h> header file, and it defines 'DIR'.
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_DIR_H
@ -479,7 +467,7 @@
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines 'DIR'.
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_NDIR_H
@ -522,7 +510,7 @@
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define to 1 if you have the 'uname' function. */
/* Define to 1 if you have the `uname' function. */
#undef HAVE_UNAME
/* Define to 1 if you have the <unistd.h> header file. */
@ -531,25 +519,25 @@
/* valgrind.h found */
#undef HAVE_VALGRIND
/* Define to 1 if you have the 'versionsort' function. */
/* Define to 1 if you have the `versionsort' function. */
#undef HAVE_VERSIONSORT
/* Define to 1 if you have the 'vfork' function. */
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
/* Define to 1 if you have the 'vprintf' function. */
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* Define to 1 if 'fork' works. */
/* Define to 1 if `fork' works. */
#undef HAVE_WORKING_FORK
/* Define to 1 if 'vfork' works. */
/* Define to 1 if `vfork' works. */
#undef HAVE_WORKING_VFORK
/* Define to 1 if the system has the type '_Bool'. */
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
/* Define to 1 if the system has the `__builtin_clz' built-in function */
@ -582,7 +570,7 @@
/* 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
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
slash. */
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
@ -613,11 +601,11 @@
/* Path to lvresize_fs_helper script. */
#undef LVRESIZE_FS_HELPER_PATH
/* Define to 1 if 'major', 'minor', and 'makedev' are declared in <mkdev.h>.
/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
*/
#undef MAJOR_IN_MKDEV
/* Define to 1 if 'major', 'minor', and 'makedev' are declared in
/* Define to 1 if `major', `minor', and `makedev' are declared in
<sysmacros.h>. */
#undef MAJOR_IN_SYSMACROS
@ -627,9 +615,6 @@
/* The path to 'modprobe', if available. */
#undef MODPROBE_CMD
/* The path to kernel modules. */
#undef MODULES_PATH
/* Define to 1 to include code that uses dbus notification. */
#undef NOTIFYDBUS_SUPPORT
@ -671,7 +656,7 @@
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define to 1 if all of the C89 standard headers exist (not just the ones
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
@ -704,10 +689,10 @@
/* The path to 'thin_restore', if available. */
#undef THIN_RESTORE_CMD
/* Define to 1 if your <sys/time.h> declares 'struct tm'. */
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
/* Define to 1 to enable synchronization with udev processing. */
/* Define to 1 to enable synchronisation with udev processing. */
#undef UDEV_SYNC_SUPPORT
/* Enable a valgrind aware build of pool */
@ -743,13 +728,13 @@
#define below would cause a syntax error. */
#undef _UINT8_T
/* Define to empty if 'const' does not conform to ANSI C. */
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define as 'int' if <sys/types.h> doesn't define. */
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
/* Define to '__inline__' or '__inline' if that's what the C compiler
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
@ -774,10 +759,10 @@
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to 'int' if <sys/types.h> does not define. */
/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t
/* Define to 'long int' if <sys/types.h> does not define. */
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
/* Define as a signed integer type capable of holding a process identifier. */
@ -786,13 +771,13 @@
/* Define to rpl_realloc if the replacement function should be used. */
#undef realloc
/* Define as 'unsigned int' if <stddef.h> doesn't define. */
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define as 'int' if <sys/types.h> doesn't define. */
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
/* Define as 'int' if <sys/types.h> doesn't define. */
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
/* Define to the type of an unsigned integer type of width exactly 16 bits if
@ -811,5 +796,5 @@
such a type exists and the standard includes do not define it. */
#undef uint8_t
/* Define as 'fork' if 'vfork' does not work. */
/* Define as `fork' if `vfork' does not work. */
#undef vfork

View File

@ -418,7 +418,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
{
return 0;
}
int dm_device_is_usable(struct cmd_context *cmd, struct device *dev, struct dev_usable_check_params check, int *is_lv)
int device_is_usable(struct cmd_context *cmd, struct device *dev, struct dev_usable_check_params check, int *is_lv)
{
return 0;
}
@ -502,7 +502,7 @@ int driver_version(char *version, size_t size)
!dm_driver_version(_vsn, sizeof(_vsn)))
return_0;
dm_strncpy(version, _vsn, size);
(void) dm_strncpy(version, _vsn, size);
return 1;
}
@ -563,50 +563,12 @@ int lvm_dm_prefix_check(int major, int minor, const char *prefix)
return dev_manager_check_prefix_dm_major_minor(major, minor, prefix);
}
/* Search modules.builtin file for built-in kernel module */
static int _check_modules_builtin(struct cmd_context *cmd, const char *target)
{
FILE *fp;
char *line = NULL;
size_t len;
int r = 0;
char path[PATH_MAX];
if (dm_snprintf(path, sizeof(path), "%s/%s/modules.builtin",
MODULES_PATH, cmd->kernel_vsn) < 0) {
log_debug_activation("Modules path %s/%s/modules.builtin is too long.",
MODULES_PATH, cmd->kernel_vsn);
return 0;
}
if (!(fp = fopen(path, "r"))) {
if (errno != ENOENT)
log_sys_debug("fopen", path);
return 0;
}
while (getline(&line, &len, fp) > 0)
if (strstr(line, target)) {
log_debug_activation("Found %s as built-in kernel module.", target);
r = 1;
break;
}
free(line);
if (fclose(fp))
log_sys_debug("fclose", path);
return r;
}
int module_present(struct cmd_context *cmd, const char *target_name)
{
int ret = 0;
#ifdef MODPROBE_CMD
char module[128];
const char *argv[] = { MODPROBE_CMD, module, NULL };
unsigned maj, min;
#endif
struct stat st;
char path[PATH_MAX];
@ -622,16 +584,11 @@ int module_present(struct cmd_context *cmd, const char *target_name)
log_debug_activation("Module directory %s exists.", path);
return 1;
}
if (path[i] == '/' && _check_modules_builtin(cmd, path + i + 1))
return 1;
}
#ifdef MODPROBE_CMD
if ((strcmp(target_name, TARGET_NAME_VDO) == 0) &&
(sscanf(cmd->kernel_vsn, "%u.%u", &maj, &min) == 2) &&
((maj < 6) || ((maj == 6) && (min < 9))))
argv[1] = MODULE_NAME_VDO; /* Kernels < 6.9 -> "kvdo" without dm- prefix */
if (strcmp(target_name, TARGET_NAME_VDO) == 0)
argv[1] = MODULE_NAME_VDO; /* ATM kvdo is without dm- prefix */
else if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
log_error("module_present module name too long: %s",
target_name);
@ -672,13 +629,13 @@ int target_present(struct cmd_context *cmd, const char *target_name,
&maj, &min, &patchlevel);
}
int get_dm_active_devices(const struct volume_group *vg, struct dm_list **devs,
unsigned *devs_features)
int get_device_list(const struct volume_group *vg, struct dm_list **devs,
unsigned *devs_features)
{
if (!activation())
return 0;
return dev_manager_get_dm_active_devices(NULL, devs, devs_features);
return dev_manager_get_device_list(NULL, devs, devs_features);
}
/*
@ -1442,9 +1399,9 @@ static int _lv_active(struct cmd_context *cmd, const struct logical_volume *lv)
struct lvinfo info;
if (!lv_info(cmd, lv, 0, &info, 0, 0)) {
log_debug_activation("Cannot determine activation status of %s%s.",
display_lvname(lv),
activation() ? "" : " (no device driver)");
log_debug("Cannot determine activation status of %s%s.",
display_lvname(lv),
activation() ? "" : " (no device driver)");
return 0;
}
@ -1649,7 +1606,18 @@ char *get_monitor_dso_path(struct cmd_context *cmd, int id)
static char *_build_target_uuid(struct cmd_context *cmd, const struct logical_volume *lv)
{
return build_dm_uuid(cmd->mem, lv, lv_layer(lv));
const char *layer;
if (lv_is_thin_pool(lv))
layer = "tpool"; /* Monitor "tpool" for the "thin pool". */
else if (lv_is_vdo_pool(lv))
layer = "vpool"; /* Monitor "vpool" for the "VDO pool". */
else if (lv_is_origin(lv) || lv_is_external_origin(lv))
layer = "real"; /* Monitor "real" for "snapshot-origin". */
else
layer = NULL;
return build_dm_uuid(cmd->mem, lv, layer);
}
static int _device_registered_with_dmeventd(struct cmd_context *cmd,
@ -1792,7 +1760,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
struct lv_segment *log_seg;
int (*monitor_fn) (struct lv_segment *s, int e);
uint32_t s;
const struct lv_activate_opts zlaopts = { 0 };
static const struct lv_activate_opts zlaopts = { 0 };
struct lv_activate_opts mirr_laopts = { .origin_only = 1 };
struct lvinfo info;
const char *dso = NULL;
@ -1813,9 +1781,6 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
if (monitor && !dmeventd_monitor_mode())
return 1;
if (sigint_caught())
return_0;
/*
* Activation of unused cache-pool activates metadata device as
* a public LV for clearing purpose.
@ -1873,10 +1838,8 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
* each of its respective snapshots. The origin itself may
* also need to be monitored if it is a mirror, for example,
* so fall through to process it afterwards.
* Before monitoring snapshots verify origin is active as with
* external origin only read-only -real device can be active.
*/
if (!laopts->origin_only && lv_is_origin(lv) && lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
if (!laopts->origin_only && lv_is_origin(lv))
dm_list_iterate_safe(snh, snht, &lv->snapshot_segs)
if (!monitor_dev_for_events(cmd, dm_list_struct_base(snh,
struct lv_segment, origin_list)->cow, NULL, monitor)) {
@ -1897,12 +1860,6 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
}
dm_list_iterate_items(seg, &lv->segments) {
if (sigint_caught()) {
stack;
r = 0;
break;
}
/* Recurse for AREA_LV */
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) != AREA_LV)
@ -2034,11 +1991,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
break;
log_very_verbose("%s %smonitoring still pending: waiting...",
display_lvname(lv), monitor ? "" : "un");
if (interruptible_usleep(10000 * i)) {
stack;
r = 0;
break;
}
usleep(10000 * i);
}
if (r)
@ -2055,7 +2008,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
}
struct detached_lv_data {
const struct volume_group *vg_pre;
const struct logical_volume *lv_pre;
struct lv_activate_opts *laopts;
int *flush_required;
};
@ -2065,17 +2018,40 @@ static int _preload_detached_lv(struct logical_volume *lv, void *data)
struct detached_lv_data *detached = data;
struct logical_volume *lv_pre;
/* Check if the LV was 'hidden' (non-toplevel) in committed metadata
* and becomes 'visible' (toplevel) in precommitted metadata */
if (!lv_is_visible(lv) &&
(lv_pre = find_lv_in_vg_by_lvid(detached->vg_pre, &lv->lvid)) &&
/* Check and preload removed raid image leg or metadata */
if (lv_is_raid_image(lv)) {
if ((lv_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) &&
!lv_is_raid_image(lv_pre) && lv_is_active(lv) &&
!_lv_preload(lv_pre, detached->laopts, detached->flush_required))
return_0;
} else if (lv_is_raid_metadata(lv)) {
if ((lv_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) &&
!lv_is_raid_metadata(lv_pre) && lv_is_active(lv) &&
!_lv_preload(lv_pre, detached->laopts, detached->flush_required))
return_0;
} else if (lv_is_mirror_image(lv)) {
if ((lv_pre = find_lv_in_vg_by_lvid(detached->lv_pre->vg, &lv->lvid)) &&
!lv_is_mirror_image(lv_pre) && lv_is_active(lv) &&
!_lv_preload(lv_pre, detached->laopts, detached->flush_required))
return_0;
}
if (!lv_is_visible(lv) && (lv_pre = find_lv(detached->lv_pre->vg, lv->name)) &&
lv_is_visible(lv_pre)) {
log_debug_activation("Preloading detached hidden volume %s as visible volume %s.",
display_lvname(lv), display_lvname(lv_pre));
if (!_lv_preload(lv_pre, detached->laopts, detached->flush_required))
return_0;
}
/* FIXME: condition here should be far more limiting to really
* detect detached LVs */
if ((lv_pre = find_lv(detached->lv_pre->vg, lv->name))) {
if (lv_is_visible(lv_pre) && lv_is_active(lv) &&
!lv_is_pool(lv) &&
(!lv_is_cow(lv) || !lv_is_cow(lv_pre)) &&
!_lv_preload(lv_pre, detached->laopts, detached->flush_required))
return_0;
}
return 1;
}
@ -2121,13 +2097,9 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
/* Ignore origin_only unless LV is origin in both old and new metadata */
/* or LV is thin or thin pool volume */
if (laopts->origin_only &&
!lv_is_thin_volume(lv) && !lv_is_thin_pool(lv) &&
!(lv_is_origin(lv) && lv_is_origin(lv_pre))) {
log_debug_activation("Not using origin only for suspend of %s.",
display_lvname(lv));
if (!lv_is_thin_volume(lv) && !lv_is_thin_pool(lv) &&
!(lv_is_origin(lv) && lv_is_origin(lv_pre)))
laopts->origin_only = 0;
}
/*
* Preload devices for the LV.
@ -2170,7 +2142,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
/*
* Search for existing LVs that have become detached and preload them.
*/
detached.vg_pre = lv_pre->vg;
detached.lv_pre = lv_pre;
detached.laopts = laopts;
detached.flush_required = &flush_required;
@ -2205,7 +2177,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
!lv_is_thin_pool(lv) &&
!lv_is_vdo(lv) &&
!lv_is_vdo_pool(lv)))) {
log_debug_activation("Requiring flush for LV %s.", display_lvname(lv));
log_debug("Requiring flush for LV %s.", display_lvname(lv));
flush_required = 1;
}
@ -2213,23 +2185,16 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
/* FIXME Consider aborting here */
stack;
/* Require fs synchronization when taking a thin snapshot */
if (!laopts->origin_only &&
(lv_is_origin(lv_pre) || lv_is_cow(lv_pre)))
lockfs = 1;
/* Converting non-thin LV to thin external origin ? */
if (!lv_is_thin_volume(lv) && lv_is_thin_volume(lv_pre))
lockfs = 1; /* Sync before conversion */
if (laopts->origin_only && lv_is_thin_volume(lv) && lv_is_thin_volume(lv_pre))
lockfs = 1;
/* Require fs synchronization when taking a thick snapshot */
else if (!laopts->origin_only &&
(lv_is_origin(lv_pre) || lv_is_cow(lv_pre)))
lockfs = 1;
/* Require fs synchronization when converting a non-thin LV to a thin LV or
* a non/thin LV with/out external origin to a thin LV with external origin LV. */
else if (!laopts->origin_only &&
lv_is_thin_volume(lv_pre) && /* new LV is a Thin */
(!lv_is_thin_volume(lv) || /* and either the existing LV is NOT a Thin */
(first_seg(lv_pre)->external_lv && /* or the existing LV IS Thin and the new LV is Thin with the external origin */
(!first_seg(lv)->external_lv || /* and check if existing Thin is either without the external origin */
memcmp(&first_seg(lv_pre)->external_lv->lvid.id[1], /* or it uses a different external origin */
&first_seg(lv)->external_lv->lvid.id[1], ID_LEN) != 0))))
lockfs = 1;
if (!lv_is_locked(lv) && lv_is_locked(lv_pre) &&
(pvmove_lv = find_pvmove_lv_in_lv(lv_pre))) {
@ -2320,12 +2285,12 @@ static int _check_suspended_lv(struct logical_volume *lv, void *data)
struct lvinfo info;
if (lv_info(lv->vg->cmd, lv, 0, &info, 0, 0) && info.exists && info.suspended) {
log_debug_activation("Found suspended LV %s in critical section().", display_lvname(lv));
log_debug("Found suspended LV %s in critical section().", display_lvname(lv));
return 0; /* There is suspended subLV in the tree */
}
if (lv_layer(lv) && lv_info(lv->vg->cmd, lv, 1, &info, 0, 0) && info.exists && info.suspended) {
log_debug_activation("Found suspended layered LV %s in critical section().", display_lvname(lv));
log_debug("Found suspended layered LV %s in critical section().", display_lvname(lv));
return 0; /* There is suspended subLV in the tree */
}
@ -2458,9 +2423,10 @@ static int _lv_has_open_snapshots(const struct logical_volume *lv)
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logical_volume *lv)
{
struct lvinfo info;
const struct lv_activate_opts laopts = { .skip_in_use = 1 };
static const struct lv_activate_opts laopts = { .skip_in_use = 1 };
struct dm_list *snh;
int r = 0;
unsigned tmp_state;
if (!activation())
return 1;
@ -2533,6 +2499,9 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
}
critical_section_dec(cmd, "deactivated");
tmp_state = cmd->disable_dm_devs;
cmd->disable_dm_devs = 1;
if (!lv_info(cmd, lv, 0, &info, 0, 0) || info.exists) {
/* Turn into log_error, but we do not log error */
log_debug_activation("Deactivated volume is still %s present.",
@ -2540,6 +2509,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
r = 0;
}
cmd->disable_dm_devs = tmp_state;
out:
return r;
@ -2585,7 +2555,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
lv_is_partial(lv) && lv_is_raid(lv) && lv_raid_has_integrity((struct logical_volume *)lv)) {
cmd->partial_activation = 0;
cmd->degraded_activation = 0;
log_print_unless_silent("No degraded or partial activation for raid with integrity.");
log_print("No degraded or partial activation for raid with integrity.");
}
if ((!lv->vg->cmd->partial_activation) && lv_is_partial(lv)) {
@ -2635,8 +2605,6 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
if (!lv_is_visible(lv) && lv_is_component(lv)) {
laopts->read_only = 1;
laopts->component_lv = lv;
} else if (lv_is_pool_metadata_spare(lv)) {
laopts->component_lv = lv;
} else if (filter)
laopts->read_only = _passes_readonly_filter(cmd, lv);
@ -2753,16 +2721,16 @@ static int _remove_dm_dev_by_name(const char *name)
/* Work all segments of @lv removing any existing, closed "*-missing_N_0" sub devices. */
static int _lv_remove_any_missing_subdevs(struct logical_volume *lv)
{
char name[NAME_LEN];
struct lv_segment *seg;
uint32_t seg_no = 0;
if (lv) {
uint32_t seg_no = 0;
char name[257];
struct lv_segment *seg;
dm_list_iterate_items(seg, &lv->segments) {
if (dm_snprintf(name, sizeof(name), "%s-%s-missing_%u_0", seg->lv->vg->name, seg->lv->name, seg_no) < 0)
return_0;
if (!_remove_dm_dev_by_name(name))
return_0;
return 0;
seg_no++;
}
@ -2780,10 +2748,10 @@ int lv_deactivate_any_missing_subdevs(const struct logical_volume *lv)
for (s = 0; s < seg->area_count; s++) {
if (seg_type(seg, s) == AREA_LV &&
!_lv_remove_any_missing_subdevs(seg_lv(seg, s)))
return_0;
return 0;
if (seg->meta_areas && seg_metatype(seg, s) == AREA_LV &&
!_lv_remove_any_missing_subdevs(seg_metalv(seg, s)))
return_0;
return 0;
}
return 1;

View File

@ -107,12 +107,8 @@ int target_present(struct cmd_context *cmd, const char *target_name,
int target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel);
int get_dm_active_devices(const struct volume_group *vg, struct dm_list **devs,
int get_device_list(const struct volume_group *vg, struct dm_list **devs,
unsigned *devs_features);
int devno_dm_uuid(struct cmd_context *cmd, int major, int minor,
char *uuid_buf, size_t uuid_buf_size);
int dev_dm_uuid(struct cmd_context *cmd, struct device *dev,
char *uuid_buf, size_t uuid_buf_size);
int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype);
int lvm_dm_prefix_check(int major, int minor, const char *prefix);
@ -264,7 +260,7 @@ struct dev_usable_check_params {
* Returns 1 if mapped device is not suspended, blocked or
* is using a reserved name.
*/
int dm_device_is_usable(struct cmd_context *cmd, struct device *dev, struct dev_usable_check_params check, int *is_lv);
int device_is_usable(struct cmd_context *cmd, struct device *dev, struct dev_usable_check_params check, int *is_lv);
/*
* Declaration moved here from fs.h to keep header fs.h hidden

File diff suppressed because it is too large Load Diff

View File

@ -108,7 +108,7 @@ int dev_manager_device_uses_vg(struct device *dev,
int dev_manager_remove_dm_major_minor(uint32_t major, uint32_t minor);
int dev_manager_check_prefix_dm_major_minor(uint32_t major, uint32_t minor, const char *prefix);
int dev_manager_get_dm_active_devices(const char *prefix, struct dm_list **devs,
unsigned *devs_features);
int dev_manager_get_device_list(const char *prefix, struct dm_list **devs,
unsigned *devs_features);
#endif

View File

@ -112,7 +112,7 @@ static void _rm_blks(const char *dir)
if (!S_ISBLK(buf.st_mode))
continue;
log_very_verbose("Removing %s", path);
if (unlink(path) && (errno != ENOENT))
if (unlink(path) < 0)
log_sys_debug("unlink", path);
}
}
@ -168,7 +168,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
_rm_blks(vg_path);
log_very_verbose("Removing %s", lvm1_group_path);
if (unlink(lvm1_group_path) && (errno != ENOENT))
if (unlink(lvm1_group_path) < 0)
log_sys_debug("unlink", lvm1_group_path);
}
}
@ -200,7 +200,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
}
log_very_verbose("Removing %s", lv_path);
if (unlink(lv_path) && (errno != ENOENT)) {
if (unlink(lv_path) < 0) {
log_sys_error("unlink", lv_path);
return 0;
}
@ -252,7 +252,7 @@ static int _rm_link(const char *dev_dir, const char *vg_name,
}
log_very_verbose("Removing link %s", lv_path);
if (unlink(lv_path) && (errno != ENOENT)) {
if (unlink(lv_path) < 0) {
log_sys_error("unlink", lv_path);
return 0;
}
@ -318,10 +318,9 @@ struct fs_op_parms {
static void _store_str(char **pos, char **ptr, const char *str)
{
size_t len = strlen(str) + 1;
memcpy(*pos, str, len);
strcpy(*pos, str);
*ptr = *pos;
*pos += len;
*pos += strlen(*ptr) + 1;
}
static void _del_fs_op(struct fs_op_parms *fsp)

163
lib/cache/lvmcache.c vendored
View File

@ -83,6 +83,7 @@ static struct dm_hash_table *_vgname_hash = NULL;
static DM_LIST_INIT(_vginfos);
static DM_LIST_INIT(_initial_duplicates);
static DM_LIST_INIT(_unused_duplicates);
static DM_LIST_INIT(_prev_unused_duplicate_devs);
static int _vgs_locked = 0;
static int _found_duplicate_vgnames = 0;
static int _outdated_warning = 0;
@ -98,6 +99,7 @@ int lvmcache_init(struct cmd_context *cmd)
dm_list_init(&_vginfos);
dm_list_init(&_initial_duplicates);
dm_list_init(&_unused_duplicates);
dm_list_init(&_prev_unused_duplicate_devs);
if (!(_vgname_hash = dm_hash_create(127)))
return 0;
@ -189,6 +191,21 @@ static void _destroy_device_list(struct dm_list *head)
dm_list_init(head);
}
bool lvmcache_has_bad_metadata(struct device *dev)
{
struct lvmcache_info *info;
if (!(info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) {
/* shouldn't happen */
log_error("No lvmcache info for checking bad metadata on %s", dev_name(dev));
return false;
}
if (info->mda1_bad || info->mda2_bad)
return true;
return false;
}
void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda)
{
if (mda->mda_num == 1)
@ -384,10 +401,10 @@ const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgnam
if (_found_duplicate_vgnames) {
if (!(vginfo = _search_vginfos_list(vgname, NULL)))
return NULL;
return_NULL;
} else {
if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
return NULL;
return_NULL;
}
if (vginfo->has_duplicate_local_vgname) {
@ -690,8 +707,8 @@ static int _all_multipath_components(struct cmd_context *cmd, struct lvmcache_in
/* Different mpath devs with the same wwid shouldn't happen. */
if (dev_is_mp && dev_mp) {
log_print_unless_silent("Found multiple multipath devices for PVID %s WWID %s: %s %s.",
pvid, wwid1_buf, dev_name(dev_mp), dev_name(dev));
log_print("Found multiple multipath devices for PVID %s WWID %s: %s %s",
pvid, wwid1_buf, dev_name(dev_mp), dev_name(dev));
continue;
}
@ -827,6 +844,7 @@ static void _choose_duplicates(struct cmd_context *cmd,
int same_size1, same_size2;
int same_name1 = 0, same_name2 = 0;
int same_id1 = 0, same_id2 = 0;
int prev_unchosen1, prev_unchosen2;
int change;
dm_list_init(&new_unused);
@ -894,10 +912,8 @@ next:
}
/* Remove dev_mpath from altdevs. */
if ((devl = device_list_find_dev(&altdevs, dev_mpath))) {
if ((devl = device_list_find_dev(&altdevs, dev_mpath)))
dm_list_del(&devl->list);
free(devl);
}
/* Remove info from lvmcache that came from the component dev. */
log_debug("Ignoring multipath component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid);
@ -934,7 +950,6 @@ next:
log_debug("Ignoring multipath component %s with PVID %s (dropping duplicate)", dev_name(dev_drop), pvid);
dm_list_del(&devl->list);
free(devl);
cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL);
dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL;
@ -964,10 +979,8 @@ next:
}
/* Remove dev_md from altdevs. */
if ((devl = device_list_find_dev(&altdevs, dev_md))) {
if ((devl = device_list_find_dev(&altdevs, dev_md)))
dm_list_del(&devl->list);
free(devl);
}
/* Remove info from lvmcache that came from the component dev. */
log_debug("Ignoring md component %s with PVID %s (dropping info)", dev_name(dev_drop), pvid);
@ -994,10 +1007,8 @@ next:
}
/* Remove dev_md from altdevs. */
if ((devl = device_list_find_dev(&altdevs, dev_md))) {
if ((devl = device_list_find_dev(&altdevs, dev_md)))
dm_list_del(&devl->list);
free(devl);
}
}
if (info && !dev_md) {
@ -1025,7 +1036,6 @@ next:
log_debug("Ignoring md component %s with PVID %s (dropping duplicate)", dev_name(dev_drop), pvid);
dm_list_del(&devl->list);
free(devl);
cmd->filter->wipe(cmd, cmd->filter, dev_drop, NULL);
dev_drop->flags &= ~DEV_SCAN_FOUND_LABEL;
@ -1075,6 +1085,21 @@ next:
if (dev1 == dev2)
continue;
prev_unchosen1 = device_list_find_dev(&_unused_duplicates, dev1) ? 1 :0;
prev_unchosen2 = device_list_find_dev(&_unused_duplicates, dev2) ? 1 :0;
if (!prev_unchosen1 && !prev_unchosen2) {
/*
* The prev list saves the unchosen preference across
* lvmcache_destroy. Sometimes a single command will
* fill lvmcache, destroy it, and refill it, and we
* want the same duplicate preference to be preserved
* in each instance of lvmcache for a single command.
*/
prev_unchosen1 = device_list_find_dev(&_prev_unused_duplicate_devs, dev1) ? 1 :0;
prev_unchosen2 = device_list_find_dev(&_prev_unused_duplicate_devs, dev2) ? 1 : 0;
}
dev1_major = MAJOR(dev1->dev);
dev1_minor = MINOR(dev1->dev);
dev2_major = MAJOR(dev2->dev);
@ -1137,6 +1162,11 @@ next:
dev_name(dev1), (unsigned long long)dev1_size,
dev_name(dev2), (unsigned long long)dev2_size);
log_debug_cache("PV %s: %s was prev %s. %s was prev %s.",
devl->dev->pvid,
dev_name(dev1), prev_unchosen1 ? "not chosen" : "<none>",
dev_name(dev2), prev_unchosen2 ? "not chosen" : "<none>");
log_debug_cache("PV %s: %s %s subsystem. %s %s subsystem.",
devl->dev->pvid,
dev_name(dev1), in_subsys1 ? "is in" : "is not in",
@ -1164,7 +1194,14 @@ next:
change = 0;
if (same_id1 && !same_id2) {
if (prev_unchosen1 && !prev_unchosen2) {
/* change to 2 (NB when unchosen is set we unprefer) */
change = 1;
reason = "of previous preference";
} else if (prev_unchosen2 && !prev_unchosen1) {
/* keep 1 (NB when unchosen is set we unprefer) */
reason = "of previous preference";
} else if (same_id1 && !same_id2) {
/* keep 1 */
reason = "device id";
} else if (same_id2 && !same_id1) {
@ -1466,9 +1503,6 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd)
*/
dm_list_iterate_items_safe(vginfo, vginfo2, &_vginfos) {
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
memcpy(vgid, vginfo->vgid, ID_LEN);
dm_list_iterate_items_safe(info, info2, &vginfo->infos) {
dev = info->dev;
device_hint = _get_pvsummary_device_hint(dev->pvid);
@ -1523,10 +1557,6 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd)
/* lvmcache_del will also delete vginfo if info was last one */
lvmcache_del(info);
cmd->filter->wipe(cmd, cmd->filter, dev, NULL);
/* If vginfo was deleted don't continue using vginfo->infos */
if (!_search_vginfos_list(NULL, vgid))
break;
}
}
}
@ -1560,9 +1590,12 @@ int lvmcache_label_scan(struct cmd_context *cmd)
{
struct dm_list del_cache_devs;
struct dm_list add_cache_devs;
struct dm_list renamed_devs;
struct lvmcache_info *info;
struct device_list *devl;
dm_list_init(&renamed_devs);
log_debug_cache("lvmcache label scan begin");
/*
@ -1590,43 +1623,25 @@ int lvmcache_label_scan(struct cmd_context *cmd)
if (!dm_list_empty(&cmd->device_ids_check_serial)) {
struct dm_list scan_devs;
dm_list_init(&scan_devs);
device_ids_check_serial(cmd, &scan_devs, 0, NULL);
device_ids_check_serial(cmd, &scan_devs, NULL, 0);
if (!dm_list_empty(&scan_devs))
label_scan_devs(cmd, cmd->filter, &scan_devs);
}
/*
* device_ids_invalid is set by device_ids_validate() when there
* are entries in the devices file that need to be corrected,
* i.e. device IDs read from the system and/or PVIDs read from
* disk do not match info in the devices file. This is usually
* related to incorrect device names which routinely change on
* reboot. When device names change for entries that use
* IDTYPE=devname, it often means that all devs on the system
* need to be scanned to find the new device for the PVIDs.
* device_ids_validate() will update the devices file to correct
* some info, but to locate new devices for PVIDs, it defers
* to device_ids_search() which involves label scanning.
*
* device_ids_refresh_trigger is set by device_ids_read() when
* it sees that the local machine doesn't match the machine
* that wrote the devices file, and device IDs of all types
* may need to be replaced for the PVIDs in the devices file.
* This also means that all devs on the system need to be
* scanned to find the new devices for the PVIDs.
*
* When device_ids_search() locates the correct devices
* for the PVs in the devices file, it returns those new
* devices in the refresh_devs list. Those devs need to
* be passed to label_scan to populate lvmcache info.
* When devnames are used as device ids (which is dispreferred),
* changing/unstable devnames can lead to entries in the devices file
* not being matched to a dev even if the PV is present on the system.
* Or, a devices file entry may have been matched to the wrong device
* (with the previous name) that does not have the PVID specified in
* the entry. This function detects that problem, scans labels on all
* devs on the system to find the missing PVIDs, and corrects the
* devices file. We then need to run label scan on these correct
* devices.
*/
if (cmd->device_ids_invalid || cmd->device_ids_refresh_trigger) {
struct dm_list new_devs;
dm_list_init(&new_devs);
device_ids_search(cmd, &new_devs, 0, 0, NULL);
if (!dm_list_empty(&new_devs))
label_scan_devs(cmd, cmd->filter, &new_devs);
}
device_ids_find_renamed_devs(cmd, &renamed_devs, NULL, 0);
if (!dm_list_empty(&renamed_devs))
label_scan_devs(cmd, cmd->filter, &renamed_devs);
/*
* _choose_duplicates() returns:
@ -1665,8 +1680,6 @@ int lvmcache_label_scan(struct cmd_context *cmd)
label_scan_dev(cmd, devl->dev);
}
_destroy_device_list(&add_cache_devs);
dm_list_splice(&_unused_duplicates, &del_cache_devs);
/* Warn about unused duplicates that the user might want to resolve. */
@ -2258,7 +2271,7 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
* vginfo/info. PVs that don't hold VG metadata weren't attached to the vginfo
* during label scan, and PVs with outdated metadata (claiming to be in the VG,
* but not listed in the latest metadata) were attached to the vginfo, but
* shouldn't be. After vg_read() gets the full metadata in the form of a 'vg',
* shouldn't be. After vg_read() gets the full metdata in the form of a 'vg',
* this function is called to fix up the lvmcache representation of the VG
* using the 'vg'.
*/
@ -2615,6 +2628,20 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
dm_list_init(&_vginfos);
/*
* Move the current _unused_duplicates to _prev_unused_duplicate_devs
* before destroying _unused_duplicates.
*
* One command can init/populate/destroy lvmcache multiple times. Each
* time it will encounter duplicates and choose the preferrred devs.
* We want the same preferred devices to be chosen each time, so save
* the unpreferred devs here so that _choose_preferred_devs can use
* this to make the same choice each time.
*
* FIXME: I don't think is is needed any more.
*/
_destroy_device_list(&_prev_unused_duplicate_devs);
dm_list_splice(&_prev_unused_duplicate_devs, &_unused_duplicates);
_destroy_device_list(&_unused_duplicates);
_destroy_device_list(&_initial_duplicates); /* should be empty anyway */
@ -2977,11 +3004,9 @@ void lvmcache_get_max_name_lengths(struct cmd_context *cmd,
*pv_max_name_len = 0;
dm_list_iterate_items(vginfo, &_vginfos) {
if (!is_orphan_vg(vginfo->vgname)) {
len = strlen(vginfo->vgname);
if (*vg_max_name_len < len)
*vg_max_name_len = len;
}
len = strlen(vginfo->vgname);
if (*vg_max_name_len < len)
*vg_max_name_len = len;
dm_list_iterate_items(info, &vginfo->infos) {
len = strlen(dev_name(info->dev));
@ -3002,16 +3027,6 @@ int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const ch
return ret;
}
int lvmcache_vg_is_lockd_type(struct cmd_context *cmd, const char *vgname, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
if ((vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
return is_lockd_type(vginfo->lock_type);
return 0;
}
/*
* Example of reading four devs in sequence from the same VG:
*
@ -3237,11 +3252,11 @@ const char *dev_filtered_reason(struct device *dev)
return "device cannot be used";
}
const char *devname_error_reason(struct cmd_context *cmd, const char *devname)
const char *devname_error_reason(const char *devname)
{
struct device *dev;
if ((dev = dev_cache_get_by_name(cmd, devname))) {
if ((dev = dev_hash_get(devname))) {
if (dev->filtered_flags)
return dev_filtered_reason(dev);
if (lvmcache_dev_is_unused_duplicate(dev))

View File

@ -179,8 +179,6 @@ void lvmcache_get_max_name_lengths(struct cmd_context *cmd,
int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_vg_is_lockd_type(struct cmd_context *cmd, const char *vgname, const char *vgid);
bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, const char *pvid_arg);
@ -188,6 +186,8 @@ int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, const char *pvid_ar
uint64_t lvmcache_max_metadata_size(void);
void lvmcache_save_metadata_size(uint64_t val);
bool lvmcache_has_bad_metadata(struct device *dev);
bool lvmcache_has_old_metadata(struct cmd_context *cmd, const char *vgname, const char *vgid, struct device *dev);
void lvmcache_get_outdated_devs(struct cmd_context *cmd,
@ -218,7 +218,7 @@ void lvmcache_get_mdas(struct cmd_context *cmd,
struct dm_list *mda_list);
const char *dev_filtered_reason(struct device *dev);
const char *devname_error_reason(struct cmd_context *cmd, const char *devname);
const char *devname_error_reason(const char *devname);
struct metadata_area *lvmcache_get_dev_mda(struct device *dev, int mda_num);

View File

@ -300,6 +300,38 @@ static void _destroy(struct segment_type *segtype)
}
#ifdef DEVMAPPER_SUPPORT
/*
* Parse and look for kernel symbol in /proc/kallsyms
* this could be our only change to figure out there is
* cache policy symbol already in the monolithic kernel
* where 'modprobe dm-cache-smq' will simply not work
*/
static int _lookup_kallsyms(const char *symbol)
{
static const char _syms[] = "/proc/kallsyms";
int ret = 0;
char *line = NULL;
size_t len;
FILE *s;
if (!(s = fopen(_syms, "r")))
log_sys_debug("fopen", _syms);
else {
while (getline(&line, &len, s) != -1)
if (strstr(line, symbol)) {
ret = 1; /* Found symbol */
log_debug("Found kernel symbol%s.", symbol); /* space is in symbol */
break;
}
free(line);
if (fclose(s))
log_sys_debug("fclose", _syms);
}
return ret;
}
static int _target_present(struct cmd_context *cmd,
const struct lv_segment *seg __attribute__((unused)),
@ -307,20 +339,21 @@ static int _target_present(struct cmd_context *cmd,
{
/* List of features with their kernel target version */
static const struct feature {
uint16_t maj;
uint16_t min;
uint16_t cache_feature;
uint16_t cache_alias;
uint32_t maj;
uint32_t min;
unsigned cache_feature;
unsigned cache_alias;
const char feature[12];
const char module[12]; /* check dm-%s */
const char aliasing[24];
const char ksymbol[12]; /* check for kernel symbol */
const char *aliasing;
} _features[] = {
{ 1, 10, CACHE_FEATURE_METADATA2, 0, "metadata2" },
/* Assumption: cache >=1.9 always aliases MQ policy */
{ 1, 9, CACHE_FEATURE_POLICY_SMQ, CACHE_FEATURE_POLICY_MQ, "policy_smq", "cache-smq",
" and aliases cache-mq" },
{ 1, 8, CACHE_FEATURE_POLICY_SMQ, 0, "policy_smq", "cache-smq" },
{ 1, 3, CACHE_FEATURE_POLICY_MQ, 0, "policy_mq", "cache-mq" },
" smq_exit", " and aliases cache-mq" },
{ 1, 8, CACHE_FEATURE_POLICY_SMQ, 0, "policy_smq", "cache-smq", " smq_exit" },
{ 1, 3, CACHE_FEATURE_POLICY_MQ, 0, "policy_mq", "cache-mq", " mq_init" },
};
static const char _lvmconf[] = "global/cache_disabled_features";
static unsigned _attrs = 0;
@ -366,10 +399,11 @@ static int _target_present(struct cmd_context *cmd,
}
if (((maj > _features[i].maj) ||
(maj == _features[i].maj && min >= _features[i].min)) &&
module_present(cmd, _features[i].module)) {
((_features[i].ksymbol[0] && _lookup_kallsyms(_features[i].ksymbol)) ||
module_present(cmd, _features[i].module))) {
log_debug_activation("Cache policy %s is available%s.",
_features[i].module,
_features[i].aliasing);
_features[i].aliasing ? : "");
_attrs |= (_features[i].cache_feature | _features[i].cache_alias);
} else if (!_features[i].cache_alias)
log_very_verbose("Target %s does not support %s.",
@ -423,7 +457,7 @@ static int _modules_needed(struct dm_pool *mem,
}
#endif /* DEVMAPPER_SUPPORT */
static const struct segtype_handler _cache_pool_ops = {
static struct segtype_handler _cache_pool_ops = {
.display = _cache_display,
.text_import = _cache_pool_text_import,
.text_import_area_count = _cache_pool_text_import_area_count,
@ -762,7 +796,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
}
#endif /* DEVMAPPER_SUPPORT */
static const struct segtype_handler _cache_ops = {
static struct segtype_handler _cache_ops = {
.display = _cache_display,
.text_import = _cache_text_import,
.text_import_area_count = _cache_text_import_area_count,

View File

@ -12,7 +12,7 @@
enum {
#define cmd(a, b) a ,
#include "cmds.h"
#include "../../include/cmds.h"
#undef cmd
};

Some files were not shown because too many files have changed in this diff Show More