mirror of
git://sourceware.org/git/lvm2.git
synced 2025-08-23 05:49:28 +03:00
Compare commits
1 Commits
dev-dct-de
...
dev-dct-pv
Author | SHA1 | Date | |
---|---|---|---|
f59cb6632b |
5
.gitignore
vendored
5
.gitignore
vendored
@ -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
|
||||
|
104
.gitlab-ci.yml
104
.gitlab-ci.yml
@ -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
|
||||
|
@ -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
29
README
@ -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:
|
||||
|
5
TESTING
5
TESTING
@ -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.
|
||||
|
||||
|
@ -1 +1 @@
|
||||
1.02.199-git (2024-05-16)
|
||||
1.02.191-git (2022-12-22)
|
||||
|
125
WHATS_NEW
125
WHATS_NEW
@ -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!
|
||||
|
||||
|
||||
|
49
WHATS_NEW_DM
49
WHATS_NEW_DM
@ -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.
|
||||
|
||||
|
||||
|
18
acinclude.m4
18
acinclude.m4
@ -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
34
aclocal.m4
vendored
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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++)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -49,7 +49,7 @@ install_localconf: $(CONFLOCAL)
|
||||
fi
|
||||
|
||||
install_profiles: $(PROFILES)
|
||||
$(SHOW) " [INSTALL] $<"
|
||||
@echo " [INSTALL] $<"
|
||||
$(Q) $(INSTALL_DIR) $(profiledir)
|
||||
$(Q) $(INSTALL_DATA) $(PROFILES) $(profiledir)/
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
1521
configure.ac
1521
configure.ac
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
"""
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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,),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
78
daemons/lvmdbusd/lvm_shell_proxy.py.in
Normal file → Executable 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
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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, '/')))
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 '?':
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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" :
|
||||
|
@ -79,7 +79,7 @@ struct dm_task {
|
||||
};
|
||||
|
||||
struct cmd_data {
|
||||
const char name[16];
|
||||
const char *name;
|
||||
const unsigned cmd;
|
||||
const int version[3];
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -223,6 +223,7 @@ retry_fcntl:
|
||||
}
|
||||
|
||||
/* coverity[leaked_handle] intentional leak of fd handle here */
|
||||
|
||||
return 1;
|
||||
|
||||
fail_close_unlink:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
152
doc/index.mdwn
152
doc/index.mdwn
@ -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
|
||||
-->
|
@ -1,4 +0,0 @@
|
||||
.page {
|
||||
max-width: 1280px;
|
||||
margin: auto;
|
||||
}
|
@ -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]]
|
||||
|
@ -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"]]
|
@ -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"]]
|
||||
-->
|
||||
|
@ -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"]]
|
@ -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"]]
|
||||
|
@ -1,3 +0,0 @@
|
||||
# Pending Release
|
||||
|
||||
[[!inline pages="release-notes/* and !*/template and !*/Discussion and tagged(pending)" rootpage="release-notes"]]
|
@ -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"]]
|
||||
-->
|
420
ikiwiki.setup
420
ikiwiki.setup
@ -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
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
163
lib/cache/lvmcache.c
vendored
@ -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))
|
||||
|
6
lib/cache/lvmcache.h
vendored
6
lib/cache/lvmcache.h
vendored
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
Reference in New Issue
Block a user