1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-15 13:44:18 +03:00

Compare commits

..

2 Commits

Author SHA1 Message Date
David Teigland
771eb2f230 device usage based on devices_file and device_id
devices_file, e.g. /etc/lvm/lvm_devices.dat,
is a list of devices that lvm can use.
Option --devicesfile can sepecify a different file
with a separate set of devices for lvm to use.
This option allows different applications to use
lvm on different sets of devices.

In most cases (with limited exceptions), lvm will not
read or use a device not listed in devices_file.
When the devices_file is used, the filter-regex is
not used and the filter settings in lvm.conf are
ignored.  lvm uses the devices_file to control access
to devices using the new filter-deviceid.

Setting --devicesfile to "" on the command line, or
devicesfile to "" in lvm.conf will disable the use
of the devices_file and filter-deviceid.  This
allows lvm to see and use any device on the system.
In this case lvm will fall back to using filter-regex
and the filter config settings in lvm.conf.

device_id, e.g. wwid or serial number from sysfs,
is a unique ID that identifies a device without
reading it, and which will change if the device
is copied to another.  The device_id is used in the
devices_file and is included in VG metadata sections.

Each device_id has a device_id_type which indicates
where the device_id comes from, e.g. "sys_wwid"
means the device_id comes from the sysfs wwid file.
Others are sys_serial, mpath_uuid, loop_file, devname.
(devname is the device path which is a fallback when
no other proper device_id_type is available.)

filter-deviceid permits lvm to use only devices
on the system that have a device_id matching a
devices_file entry.  Using the device_id, lvm can
determine the set of devices to use without reading
any devices, so devices_file will constrain lvm in
two ways:
1. it limits the devices that lvm will read.
2. it limits the devices that lvm will use.

In some uncommon cases, e.g. when devices have no
unique ID and device_id has to fall back to using
the devname, lvm may need to read all devices on the
system to determine which ones correspond to the
devices_file entries.  In this case, the devices_file
does not limit the devices that lvm reads, but it does
limit the devices that lvm uses.

pvcreate/vgcreate/vgextend are not constrained by
the devices_file, and will look outside it to find
the new PV.  They assign the new PV a device_id
and add it to the devices_file.  It would be possible
to explicitly add new PVs to devices_file before using
them in pvcreate/etc, in which case these commands
would not need to access devices outside devices_file.
(A config setting may be added to control the ability
of these commands to search outside devices_list.)

vgimportdevices VG looks at all devices on the system
to find an existing VG and add its devices to the
devices_file.  The command is not limited by an
existing devices_file.  The command will also add
device_ids to the VG metadata if the VG does not yet
include device_ids.  vgimportdevices -a imports devices
for all accessible VGs.  Since vgimportdevices does not
limit itself to devices in an existing devices_file, the
lvm.conf filter applies.  Adding --foreign will
import devices for foreign VGs, but device_ids are
not added to foreign VGs.

TODO:
pvchange --deviceidupdate PV
vgchange --deviceidupdate VG
pvs -o deviceidtype,deviceid
duplicate PV resolution using device_id
vgimportclone needs to update device_file
pvchange --uuid needs to update device_file
config setting device_id_types to control idtypes used
lvmdevices command to manage devices_file
search for pvid when no wwid is available and PV is missing
md device_id_type
config setting pvcreate_extends_devices_file=0|1
shortsystemid crc of systemid and written in pv header
use shortsystemid for new filter and orphan PV ownership

TODO: new lvmdevices command:

--adddev <devname>
Adds devices_file entry, reads device header.

--deldev <devname>
Removes devices_file entry.

--addpvid <pvid>
Reads pv header of all devices to find <pvid>,
if found adds devices_file entry.

--delpvid <pvid>
Removes devices_file entry.

--adddeviceid <device_id> --deviceidtype <idtype>
Reads <idtype> of all devices (e.g. from sysfs) to find a match,
if found, reads pv header and adds devices_file entry.

--deldeviceid <device_id>
Removes devices_file entry.
2020-07-06 17:39:54 -05:00
David Teigland
b078703302 pvcreate/pvremove: reimplement checks 2020-06-23 13:19:11 -05:00
593 changed files with 26395 additions and 43377 deletions

7
.gitignore vendored
View File

@@ -30,19 +30,14 @@ make.tmpl
/config.log
/config.status
/configure.scan
/cscope.*
/cscope.out
/html/
/python/
/reports/
/tags
/tmp/
coverity/coverity_model.xml
# gcov files:
*.gcda
*.gcno
tools/man-generator
tools/man-generator.c

View File

@@ -18,7 +18,7 @@ top_builddir = @top_builddir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
SUBDIRS = libdm conf daemons include lib libdaemon man scripts tools
SUBDIRS = conf daemons include lib libdaemon libdm man scripts tools
ifeq ("@UDEV_RULES@", "yes")
SUBDIRS += udev
@@ -47,6 +47,8 @@ include $(top_srcdir)/base/Makefile
include $(top_srcdir)/device_mapper/Makefile
include $(top_srcdir)/test/unit/Makefile
libdm: include
libdaemon: include
lib: libdaemon $(BASE_TARGET) $(DEVICE_MAPPER_TARGET)
daemons: lib libdaemon tools
scripts: lib
@@ -54,13 +56,16 @@ tools: lib libdaemon
po: tools daemons
man: tools
all_man: tools
scripts: libdm
test: tools daemons
unit-test run-unit-test: test
lib.device-mapper: include.device-mapper
libdm.device-mapper: include.device-mapper
daemons.device-mapper: libdm.device-mapper
tools.device-mapper: libdm.device-mapper
scripts.device-mapper: include.device-mapper
device-mapper: tools.device-mapper daemons.device-mapper man.device-mapper
device_mapper: device-mapper
ifeq ("@INTL@", "yes")
lib.pofile: include.pofile
@@ -76,10 +81,9 @@ daemons.cflow: tools.cflow
cflow: include.cflow
endif
CSCOPE_DIRS = base daemons device_mapper include lib libdaemon scripts tools libdm test
ifneq ("@CSCOPE_CMD@", "")
cscope.out:
@CSCOPE_CMD@ -b -R $(patsubst %,-s%,$(addprefix $(srcdir)/,$(CSCOPE_DIRS)))
@CSCOPE_CMD@ -b -R -s$(top_srcdir)
all: cscope.out
endif
DISTCLEAN_TARGETS += cscope.out
@@ -112,11 +116,11 @@ rpm: dist
$(LN_S) -f $(abs_top_srcdir)/spec/packages.inc $(rpmbuilddir)/SOURCES
DM_VER=$$(cut -d- -f1 $(top_srcdir)/VERSION_DM);\
GIT_VER=$$(cd $(top_srcdir); git describe | cut -d- --output-delimiter=. -f2,3 || echo 0);\
$(SED) -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \
sed -e "s,\(device_mapper_version\) [0-9.]*$$,\1 $$DM_VER," \
-e "s,^\(Version:[^0-9%]*\)[0-9.]*$$,\1 $(LVM_VER)," \
-e "s,^\(Release:[^0-9%]*\)[0-9.]\+,\1 $$GIT_VER," \
$(top_srcdir)/spec/source.inc >$(rpmbuilddir)/SOURCES/source.inc
V=$(V) rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
rpmbuild -v --define "_topdir $(rpmbuilddir)" -ba $(top_srcdir)/spec/lvm2.spec
generate: conf.generate man.generate
$(MAKE) -C conf generate
@@ -150,31 +154,6 @@ install_all_man:
install_tmpfiles_configuration:
$(MAKE) -C scripts install_tmpfiles_configuration
help:
@echo -e "\nAvailable targets:"
@echo " all Default target."
@echo " all_man Build all man pages with generators."
@echo " clean Remove all compile files."
@echo " device-mapper Device mapper part of lvm2."
@echo " dist Generate distributable file."
@echo " distclean Remove all build files."
@echo " generate Generate man pages for sources."
@echo " help Display callable targets."
@echo " install Install all files."
@echo " install_all_man Install all man pages."
@echo " install_cluster Install cmirrord."
@echo " install_device-mapper Install device mapper files."
@echo " install_initscripts Install initialization scripts."
@echo " install_lvm2 Install lvm2 files."
@echo " install_systemd_units Install systemd units."
@echo " lcov Generate lcov output."
@echo " lcov-dated Generate lcov with timedate suffix."
@echo " lcov-reset Reset lcov counters"
@echo " man Build man pages."
@echo " rpm Build rpm."
@echo " run-unit-test Run unit tests."
@echo " tags Generate c/etags."
ifneq ("$(LCOV)", "")
.PHONY: lcov-reset lcov lcov-dated
@@ -204,8 +183,8 @@ endif
ifneq ($(shell which ctags 2>/dev/null),)
.PHONY: tags
tags:
test -z "$(shell find $(addprefix $(top_srcdir)/,$(CSCOPE_DIRS)) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
test -f tags || find $(addprefix $(top_srcdir)/,$(CSCOPE_DIRS)) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
test -z "$(shell find $(top_srcdir) -type f -name '*.[ch]' -newer tags 2>/dev/null | head -1)" || $(RM) tags
test -f tags || find $(top_srcdir) -maxdepth 5 -type f -name '*.[ch]' -exec ctags -a '{}' +
CLEAN_TARGETS += tags
endif

11
README
View File

@@ -1,6 +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.
This is development branch, for stable 2.02 release see 2018-06-01-stable
branch.
For more information about LVM2 read the changelog in the WHATS_NEW file.
Installation instructions are in INSTALL.
@@ -9,6 +10,7 @@ There is no warranty - see COPYING and COPYING.LIB.
Tarballs are available from:
ftp://sourceware.org/pub/lvm2/
ftp://sources.redhat.com/pub/lvm2/
https://github.com/lvmteam/lvm2/releases
The source code is stored in git:
@@ -43,9 +45,6 @@ Report upstream bugs at:
or open issues at:
https://github.com/lvmteam/lvm2/issues
The source code repository used until 7th June 2012 is accessible using CVS:
The source code repository used until 7th June 2012 is accessible here:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/LVM2/?cvsroot=lvm2.
cvs -d :pserver:cvs@sourceware.org:/cvs/lvm2 login cvs
cvs -d :pserver:cvs@sourceware.org:/cvs/lvm2 checkout LVM2
The password is cvs.

View File

@@ -1 +1 @@
2.03.14(2)-git (2021-08-11)
2.03.10(2)-git (2020-03-26)

View File

@@ -1 +1 @@
1.02.181-git (2021-08-11)
1.02.173-git (2020-03-26)

150
WHATS_NEW
View File

@@ -1,148 +1,5 @@
Version 2.03.14 -
==================================
Print info message with too many or too large archived files.
Reduce metadata readings during scanning phase.
Optimize computation of crc32 check sum with multiple PVs.
Enhance recover path on cache creation failure.
Filter out unsupported MQ/SMQ cache policy setting.
Fix memleak in mpath filter.
Support newer location for VDO statistics.
Add support for VDO async-unsage write policy.
Improve lvm_import_vdo script.
Support VDO LV with lvcreate -ky.
Fix lvconvert for VDO LV bigger then 2T.
Create VDO LVs automatically without zeroing.
Rename vdoimport to lvm_import_vdo.
Version 2.03.13 - 11th August 2021
==================================
Changes in udev support:
- obtain_device_list_from_udev defaults to 0.
- see devices/external_device_info_source,
devices/obtain_device_list_from_udev, and devices/multipath_wwids_file help
in lvm.conf
Fix devices file handling of loop with deleted backing file.
Fix devices file handling of scsi_debug WWIDs.
Fix many static analysis issues.
Support --poolmetadataspare with vgsplit and vgmerge.
Fix detection of active components of external origin volume.
Add vdoimport tool to support conversion of VDO volumes.
Support configurable allocation/vdo_pool_header_size.
Fix handling of lvconvert --type vdo-pool --virtualsize.
Simplified handling of archive() and backup() internal calls.
Add 'idm' locking type for IDM lock manager.
Fix load of kvdo target when it is not present in memory (2.03.12).
Version 2.03.12 - 07th May 2021
===============================
Allow attaching cache to thin data volume.
Fix memleak when generating list of outdated pvs.
Better hyphenation usage in man pages.
Replace use of deprecated security_context_t with char*.
Configure supports AIO_LIBS and AIO_CFLAGS.
Improve build process for static builds.
New --setautoactivation option to modify LV or VG auto activation.
New metadata based autoactivation property for LVs and VGs.
Improve signal handling with lvmpolld.
Signal handler can interrupt command also for SIGTERM.
Lvreduce --yes support.
Add configure option --with/out-symvers for non-glibc builds.
Report error when the filesystem is missing on fsadm resized volume.
Handle better blockdev with --getsize64 support for fsadm.
Do not include editline/history.h when using editline library.
Support error and zero segtype for thin-pool data for testing.
Support mixed extension for striped, error and zero segtypes.
Support resize also for stacked virtual volumes.
Skip dm-zero devices just like with dm-error target.
Reduce ioctl() calls when checking target status.
Merge polling does not fail, when LV is found to be already merged.
Poll volumes with at least 100ms delays.
Do not flush dm cache when cached LV is going to be removed.
New lvmlockctl_kill_command configuration option.
Support interruption while waiting on device close before deactivation.
Flush thin-pool messages before removing more thin volumes.
Improve hash function with less collisions and make it faster.
Reduce ioctl count when deactivating volumes.
Reduce number of metadata parsing.
Enhance performance of lvremove and vgremove commands.
Support interruption when taking archive and backup.
Accelerate large lvremoves.
Speedup search for cached device nodes.
Speedup command initialization.
Add devices file feature, off by default for now.
Support extension of writecached volumes.
Fix problem with unbound variable usage within fsadm.
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 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.
Improve thin-performance profile support conversion to thin-pool.
Add workaround to avoid read of internal 'converted' devices.
Prohibit merging snapshot into the read-only thick snapshot origin.
Restore support for flipping rw/r permissions for thin snapshot origin.
Support resize of cached volumes.
Disable autoactivation with global/event_activation=0.
Check if lvcreate passes read_only_volume_list with tags and skips zeroing.
Allocation prints better error when metadata cannot fit on a single PV.
Pvmove can better resolve full thin-pool tree move.
Limit pool metadata spare to 16GiB.
Improves conversion and allocation of pool metadata.
Support thin pool metadata 15.88GiB, adds 64MiB, thin_pool_crop_metadata=0.
Enhance lvdisplay to report raid available/partial.
Support online rename of VDO pools.
Improve removal of pmspare when last pool is removed.
Fix problem with wiping of converted LVs.
Fix memleak in scanning (2.03.11).
Fix corner case allocation for thin-pools.
Version 2.03.11 - 08th January 2021
===================================
Fix pvck handling MDA at offset different from 4096.
Partial or degraded activation of writecache is not allowed.
Enhance error handling for fsadm and handle correct fsck result.
Dmeventd lvm plugin ignores higher reserved_stack lvm.conf values.
Support using BLKZEROOUT for clearing devices.
Support interruption when wipping LVs.
Support interruption for bcache waiting.
Fix bcache when device has too many failing writes.
Fix bcache waiting for IO completion with failing disks.
Configure use own python path name order to prefer using python3.
Add configure --enable-editline support as an alternative to readline.
Enhance reporting and error handling when creating thin volumes.
Enable vgsplit for VDO volumes.
Lvextend of vdo pool volumes ensure at least 1 new VDO slab is added.
Use revert_lv() on reload error path after vg_revert().
Configure --with-integrity enabled.
Restore lost signal blocking while VG lock is held.
Improve estimation of needed extents when creating thin-pool.
Use extra 1% when resizing thin-pool metadata LV with --use-policy.
Enhance --use-policy percentage rounding.
Configure --with-vdo and --with-writecache as internal segments.
Improving VDO man page examples.
Allow pvmove of writecache origin.
Report integrity fields.
Integrity volumes defaults to journal mode.
Switch code base to use flexible array syntax.
Fix 64bit math when calculation cachevol size.
Preserve uint32_t for seqno handling.
Switch from mmap to plain read when loading regular files.
Update lvmvdo man page and better explain DISCARD usage.
Version 2.03.10 - 09th August 2020
==================================
Add writecache and integrity support to lvmdbusd.
Generate unique cachevol name when default required from lvcreate.
Converting RAID1 volume to one with same number of legs now succeeds with a
warning.
Fix conversion to raid from striped lagging type.
Fix conversion to 'mirrored' mirror log with larger regionsize.
Zero pool metadata on allocation (disable with allocation/zero_metadata=0).
Failure in zeroing or wiping will fail command (bypass with -Zn, -Wn).
Add lvcreate of new cache or writecache lv with single command.
Fix running out of free buffers for async writing for larger writes.
Version 2.03.10 -
=================================
Add integrity with raid capability.
Fix support for lvconvert --repair used by foreign apps (i.e. Docker).
@@ -296,6 +153,7 @@ Version 2.03.00 - 10th October 2018
Remove clvmd
Remove lvmlib (api)
Remove lvmetad
lvconvert: provide possible layouts between linear and striped/raid
Use versionsort to fix archive file expiry beyond 100000 files.
Version 2.02.178-rc1 - 24th May 2018
@@ -1815,7 +1673,7 @@ Version 2.02.105 - 20th January 2014
Allow lvmetad to reuse stale socket.
Only unlink lvmetad socket on error if created by the same process.
Append missing newline to lvmetad missing socket path error message.
Check for non-zero alignment in _text_pv_add_metadata_area() to not div by 0.
Check for non-zero aligment in _text_pv_add_metadata_area() to not div by 0.
Add allocation/use_blkid_wiping to lvm.conf to enable blkid wiping.
Enable blkid_wiping by default if the blkid library is present.
Add configure --disable-blkid_wiping to disable libblkid signature detection.

View File

@@ -1,29 +1,9 @@
Version 1.02.181 -
===================================
Add IMA support with 'dmsetup measure' command.
Add defines DM_NAME_LIST_FLAG_HAS_UUID, DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID.
Enhance tracking of activated devices when preloading dm tree.
Fix bug in construction of cache table line (regression from 1.02.159).
Version 1.02.179 - 11th August 2021
===================================
Version 1.02.177 - 07th May 2021
================================
Configure proceeds without libaio to allow build of device-mapper only.
Fix symbol versioning build with -O2 -flto.
Add dm_tree_node_add_thin_pool_target_v1 with crop_metadata support.
Version 1.02.175 - 08th January 2021
====================================
Version 1.02.173 - 09th August 2020
===================================
Version 1.02.173 -
==================================
Add support for VDO in blkdeactivate script.
Version 1.02.171 - 26th March 2020
==================================
Try to remove all created devices on dm preload tree error path.
Fix dm_list interators with gcc 10 optimization (-ftree-pta).
Dmeventd handles timer without looping on short intervals.
@@ -567,7 +547,7 @@ Version 1.02.86 - 23rd June 2014
Add DM_REPORT_FIELD_TYPE_STRING_LIST: separate string and string list fields.
Add dm_str_list to libdevmapper for string list type definition and its reuse.
Add dmsetup -S/--select to define selection criteria for dmsetup reports.
Add dm_report_init_with_selection to initialize report with selection criteria.
Add dm_report_init_with_selection to intialize report with selection criteria.
Add DM_REPORT_FIELD_TYPE_SIZE: separate number and size reporting fields.
Use RemoveOnStop for dm-event.socket systemd unit.
Document env var 'DM_DEFAULT_NAME_MANGLING_MODE' in dmsetup man page.

26
aclocal.m4 vendored
View File

@@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -413,7 +413,7 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
])dnl PKG_HAVE_DEFINE_WITH_MODULES
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Copyright (C) 1999-2017 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -446,12 +446,10 @@ AC_DEFUN([AM_PATH_PYTHON],
[
dnl Find a Python interpreter. Python versions prior to 2.0 are not
dnl supported. (2.0 was released on October 16, 2000).
dnl FIXME: Remove the need to hard-code Python versions here.
m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
[python python2 python3 dnl
python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl
python3.2 python3.1 python3.0 dnl
python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl
python2.0])
[python python2 python3 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl
python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0])
AC_ARG_VAR([PYTHON], [the Python interpreter])
@@ -496,14 +494,12 @@ AC_DEFUN([AM_PATH_PYTHON],
m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
else
dnl Query Python for its version number. Although site.py simply uses
dnl sys.version[:3], printing that failed with Python 3.10, since the
dnl trailing zero was eliminated. So now we output just the major
dnl and minor version numbers, as numbers. Apparently the tertiary
dnl version is not of interest.
dnl Query Python for its version number. Getting [:3] seems to be
dnl the best way to do this; it's what "site.py" does in the standard
dnl library.
AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
[am_cv_python_version=`$PYTHON -c "import sys; print('%u.%u' % sys.version_info[[:2]])"`])
[am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
dnl Use the values of $prefix and $exec_prefix for the corresponding
@@ -653,7 +649,7 @@ for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
sys.exit(sys.hexversion < minverhex)"
AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
# Copyright (C) 2001-2017 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,

View File

@@ -22,26 +22,17 @@ struct dm_hash_node {
void *data;
unsigned data_len;
unsigned keylen;
unsigned hash;
char key[0];
};
struct dm_hash_table {
unsigned num_nodes;
unsigned num_hint;
unsigned mask_slots; /* (slots - 1) -> used as hash mask */
unsigned collisions; /* Collissions of hash keys */
unsigned search; /* How many keys were searched */
unsigned found; /* How many nodes were found */
unsigned same_hash; /* Was there a colision with same masked hash and len ? */
unsigned num_slots;
struct dm_hash_node **slots;
};
#if 0 /* TO BE REMOVED */
static unsigned _hash(const void *key, unsigned len)
{
/* Permutation of the Integers 0 through 255 */
static unsigned char _nums[] = {
/* Permutation of the Integers 0 through 255 */
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,
@@ -66,16 +57,29 @@ static unsigned _hash(const void *key, unsigned len)
44, 38, 31, 149, 135, 0, 216, 52, 63, 23, 37, 69, 39, 117, 146, 184,
163, 200, 222, 235, 248, 243, 219, 10, 152, 131, 123, 229, 203, 76, 120,
209
};
};
const uint8_t *str = key;
unsigned h = 0, g;
static struct dm_hash_node *_create_node(const char *str, unsigned len)
{
struct dm_hash_node *n = malloc(sizeof(*n) + len);
if (n) {
memcpy(n->key, str, len);
n->keylen = len;
}
return n;
}
static unsigned long _hash(const char *str, unsigned len)
{
unsigned long h = 0, g;
unsigned i;
for (i = 0; i < len; i++) {
h <<= 4;
h += _nums[*str++];
g = h & ((unsigned) 0xf << 16u);
h += _nums[(unsigned char) *str++];
g = h & ((unsigned long) 0xf << 16u);
if (g) {
h ^= g >> 16u;
h ^= g >> 5u;
@@ -85,99 +89,30 @@ static unsigned _hash(const void *key, unsigned len)
return h;
}
/* In-kernel DM hashing, still lots of collisions */
static unsigned _hash_in_kernel(const char *key, unsigned len)
{
const unsigned char *str = (unsigned char *)key;
const unsigned hash_mult = 2654435387U;
unsigned hash = 0, i;
for (i = 0; i < len; ++i)
hash = (hash + str[i]) * hash_mult;
return hash;
}
#endif
#undef get16bits
#if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
/*
* Adapted Bob Jenkins hash to read by 2 bytes if possible.
* https://secure.wikimedia.org/wikipedia/en/wiki/Jenkins_hash_function
*
* Reduces amount of hash collisions
*/
static unsigned _hash(const void *key, unsigned len)
{
const uint8_t *str = (uint8_t*) key;
unsigned hash = 0, i;
unsigned sz = len / 2;
for(i = 0; i < sz; ++i) {
hash += get16bits(str + 2 * i);
hash += (hash << 10);
hash ^= (hash >> 6);
}
if (len & 1) {
hash += str[len - 1];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
static struct dm_hash_node *_create_node(const void *key, unsigned len)
{
struct dm_hash_node *n = malloc(sizeof(*n) + len);
if (n) {
memcpy(n->key, key, len);
n->keylen = len;
}
return n;
}
struct dm_hash_table *dm_hash_create(unsigned size_hint)
{
size_t len;
unsigned new_size = 16u;
struct dm_hash_table *hc = zalloc(sizeof(*hc));
if (!hc) {
log_error("Failed to allocate memory for hash.");
return 0;
}
hc->num_hint = size_hint;
if (!hc)
return_0;
/* round size hint up to a power of two */
while (new_size < size_hint)
new_size = new_size << 1;
hc->mask_slots = new_size - 1;
hc->num_slots = new_size;
len = sizeof(*(hc->slots)) * new_size;
if (!(hc->slots = zalloc(len))) {
free(hc);
log_error("Failed to allocate slots for hash.");
return 0;
}
if (!(hc->slots = zalloc(len)))
goto_bad;
return hc;
bad:
free(hc->slots);
free(hc);
return 0;
}
static void _free_nodes(struct dm_hash_table *t)
@@ -185,16 +120,7 @@ static void _free_nodes(struct dm_hash_table *t)
struct dm_hash_node *c, *n;
unsigned i;
#ifdef DEBUG
log_debug("Free hash hint:%d slots:%d nodes:%d (s:%d f:%d c:%d h:%d)",
t->num_hint, t->mask_slots + 1, t->num_nodes,
t->search, t->found, t->collisions, t->same_hash);
#endif
if (!t->num_nodes)
return;
for (i = 0; i <= t->mask_slots; i++)
for (i = 0; i < t->num_slots; i++)
for (c = t->slots[i]; c; c = n) {
n = c->next;
free(c);
@@ -208,30 +134,21 @@ void dm_hash_destroy(struct dm_hash_table *t)
free(t);
}
static struct dm_hash_node **_findh(struct dm_hash_table *t, const void *key,
uint32_t len, unsigned hash)
{
struct dm_hash_node **c;
++t->search;
for (c = &t->slots[hash & t->mask_slots]; *c; c = &((*c)->next)) {
if ((*c)->keylen == len && (*c)->hash == hash) {
if (!memcmp(key, (*c)->key, len)) {
++t->found;
break;
}
++t->same_hash;
}
++t->collisions;
}
return c;
}
static struct dm_hash_node **_find(struct dm_hash_table *t, const void *key,
uint32_t len)
{
return _findh(t, key, len, _hash(key, len));
unsigned h = _hash(key, len) & (t->num_slots - 1);
struct dm_hash_node **c;
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
continue;
if (!memcmp(key, (*c)->key, len))
break;
}
return c;
}
void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key,
@@ -245,8 +162,7 @@ void *dm_hash_lookup_binary(struct dm_hash_table *t, const void *key,
int dm_hash_insert_binary(struct dm_hash_table *t, const void *key,
uint32_t len, void *data)
{
unsigned hash = _hash(key, len);
struct dm_hash_node **c = _findh(t, key, len, hash);
struct dm_hash_node **c = _find(t, key, len);
if (*c)
(*c)->data = data;
@@ -257,7 +173,6 @@ int dm_hash_insert_binary(struct dm_hash_table *t, const void *key,
return 0;
n->data = data;
n->hash = hash;
n->next = 0;
*c = n;
t->num_nodes++;
@@ -301,7 +216,7 @@ static struct dm_hash_node **_find_str_with_val(struct dm_hash_table *t,
struct dm_hash_node **c;
unsigned h;
h = _hash(key, len) & t->mask_slots;
h = _hash(key, len) & (t->num_slots - 1);
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
@@ -332,7 +247,7 @@ int dm_hash_insert_allow_multiple(struct dm_hash_table *t, const char *key,
n->data = (void *)val;
n->data_len = val_len;
h = _hash(key, len) & t->mask_slots;
h = _hash(key, len) & (t->num_slots - 1);
first = t->slots[h];
@@ -400,7 +315,7 @@ void *dm_hash_lookup_with_count(struct dm_hash_table *t, const char *key, int *c
*count = 0;
h = _hash(key, len) & t->mask_slots;
h = _hash(key, len) & (t->num_slots - 1);
for (c = &t->slots[h]; *c; c = &((*c)->next)) {
if ((*c)->keylen != len)
@@ -429,7 +344,7 @@ void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
struct dm_hash_node *c, *n;
unsigned i;
for (i = 0; i <= t->mask_slots; i++)
for (i = 0; i < t->num_slots; i++)
for (c = t->slots[i]; c; c = n) {
n = c->next;
f(c->data);
@@ -439,8 +354,8 @@ void dm_hash_iter(struct dm_hash_table *t, dm_hash_iterate_fn f)
void dm_hash_wipe(struct dm_hash_table *t)
{
_free_nodes(t);
memset(t->slots, 0, sizeof(struct dm_hash_node *) * (t->mask_slots + 1));
t->num_nodes = t->collisions = t->search = t->same_hash = 0u;
memset(t->slots, 0, sizeof(struct dm_hash_node *) * t->num_slots);
t->num_nodes = 0u;
}
char *dm_hash_get_key(struct dm_hash_table *t __attribute__((unused)),
@@ -460,7 +375,7 @@ static struct dm_hash_node *_next_slot(struct dm_hash_table *t, unsigned s)
struct dm_hash_node *c = NULL;
unsigned i;
for (i = s; i <= t->mask_slots && !c; i++)
for (i = s; i < t->num_slots && !c; i++)
c = t->slots[i];
return c;
@@ -473,5 +388,7 @@ struct dm_hash_node *dm_hash_get_first(struct dm_hash_table *t)
struct dm_hash_node *dm_hash_get_next(struct dm_hash_table *t, struct dm_hash_node *n)
{
return n->next ? n->next : _next_slot(t, (n->hash & t->mask_slots) + 1);
unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
return n->next ? n->next : _next_slot(t, h + 1);
}

View File

@@ -47,7 +47,7 @@ struct value_chain {
struct prefix_chain {
struct value child;
unsigned len;
uint8_t prefix[];
uint8_t prefix[0];
};
struct node4 {
@@ -1032,7 +1032,7 @@ void radix_tree_iterate(struct radix_tree *rt, uint8_t *kb, uint8_t *ke,
{
struct lookup_result lr = _lookup_prefix(&rt->root, kb, ke);
if (lr.kb == ke || _prefix_chain_matches(&lr, ke))
(void) _iterate(lr.v, it);
_iterate(lr.v, it);
}
//----------------------------------------------------------------

View File

@@ -18,7 +18,7 @@
//----------------------------------------------------------------
#define container_of(v, t, head) \
((t *)((char *)(v) - offsetof(t, head)))
((t *)((const char *)(v) - offsetof(t, head)))
//----------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -28,13 +28,13 @@ local {
# main configuration file, e.g. lvm.conf. When used, it must be set to
# a unique value among all hosts sharing access to the storage,
# e.g. a host name.
#
#
# Example
# Set no system ID:
# system_id = ""
# Set the system_id to a specific name:
# system_id = "host1"
#
#
# This configuration option has an automatic default value.
# system_id = ""

865
configure vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -46,7 +46,6 @@ const char *find_config_tree_str(struct cmd_context *cmd, int id, struct profile
return "STRING";
}
/*
struct logical_volume *origin_from_cow(const struct logical_volume *lv)
{
if (lv)
@@ -54,7 +53,6 @@ struct logical_volume *origin_from_cow(const struct logical_volume *lv)
__coverity_panic__();
}
*/
/* simple_memccpy() from glibc */
void *memccpy(void *dest, const void *src, int c, size_t n)

View File

@@ -22,9 +22,6 @@ SOURCES = clogd.c cluster.c compat.c functions.c link_mon.c local.c logging.c
TARGETS = cmirrord
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
CFLOW_TARGET := $(TARGETS)
include $(top_builddir)/make.tmpl
LMLIBS += $(CPG_LIBS)
@@ -36,8 +33,6 @@ cmirrord: $(OBJECTS)
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) \
$(LMLIBS) -L$(top_builddir)/libdm -ldevmapper $(LIBS)
install_cluster: $(TARGETS)
install: $(TARGETS)
@echo " [INSTALL] $<"
$(Q) $(INSTALL_PROGRAM) -D $< $(usrsbindir)/$(<F)
install: install_cluster
$(Q) $(INSTALL_PROGRAM) -D cmirrord $(usrsbindir)/cmirrord

View File

@@ -245,7 +245,6 @@ static void daemonize(void)
}
LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
/* coverity[leaked_handle] devnull cannot leak here */
}
/*

View File

@@ -1383,7 +1383,7 @@ static void cpg_leave_callback(struct clog_cpg *match,
size_t member_list_entries)
{
unsigned i;
int j, fd = -1;
int j, fd;
uint32_t lowest = match->lowest_id;
struct clog_request *rq, *n;
struct checkpoint_data *p_cp, *c_cp;
@@ -1548,7 +1548,7 @@ static void cpg_config_callback(cpg_handle_t handle, const struct cpg_name *gnam
member_list, member_list_entries);
}
static cpg_callbacks_t cpg_callbacks = {
cpg_callbacks_t cpg_callbacks = {
.cpg_deliver_fn = cpg_message_callback,
.cpg_confchg_fn = cpg_config_callback,
};

View File

@@ -39,7 +39,7 @@ struct clog_request {
* machine. If the two are equal, there is no need
* to do endian conversions.
*/
union version_u {
union {
uint64_t version[2]; /* LE version and native version */
struct dm_list list;
} u;

View File

@@ -378,7 +378,7 @@ static int _clog_ctr(char *uuid, uint64_t luid,
uint32_t block_on_error = 0;
int disk_log;
char disk_path[PATH_MAX] = { 0 };
char disk_path[PATH_MAX];
int unlink_path = 0;
long page_size;
int pages;
@@ -658,7 +658,8 @@ static int clog_dtr(struct dm_ulog_request *rq)
if (lc->disk_fd != -1 && close(lc->disk_fd))
LOG_ERROR("Failed to close disk log: %s",
strerror(errno));
free(lc->disk_buffer);
if (lc->disk_buffer)
free(lc->disk_buffer);
free(lc->clean_bits);
free(lc->sync_bits);
free(lc);

View File

@@ -14,21 +14,11 @@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
abs_srcdir = @abs_srcdir@
SOURCES = libdevmapper-event.c
SOURCES2 = dmeventd.c
TARGETS = dmeventd
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES) $(SOURCES2) \
plugins/lvm2/dmeventd_lvm.c \
plugins/mirror/dmeventd_mirror.c \
plugins/raid/dmeventd_raid.c \
plugins/snapshot/dmeventd_snapshot.c \
plugins/thin/dmeventd_thin.c \
plugins/vdo/dmeventd_vdo.c \
)
CFLOW_TARGET := $(TARGETS)
.PHONY: install_lib_dynamic install_lib_static install_include \
install_pkgconfig install_dmeventd_dynamic install_dmeventd_static \
@@ -47,7 +37,6 @@ endif
LIB_VERSION = $(LIB_VERSION_DM)
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIBS = $(PTHREAD_LIBS) -L$(interfacebuilddir) -ldevmapper
CLEAN_TARGETS = dmeventd.static $(LIB_NAME).a
@@ -57,6 +46,7 @@ endif
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
CFLOW_TARGET = dmeventd
EXPORTED_HEADER = $(srcdir)/libdevmapper-event.h
EXPORTED_FN_PREFIX = dm_event
@@ -65,26 +55,34 @@ include $(top_builddir)/make.tmpl
all: device-mapper
device-mapper: $(TARGETS)
plugins.device-mapper: $(LIB_SHARED)
CFLAGS_dmeventd.o += $(EXTRA_EXEC_CFLAGS)
LIBS += $(PTHREAD_LIBS) -L$(top_builddir)/libdm -ldevmapper
dmeventd: $(LIB_SHARED) dmeventd.o
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS)
$(Q) $(CC) $(CFLAGS) -L. $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) -lm
dmeventd.static: $(LIB_STATIC) dmeventd.o
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static dmeventd.o \
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) dmeventd.o \
-o $@ $(DL_LIBS) $(DMEVENT_LIBS) $(LIBS) $(STATIC_LIBS)
ifeq ("@PKGCONFIG@", "yes")
INSTALL_LIB_TARGETS += install_pkgconfig
endif
ifneq ("$(CFLOW_CMD)", "")
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
-include $(top_builddir)/lib/liblvm-internal.cflow
-include $(top_builddir)/lib/liblvm2cmd.cflow
-include $(top_builddir)/daemons/dmeventd/$(LIB_NAME).cflow
-include $(top_builddir)/daemons/dmeventd/plugins/mirror/$(LIB_NAME)-lvm2mirror.cflow
endif
install_include: $(srcdir)/libdevmapper-event.h
@echo " [INSTALL] $(<F)"
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DATA) -D $< $(includedir)/$(<F)
install_pkgconfig: libdevmapper-event.pc

View File

@@ -678,9 +678,6 @@ static int _get_status(struct message_data *message_data)
char **buffers;
char *message;
if (!message_data->id)
return -EINVAL;
_lock_mutex();
count = dm_list_size(&_thread_registry);
buffers = alloca(sizeof(char*) * count);
@@ -1075,7 +1072,6 @@ out:
* "label at end of compound statement" */
;
/* coverity[lock_order] _global_mutex is kept locked */
pthread_cleanup_pop(1);
return NULL;
@@ -1746,8 +1742,7 @@ static void _init_thread_signals(void)
sigset_t my_sigset;
struct sigaction act = { .sa_handler = _sig_alarm };
if (sigaction(SIGALRM, &act, NULL))
log_sys_debug("sigaction", "SIGLARM");
sigaction(SIGALRM, &act, NULL);
sigfillset(&my_sigset);
/* These are used for exiting */
@@ -2033,8 +2028,8 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos)
static void _restart_dmeventd(void)
{
struct dm_event_fifos fifos = {
.client = -1,
.server = -1,
.client = -1,
/* FIXME Make these either configurable or depend directly on dmeventd_path */
.client_path = DM_EVENT_FIFO_CLIENT,
.server_path = DM_EVENT_FIFO_SERVER
@@ -2073,7 +2068,7 @@ static void _restart_dmeventd(void)
++count;
}
if (!(_initial_registrations = zalloc(sizeof(char*) * (count + 1)))) {
if (!(_initial_registrations = malloc(sizeof(char*) * (count + 1)))) {
fprintf(stderr, "Memory allocation registration failed.\n");
goto bad;
}
@@ -2085,6 +2080,7 @@ static void _restart_dmeventd(void)
}
message += strlen(message) + 1;
}
_initial_registrations[count] = NULL;
if (version >= 2) {
if (daemon_talk(&fifos, &msg, DM_EVENT_CMD_GET_PARAMETERS, "-", "-", 0, 0)) {

View File

@@ -615,8 +615,8 @@ static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_messag
{
int ret;
struct dm_event_fifos fifos = {
.client = -1,
.server = -1,
.client = -1,
/* FIXME Make these either configurable or depend directly on dmeventd_path */
.client_path = DM_EVENT_FIFO_CLIENT,
.server_path = DM_EVENT_FIFO_SERVER
@@ -709,11 +709,15 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
static char *_fetch_string(char **src, const int delimiter)
{
char *p, *ret;
size_t len = (p = strchr(*src, delimiter)) ?
(size_t)(p - *src) : strlen(*src);
if ((ret = strndup(*src, len)))
*src += len + 1;
if ((p = strchr(*src, delimiter)))
*p = 0;
if ((ret = strdup(*src)))
*src += strlen(ret) + 1;
if (p)
*p = delimiter;
return ret;
}

View File

@@ -71,7 +71,7 @@ int dmeventd_lvm2_init(void)
if (!_lvm_handle) {
lvm2_log_fn(_lvm2_print_log);
if (!(_lvm_handle = lvm2_init_threaded()))
if (!(_lvm_handle = lvm2_init()))
goto out;
/*

View File

@@ -25,6 +25,9 @@ LIB_NAME = libdevmapper-event-lvm2mirror
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin

View File

@@ -24,6 +24,9 @@ LIB_NAME = libdevmapper-event-lvm2raid
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin

View File

@@ -77,7 +77,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
if (dead) {
/*
* Use the first event to run a repair ignoring any additional ones.
* Use the first event to run a repair ignoring any additonal ones.
*
* We presume lvconvert to do pre-repair
* checks to avoid bloat in this plugin.

View File

@@ -24,6 +24,9 @@ LIB_NAME = libdevmapper-event-lvm2thin
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin

View File

@@ -24,6 +24,9 @@ LIB_NAME = libdevmapper-event-lvm2vdo
LIB_SHARED = $(LIB_NAME).$(LIB_SUFFIX)
LIB_VERSION = $(LIB_VERSION_LVM)
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
include $(top_builddir)/make.tmpl
install_lvm2: install_dm_plugin

View File

@@ -22,7 +22,6 @@
* in runtime we are linked agains systems libdm 'older' library
* which does not provide this symbol and plugin fails to load
*/
/* coverity[unnecessary_header] used for parsing */
#include "device_mapper/vdo/status.c"
#include <sys/wait.h>

View File

@@ -15,8 +15,7 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
lvmdbuspydir = $(python3dir)/lvmdbusd
lvmdbusdir = $(DESTDIR)$(lvmdbuspydir)
lvmdbusdir = $(python3dir)/lvmdbusd
LVMDBUS_SRCDIR_FILES = \
automatedproperties.py \
@@ -54,16 +53,16 @@ include $(top_builddir)/make.tmpl
all:
$(Q) test -x $(LVMDBUSD) || chmod 755 $(LVMDBUSD)
install_lvmdbusd: $(LVMDBUSD)
install_lvmdbusd:
@echo " [INSTALL] $<"
$(Q) $(INSTALL_DIR) $(sbindir)
$(Q) $(INSTALL_SCRIPT) $(LVMDBUSD) $(sbindir)
$(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]
$(Q) $(INSTALL_DIR) $(DESTDIR)$(lvmdbusdir)
$(Q) (cd $(srcdir); $(INSTALL_DATA) $(LVMDBUS_SRCDIR_FILES) $(DESTDIR)$(lvmdbusdir))
$(Q) $(INSTALL_DATA) $(LVMDBUS_BUILDDIR_FILES) $(DESTDIR)$(lvmdbusdir)
$(Q) PYTHON=$(PYTHON3) $(PYCOMPILE) --destdir "$(DESTDIR)" --basedir "$(lvmdbusdir)" $(LVMDBUS_SRCDIR_FILES) $(LVMDBUS_BUILDDIR_FILES)
$(Q) $(CHMOD) 755 $(DESTDIR)$(lvmdbusdir)/__pycache__
$(Q) $(CHMOD) 444 $(DESTDIR)$(lvmdbusdir)/__pycache__/*.py[co]
install_lvm2: install_lvmdbusd

View File

@@ -157,15 +157,14 @@ class AutomatedProperties(dbus.service.Object):
if not self._ap_search_method:
return 0
search = self.lvm_id
if search_key:
search = search_key
# Either we have the new object state or we need to go fetch it
if object_state:
new_state = object_state
else:
if search_key:
search = search_key
else:
search = self.lvm_id
new_state = self._ap_search_method([search])[0]
assert isinstance(new_state, State)

View File

@@ -9,14 +9,13 @@
import subprocess
from . import cfg
from .cmdhandler import options_to_cli_args, LvmExecutionMeta, call_lvm
from .cmdhandler import options_to_cli_args, LvmExecutionMeta
import dbus
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug,\
mt_async_call
from .request import RequestEntry
add_no_notify
import os
import threading
import time
import traceback
def pv_move_lv_cmd(move_options, lv_full_name,
@@ -40,50 +39,58 @@ def lv_merge_cmd(merge_options, lv_full_name):
return cmd
def _load_wrapper(ignored):
cfg.load()
def _move_callback(job_state, line_str):
try:
if line_str.count(':') == 2:
(device, ignore, percentage) = line_str.split(':')
job_state.Percent = int(round(
float(percentage.strip()[:-1]), 1))
# While the move is in progress we need to periodically update
# the state to reflect where everything is at. we will do this
# by scheduling the load to occur in the main work queue.
r = RequestEntry(
-1, _load_wrapper, ("_move_callback: load",), None, None, False)
cfg.worker_q.put(r)
except ValueError:
log_error("Trying to parse percentage which failed for %s" % 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.
command.insert(0, cfg.LVM_CMD)
# Instruct lvm to not register an event with us
command = add_no_notify(command)
#(self, start, ended, cmd, ec, stdout_txt, stderr_txt)
meta = LvmExecutionMeta(time.time(), 0, command, -1000, None, None)
cfg.blackbox.add(meta)
ec, stdout, stderr = call_lvm(command, line_cb=_move_callback,
cb_data=job_state)
process = subprocess.Popen(command, stdout=subprocess.PIPE,
env=os.environ,
stderr=subprocess.PIPE, close_fds=True)
log_debug("Background process for %s is %d" %
(str(command), process.pid))
lines_iterator = iter(process.stdout.readline, b"")
for line in lines_iterator:
line_str = line.decode("utf-8")
# Check to see if the line has the correct number of separators
try:
if line_str.count(':') == 2:
(device, ignore, percentage) = line_str.split(':')
job_state.Percent = round(
float(percentage.strip()[:-1]), 1)
# While the move is in progress we need to periodically update
# the state to reflect where everything is at.
cfg.load()
except ValueError:
log_error("Trying to parse percentage which failed for %s" %
line_str)
out = process.communicate()
with meta.lock:
meta.ended = time.time()
meta.ec = ec
meta.stderr_txt = stderr
meta.ec = process.returncode
meta.stderr_txt = out[1]
if ec == 0:
if process.returncode == 0:
job_state.Percent = 100
else:
raise dbus.exceptions.DBusException(
interface_name,
'Exit code %s, stderr = %s' % (str(ec), stderr))
'Exit code %s, stderr = %s' % (str(process.returncode), out[1]))
cfg.load()
return '/'

View File

@@ -8,7 +8,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from subprocess import Popen, PIPE
import select
import time
import threading
from itertools import chain
@@ -17,8 +16,7 @@ import traceback
import os
from lvmdbusd import cfg
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify,\
make_non_block, read_decoded
from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error, add_no_notify
from lvmdbusd.lvm_shell_proxy import LVMShellProxy
try:
@@ -84,23 +82,16 @@ def _debug_c(cmd, exit_code, out):
log_error(("STDERR=\n %s\n" % out[1]))
def call_lvm(command, debug=False, line_cb=None,
cb_data=None):
def call_lvm(command, debug=False):
"""
Call an executable and return a tuple of exitcode, stdout, stderr
:param command: Command to execute
:param debug: Dump debug to stdout
:param line_cb: Call the supplied function for each line read from
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 callback to allow caller access to
its own data
# Callback signature
def my_callback(my_context, line_read_stdin)
pass
:param command: Command to execute
:param debug: Dump debug to stdout
"""
# print 'STACK:'
# for line in traceback.format_stack():
# print line.strip()
# Prepend the full lvm executable so that we can run different versions
# in different locations on the same box
command.insert(0, cfg.LVM_CMD)
@@ -108,44 +99,10 @@ def call_lvm(command, debug=False, line_cb=None,
process = Popen(command, stdout=PIPE, stderr=PIPE, close_fds=True,
env=os.environ)
out = process.communicate()
stdout_text = ""
stderr_text = ""
stdout_index = 0
make_non_block(process.stdout)
make_non_block(process.stderr)
while True:
try:
rd_fd = [process.stdout.fileno(), process.stderr.fileno()]
ready = select.select(rd_fd, [], [], 2)
for r in ready[0]:
if r == process.stdout.fileno():
stdout_text += read_decoded(process.stdout)
elif r == process.stderr.fileno():
stderr_text += read_decoded(process.stderr)
if line_cb is not None:
# Process the callback for each line read!
while True:
i = stdout_text.find("\n", stdout_index)
if i != -1:
try:
line_cb(cb_data, stdout_text[stdout_index:i])
except:
st = traceback.format_exc()
log_error("call_lvm: line_cb exception: \n %s" % st)
stdout_index = i + 1
else:
break
# Check to see if process has terminated, None when running
if process.poll() is not None:
break
except IOError as ioe:
log_debug("call_lvm:" + str(ioe))
pass
stdout_text = bytes(out[0]).decode("utf-8")
stderr_text = bytes(out[1]).decode("utf-8")
if debug or process.returncode != 0:
_debug_c(command, process.returncode, (stdout_text, stderr_text))
@@ -496,15 +453,6 @@ def lv_cache_lv(cache_pool_full_name, lv_full_name, cache_options):
return call(cmd)
def lv_writecache_lv(cache_lv_full_name, lv_full_name, cache_options):
# lvconvert --type writecache --cachevol VG/CacheLV VG/OriginLV
cmd = ['lvconvert']
cmd.extend(options_to_cli_args(cache_options))
cmd.extend(['-y', '--type', 'writecache', '--cachevol',
cache_lv_full_name, lv_full_name])
return call(cmd)
def lv_detach_cache(lv_full_name, detach_options, destroy_cache):
cmd = ['lvconvert']
if destroy_cache:
@@ -627,13 +575,7 @@ def lvm_full_report_json():
assert(type(out) == dict)
return out
else:
try:
return json.loads(out)
except json.decoder.JSONDecodeError as joe:
log_error("JSONDecodeError %s, \n JSON=\n%s\n" %
(str(joe), out))
raise joe
return json.loads(out)
return None

View File

@@ -20,30 +20,22 @@ import traceback
def _main_thread_load(refresh=True, emit_signal=True):
num_total_changes = 0
to_remove = []
(changes, remove) = load_pvs(
num_total_changes += load_pvs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1:]
num_total_changes += changes
to_remove.extend(remove)
(changes, remove) = load_vgs(
cache_refresh=False)[1]
num_total_changes += load_vgs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1:]
cache_refresh=False)[1]
num_total_changes += changes
to_remove.extend(remove)
(lv_changes, remove) = load_lvs(
lv_changes = load_lvs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1:]
cache_refresh=False)[1]
num_total_changes += lv_changes
to_remove.extend(remove)
# When the LVs change it can cause another change in the VGs which is
# missed if we don't scan through the VGs again. We could achieve this
@@ -52,23 +44,10 @@ def _main_thread_load(refresh=True, emit_signal=True):
# changes causing the dbus object representing it to be removed and
# recreated.
if refresh and lv_changes > 0:
(changes, remove) = load_vgs(
num_total_changes += load_vgs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1:]
num_total_changes += changes
to_remove.extend(remove)
# Remove any objects that are no longer needed. We do this after we process
# all the objects to ensure that references still exist for objects that
# are processed after them.
to_remove.reverse()
for i in to_remove:
dbus_obj = cfg.om.get_object_by_path(i)
if dbus_obj:
cfg.om.remove_object(dbus_obj, True)
num_total_changes += 1
cache_refresh=False)[1]
return num_total_changes

View File

@@ -75,10 +75,11 @@ def common(retrieve, o_type, search_keys,
object_path = None
to_remove = []
if refresh:
to_remove = list(existing_paths.keys())
for k in list(existing_paths.keys()):
cfg.om.remove_object(cfg.om.get_object_by_path(k), True)
num_changes += 1
num_changes += len(rc)
return rc, num_changes, to_remove
return rc, num_changes

View File

@@ -388,7 +388,7 @@ class LvCommon(AutomatedProperties):
'l': 'mirror log device', 'c': 'under conversion',
'V': 'thin Volume', 't': 'thin pool', 'T': 'Thin pool data',
'e': 'raid or pool metadata or pool metadata spare',
'd': 'vdo pool', 'D': 'vdo pool data', 'g': 'integrity',
'd': 'vdo pool', 'D': 'vdo pool data',
'-': 'Unspecified'}
return self.attr_struct(0, type_map)
@@ -743,49 +743,6 @@ class Lv(LvCommon):
cb, cbe, return_tuple=False)
cfg.worker_q.put(r)
@staticmethod
def _writecache_lv(lv_uuid, lv_name, lv_object_path, cache_options):
# Make sure we have a dbus object representing it
dbo = LvCommon.validate_dbus_object(lv_uuid, lv_name)
# Make sure we have dbus object representing lv to cache
lv_to_cache = cfg.om.get_object_by_path(lv_object_path)
if lv_to_cache:
fcn = lv_to_cache.lv_full_name()
rc, out, err = cmdhandler.lv_writecache_lv(
dbo.lv_full_name(), fcn, cache_options)
if rc == 0:
# When we cache an LV, the cache pool and the lv that is getting
# cached need to be removed from the object manager and
# re-created as their interfaces have changed!
mt_remove_dbus_objects((dbo, lv_to_cache))
cfg.load()
lv_converted = cfg.om.get_object_path_by_lvm_id(fcn)
else:
raise dbus.exceptions.DBusException(
LV_INTERFACE,
'Exit code %s, stderr = %s' % (str(rc), err))
else:
raise dbus.exceptions.DBusException(
LV_INTERFACE, 'LV to cache with object path %s not present!' %
lv_object_path)
return lv_converted
@dbus.service.method(
dbus_interface=LV_INTERFACE,
in_signature='oia{sv}',
out_signature='(oo)',
async_callbacks=('cb', 'cbe'))
def WriteCacheLv(self, lv_object, tmo, cache_options, cb, cbe):
r = RequestEntry(
tmo, Lv._writecache_lv,
(self.Uuid, self.lvm_id, lv_object,
cache_options), cb, cbe)
cfg.worker_q.put(r)
# noinspection PyPep8Naming
@utils.dbus_property(VDO_POOL_INTERFACE, 'OperatingMode', 's')
@utils.dbus_property(VDO_POOL_INTERFACE, 'CompressionState', 's')

View File

@@ -13,6 +13,7 @@
import subprocess
import shlex
from fcntl import fcntl, F_GETFL, F_SETFL
import os
import traceback
import sys
@@ -28,8 +29,7 @@ except ImportError:
from lvmdbusd.cfg import LVM_CMD
from lvmdbusd.utils import log_debug, log_error, add_no_notify, make_non_block,\
read_decoded
from lvmdbusd.utils import log_debug, log_error, add_no_notify
SHELL_PROMPT = "lvm> "
@@ -43,6 +43,13 @@ def _quote_arg(arg):
class LVMShellProxy(object):
@staticmethod
def _read(stream):
tmp = stream.read()
if tmp:
return tmp.decode("utf-8")
return ''
# Read until we get prompt back and a result
# @param: no_output Caller expects no output to report FD
# Returns stdout, report, stderr (report is JSON!)
@@ -68,11 +75,11 @@ class LVMShellProxy(object):
for r in ready[0]:
if r == self.lvm_shell.stdout.fileno():
stdout += read_decoded(self.lvm_shell.stdout)
stdout += LVMShellProxy._read(self.lvm_shell.stdout)
elif r == self.report_stream.fileno():
report += read_decoded(self.report_stream)
report += LVMShellProxy._read(self.report_stream)
elif r == self.lvm_shell.stderr.fileno():
stderr += read_decoded(self.lvm_shell.stderr)
stderr += LVMShellProxy._read(self.lvm_shell.stderr)
# Check to see if the lvm process died on us
if self.lvm_shell.poll():
@@ -117,6 +124,11 @@ class LVMShellProxy(object):
assert (num_written == len(cmd_bytes))
self.lvm_shell.stdin.flush()
@staticmethod
def _make_non_block(stream):
flags = fcntl(stream, F_GETFL)
fcntl(stream, F_SETFL, flags | os.O_NONBLOCK)
def __init__(self):
# Create a temp directory
@@ -150,8 +162,8 @@ class LVMShellProxy(object):
stderr=subprocess.PIPE, close_fds=True, shell=True)
try:
make_non_block(self.lvm_shell.stdout)
make_non_block(self.lvm_shell.stderr)
LVMShellProxy._make_non_block(self.lvm_shell.stdout)
LVMShellProxy._make_non_block(self.lvm_shell.stderr)
# wait for the first prompt
errors = self._read_until_prompt(no_output=True)[2]

View File

@@ -27,7 +27,7 @@ class Manager(AutomatedProperties):
@property
def Version(self):
return dbus.String('1.1.0')
return dbus.String('1.0.0')
@staticmethod
def handle_execute(rc, out, err):

View File

@@ -52,8 +52,8 @@ def filter_event(action, device):
# when appropriate.
refresh = False
if 'ID_FS_TYPE' in device:
fs_type_new = device['ID_FS_TYPE']
if '.ID_FS_TYPE_NEW' in device:
fs_type_new = device['.ID_FS_TYPE_NEW']
if 'LVM' in fs_type_new:
refresh = True

View File

@@ -14,7 +14,6 @@ import ctypes
import os
import string
import datetime
from fcntl import fcntl, F_GETFL, F_SETFL
import dbus
from lvmdbusd import cfg
@@ -682,16 +681,3 @@ def _remove_objects(dbus_objects_rm):
# Remove dbus objects from main thread
def mt_remove_dbus_objects(objs):
MThreadRunner(_remove_objects, objs).done()
# Make stream non-blocking
def make_non_block(stream):
flags = fcntl(stream, F_GETFL)
fcntl(stream, F_SETFL, flags | os.O_NONBLOCK)
def read_decoded(stream):
tmp = stream.read()
if tmp:
return tmp.decode("utf-8")
return ''

View File

@@ -30,39 +30,33 @@ ifeq ("@BUILD_LOCKDDLM@", "yes")
LOCK_LIBS += -ldlmcontrol
endif
ifeq ("@BUILD_LOCKDIDM@", "yes")
SOURCES += lvmlockd-idm.c
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
.PHONY: install_lvmlockd
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)
LIBS += $(RT_LIBS) $(DAEMON_LIBS) $(PTHREAD_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)
lvmlockd: $(OBJECTS) $(top_builddir)/libdaemon/client/libdaemonclient.a \
$(top_builddir)/libdaemon/server/libdaemonserver.a
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LOCK_LIBS) $(LIBS)
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LOCK_LIBS) -ldaemonserver $(INTERNAL_LIBS) $(LIBS)
lvmlockctl: lvmlockctl.o $(INTERNAL_LIBS)
lvmlockctl: lvmlockctl.o $(top_builddir)/libdaemon/client/libdaemonclient.a
@echo " [CC] $@"
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ lvmlockctl.o $(INTERNAL_LIBS) $(LIBS)
install_lvmlockd: lvmlockd
@echo " [INSTALL] $<"

View File

@@ -18,11 +18,8 @@
#include <errno.h>
#include <fcntl.h>
#include <syslog.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/wait.h>
static int quit = 0;
static int info = 0;
@@ -33,7 +30,6 @@ static int kill_vg = 0;
static int drop_vg = 0;
static int gl_enable = 0;
static int gl_disable = 0;
static int use_stderr = 0;
static int stop_lockspaces = 0;
static char *arg_vg_name = NULL;
@@ -51,22 +47,6 @@ do { \
printf(fmt "\n", ##args); \
} while (0)
#define log_sys_emerg(fmt, args...) \
do { \
if (use_stderr) \
fprintf(stderr, fmt "\n", ##args); \
else \
syslog(LOG_EMERG, fmt, ##args); \
} while (0)
#define log_sys_warn(fmt, args...) \
do { \
if (use_stderr) \
fprintf(stderr, fmt "\n", ##args); \
else \
syslog(LOG_WARNING, fmt, ##args); \
} while (0)
#define MAX_LINE 512
/* copied from lvmlockd-internal.h */
@@ -457,7 +437,6 @@ retry:
if (count < dump_len)
goto retry;
dump_buf[count] = 0;
rv = 0;
if ((info && dump) || !strcmp(req_name, "dump"))
printf("%s\n", dump_buf);
@@ -523,274 +502,51 @@ static int do_stop_lockspaces(void)
return rv;
}
static int _reopen_fd_to_null(int fd)
static int do_kill(void)
{
int null_fd;
int r = 0;
if ((null_fd = open("/dev/null", O_RDWR)) == -1) {
log_error("open error /dev/null %d", errno);
return 0;
}
if (close(fd)) {
log_error("close error fd %d %d", fd, errno);
goto out;
}
if (dup2(null_fd, fd) == -1) {
log_error("dup2 error %d", errno);
goto out;
}
r = 1;
out:
if (close(null_fd)) {
log_error("close error fd %d %d", null_fd, errno);
return 0;
}
return r;
}
#define MAX_AV_COUNT 32
#define ONE_ARG_LEN 1024
static void _run_command_pipe(const char *cmd_str, pid_t *pid_out, FILE **fp_out)
{
char arg[ONE_ARG_LEN];
char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
char *arg_dup;
int av_count = 0;
int cmd_len;
int arg_len;
pid_t pid = 0;
FILE *fp = NULL;
int pipefd[2];
int i;
for (i = 0; i < MAX_AV_COUNT + 1; i++)
av[i] = NULL;
cmd_len = strlen(cmd_str);
memset(&arg, 0, sizeof(arg));
arg_len = 0;
for (i = 0; i < cmd_len; i++) {
if (!cmd_str[i])
break;
if (av_count == MAX_AV_COUNT)
goto out;
if (cmd_str[i] == '\\') {
if (i == (cmd_len - 1))
break;
i++;
if (cmd_str[i] == '\\') {
arg[arg_len++] = cmd_str[i];
continue;
}
if (isspace(cmd_str[i])) {
arg[arg_len++] = cmd_str[i];
continue;
} else {
break;
}
}
if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
arg[arg_len++] = cmd_str[i];
} else if (isspace(cmd_str[i])) {
if (arg_len) {
if (!(arg_dup = strdup(arg)))
goto out;
av[av_count++] = arg_dup;
}
memset(arg, 0, sizeof(arg));
arg_len = 0;
} else {
break;
}
}
if (arg_len) {
if (av_count >= MAX_AV_COUNT)
goto out;
if (!(arg_dup = strdup(arg)))
goto out;
av[av_count++] = arg_dup;
}
if (pipe(pipefd)) {
log_error("pipe error %d", errno);
goto out;
}
pid = fork();
if (pid < 0) {
log_error("fork error %d", errno);
pid = 0;
goto out;
}
if (pid == 0) {
/* Child -> writer, convert pipe[0] to STDOUT */
if (!_reopen_fd_to_null(STDIN_FILENO))
log_error("reopen STDIN error");
else if (close(pipefd[0 /*read*/]))
log_error("close error pipe[0] %d", errno);
else if (close(STDOUT_FILENO))
log_error("close error STDOUT %d", errno);
else if (dup2(pipefd[1 /*write*/], STDOUT_FILENO) == -1)
log_error("dup2 error STDOUT %d", errno);
else if (close(pipefd[1]))
log_error("close error pipe[1] %d", errno);
else {
execvp(av[0], av);
log_error("execvp error %d", errno);
}
_exit(errno);
}
/* Parent -> reader */
if (close(pipefd[1 /*write*/]))
log_error("close error STDOUT %d", errno);
if (!(fp = fdopen(pipefd[0 /*read*/], "r"))) {
log_error("fdopen STDIN error %d", errno);
if (close(pipefd[0]))
log_error("close error STDIN %d", errno);
}
out:
for (i = 0; i < MAX_AV_COUNT + 1; i++)
free(av[i]);
*pid_out = pid;
*fp_out = fp;
}
/* Returns -1 on error, 0 on success. */
static int _close_command_pipe(pid_t pid, FILE *fp)
{
int status, estatus;
int ret = -1;
if (waitpid(pid, &status, 0) != pid) {
log_error("waitpid error pid %d %d", pid, errno);
goto out;
}
if (WIFEXITED(status)) {
/* pid exited with an exit code */
estatus = WEXITSTATUS(status);
/* exit status 0: child success */
if (!estatus) {
ret = 0;
goto out;
}
/* exit status not zero: child error */
log_error("child exit error %d", estatus);
goto out;
}
if (WIFSIGNALED(status)) {
/* pid terminated due to a signal */
log_error("child exit from signal");
goto out;
}
log_error("child exit problem");
out:
if (fp && fclose(fp))
log_error("fclose error STDIN %d", errno);
return ret;
}
/* Returns -1 on error, 0 on success. */
static int _get_kill_command(char *kill_cmd)
{
char config_cmd[PATH_MAX + 128] = { 0 };
char config_val[1024] = { 0 };
char line[PATH_MAX] = { 0 };
pid_t pid = 0;
FILE *fp = NULL;
snprintf(config_cmd, PATH_MAX, "%s config --typeconfig full global/lvmlockctl_kill_command", LVM_PATH);
_run_command_pipe(config_cmd, &pid, &fp);
if (!pid) {
log_error("failed to run %s", config_cmd);
return -1;
}
if (!fp) {
log_error("failed to get output %s", config_cmd);
_close_command_pipe(pid, fp);
return -1;
}
if (!fgets(line, sizeof(line), fp)) {
log_error("no output from %s", config_cmd);
goto bad;
}
if (sscanf(line, "lvmlockctl_kill_command=\"%256[^\n\"]\"", config_val) != 1) {
log_error("unrecognized config value from %s", config_cmd);
goto bad;
}
if (!config_val[0] || (config_val[0] == ' ')) {
log_error("invalid config value from %s", config_cmd);
goto bad;
}
if (config_val[0] != '/') {
log_error("lvmlockctl_kill_command must be full path");
goto bad;
}
printf("Found lvmlockctl_kill_command: %s\n", config_val);
snprintf(kill_cmd, PATH_MAX, "%s %s", config_val, arg_vg_name);
kill_cmd[PATH_MAX-1] = '\0';
_close_command_pipe(pid, fp);
return 0;
bad:
_close_command_pipe(pid, fp);
return -1;
}
/* Returns -1 on error, 0 on success. */
static int _run_kill_command(char *kill_cmd)
{
pid_t pid = 0;
FILE *fp = NULL;
daemon_reply reply;
int result;
int rv;
_run_command_pipe(kill_cmd, &pid, &fp);
rv = _close_command_pipe(pid, fp);
syslog(LOG_EMERG, "Lost access to sanlock lease storage in VG %s.", arg_vg_name);
/* These two lines explain the manual alternative to the FIXME below. */
syslog(LOG_EMERG, "Immediately deactivate LVs in VG %s.", arg_vg_name);
syslog(LOG_EMERG, "Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
if (!pid)
return -1;
/*
* It may not be strictly necessary to notify lvmlockd of the kill, but
* lvmlockd can use this information to avoid attempting any new lock
* requests in the VG (which would fail anyway), and can return an
* error indicating that the VG has been killed.
*/
if (rv < 0)
return -1;
reply = _lvmlockd_send("kill_vg",
"cmd = %s", "lvmlockctl",
"pid = " FMTd64, (int64_t) getpid(),
"vg_name = %s", arg_vg_name,
NULL);
return 0;
if (!_lvmlockd_result(reply, &result)) {
log_error("lvmlockd result %d", result);
rv = result;
} else {
rv = 0;
}
daemon_reply_destroy(reply);
/*
* FIXME: here is where we should implement a strong form of
* blkdeactivate, and if it completes successfully, automatically call
* do_drop() afterward. (The drop step may not always be necessary
* if the lvm commands run while shutting things down release all the
* leases.)
*
* run_strong_blkdeactivate();
* do_drop();
*/
return rv;
}
static int do_drop(void)
@@ -799,7 +555,7 @@ static int do_drop(void)
int result;
int rv;
log_sys_warn("Dropping locks for VG %s.", arg_vg_name);
syslog(LOG_WARNING, "Dropping locks for VG %s.", arg_vg_name);
/*
* Check for misuse by looking for any active LVs in the VG
@@ -827,84 +583,6 @@ static int do_drop(void)
return rv;
}
static int do_kill(void)
{
char kill_cmd[PATH_MAX] = { 0 };
daemon_reply reply;
int no_kill_command = 0;
int result;
int rv;
log_sys_emerg("lvmlockd lost access to locks in VG %s.", arg_vg_name);
rv = _get_kill_command(kill_cmd);
if (rv < 0) {
log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name);
log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
no_kill_command = 1;
}
/*
* It may not be strictly necessary to notify lvmlockd of the kill, but
* lvmlockd can use this information to avoid attempting any new lock
* requests in the VG (which would fail anyway), and can return an
* error indicating that the VG has been killed.
*/
_lvmlockd = lvmlockd_open(NULL);
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
log_error("Cannot connect to lvmlockd for kill_vg.");
goto run;
}
reply = _lvmlockd_send("kill_vg",
"cmd = %s", "lvmlockctl",
"pid = " FMTd64, (int64_t) getpid(),
"vg_name = %s", arg_vg_name,
NULL);
if (!_lvmlockd_result(reply, &result))
log_error("lvmlockd result %d kill_vg", result);
daemon_reply_destroy(reply);
lvmlockd_close(_lvmlockd);
run:
if (no_kill_command)
return 0;
rv = _run_kill_command(kill_cmd);
if (rv < 0) {
log_sys_emerg("Failed to run VG %s kill command %s", arg_vg_name, kill_cmd);
log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name);
log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
return -1;
}
log_sys_warn("Successful VG %s kill command %s", arg_vg_name, kill_cmd);
/*
* If kill command was successfully, call do_drop(). (The drop step
* may not always be necessary if the lvm commands run while shutting
* things down release all the leases.)
*/
rv = 0;
_lvmlockd = lvmlockd_open(NULL);
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
log_sys_emerg("Failed to connect to lvmlockd to drop locks in VG %s.", arg_vg_name);
return -1;
}
reply = _lvmlockd_send("drop_vg",
"cmd = %s", "lvmlockctl",
"pid = " FMTd64, (int64_t) getpid(),
"vg_name = %s", arg_vg_name,
NULL);
if (!_lvmlockd_result(reply, &result)) {
log_sys_emerg("Failed to drop locks in VG %s", arg_vg_name);
rv = result;
}
daemon_reply_destroy(reply);
lvmlockd_close(_lvmlockd);
return rv;
}
static void print_usage(void)
{
printf("lvmlockctl options\n");
@@ -922,7 +600,7 @@ static void print_usage(void)
printf("--force | -f 0|1>\n");
printf(" Force option for other commands.\n");
printf("--kill | -k <vgname>\n");
printf(" Kill access to the VG locks are lost (see lvmlockctl_kill_command).\n");
printf(" Kill access to the VG when sanlock cannot renew lease.\n");
printf("--drop | -r <vgname>\n");
printf(" Clear locks for the VG when it is unused after kill (-k).\n");
printf("--gl-enable | -E <vgname>\n");
@@ -931,8 +609,6 @@ static void print_usage(void)
printf(" Tell lvmlockd to disable the global lock in a sanlock VG.\n");
printf("--stop-lockspaces | -S\n");
printf(" Stop all lockspaces.\n");
printf("--stderr | -e\n");
printf(" Send kill and drop messages to stderr instead of syslog\n");
}
static int read_options(int argc, char *argv[])
@@ -952,7 +628,6 @@ static int read_options(int argc, char *argv[])
{"gl-enable", required_argument, 0, 'E' },
{"gl-disable", required_argument, 0, 'D' },
{"stop-lockspaces", no_argument, 0, 'S' },
{"stderr", no_argument, 0, 'e' },
{0, 0, 0, 0 }
};
@@ -962,7 +637,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:S", long_options, &option_index);
if (c == -1)
break;
@@ -988,30 +663,23 @@ static int read_options(int argc, char *argv[])
break;
case 'k':
kill_vg = 1;
free(arg_vg_name);
arg_vg_name = strdup(optarg);
break;
case 'r':
drop_vg = 1;
free(arg_vg_name);
arg_vg_name = strdup(optarg);
break;
case 'E':
gl_enable = 1;
free(arg_vg_name);
arg_vg_name = strdup(optarg);
break;
case 'D':
gl_disable = 1;
free(arg_vg_name);
arg_vg_name = strdup(optarg);
break;
case 'S':
stop_lockspaces = 1;
break;
case 'e':
use_stderr = 1;
break;
default:
print_usage();
exit(1);
@@ -1030,12 +698,8 @@ int main(int argc, char **argv)
if (rv < 0)
return rv;
/* do_kill handles lvmlockd connections itself */
if (kill_vg)
return do_kill();
_lvmlockd = lvmlockd_open(NULL);
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
log_error("Cannot connect to lvmlockd.");
return -1;
@@ -1056,6 +720,11 @@ int main(int argc, char **argv)
goto out;
}
if (kill_vg) {
rv = do_kill();
goto out;
}
if (drop_vg) {
rv = do_drop();
goto out;

View File

@@ -23,9 +23,9 @@ static inline daemon_handle lvmlockd_open(const char *sock)
daemon_info lvmlockd_info = {
.path = "lvmlockd",
.socket = sock ?: LVMLOCKD_SOCKET,
.autostart = 0,
.protocol = "lvmlockd",
.protocol_version = 1,
.autostart = 0
};
return daemon_open(lvmlockd_info);
@@ -33,7 +33,7 @@ static inline daemon_handle lvmlockd_open(const char *sock)
static inline void lvmlockd_close(daemon_handle h)
{
daemon_close(h);
return daemon_close(h);
}
/*

View File

@@ -421,56 +421,6 @@ struct lockspace *alloc_lockspace(void)
return ls;
}
static char **alloc_pvs_path(struct pvs *pvs, int num)
{
if (!num)
return NULL;
pvs->path = malloc(sizeof(char *) * num);
if (!pvs->path)
return NULL;
memset(pvs->path, 0x0, sizeof(char *) * num);
return pvs->path;
}
static void free_pvs_path(struct pvs *pvs)
{
int i;
for (i = 0; i < pvs->num; i++)
free((char *)pvs->path[i]);
free(pvs->path);
pvs->path = NULL;
}
static char **alloc_and_copy_pvs_path(struct pvs *dst, struct pvs *src)
{
int i;
if (!alloc_pvs_path(dst, src->num))
return NULL;
dst->num = 0;
for (i = 0; i < src->num; i++) {
if (!src->path[i] || !strcmp(src->path[i], "none"))
continue;
dst->path[dst->num] = strdup(src->path[i]);
if (!dst->path[dst->num]) {
log_error("out of memory for copying pvs path");
goto failed;
}
dst->num++;
}
return dst->path;
failed:
free_pvs_path(dst);
return NULL;
}
static struct action *alloc_action(void)
{
struct action *act;
@@ -556,11 +506,10 @@ static struct lock *alloc_lock(void)
static void free_action(struct action *act)
{
free(act->path);
act->path = NULL;
free_pvs_path(&act->pvs);
if (act->path) {
free(act->path);
act->path = NULL;
}
pthread_mutex_lock(&unused_struct_mutex);
if (unused_action_count >= MAX_UNUSED_ACTION) {
free(act);
@@ -615,12 +564,9 @@ static int setup_structs(void)
struct lock *lk;
int data_san = lm_data_size_sanlock();
int data_dlm = lm_data_size_dlm();
int data_idm = lm_data_size_idm();
int i;
resource_lm_data_size = data_san > data_dlm ? data_san : data_dlm;
resource_lm_data_size = resource_lm_data_size > data_idm ?
resource_lm_data_size : data_idm;
pthread_mutex_init(&unused_struct_mutex, NULL);
INIT_LIST_HEAD(&unused_action);
@@ -737,8 +683,6 @@ static const char *lm_str(int x)
return "dlm";
case LD_LM_SANLOCK:
return "sanlock";
case LD_LM_IDM:
return "idm";
default:
return "lm_unknown";
}
@@ -919,7 +863,7 @@ static void write_adopt_file(void)
pthread_mutex_unlock(&lockspaces_mutex);
fflush(fp);
(void) fclose(fp);
fclose(fp);
}
static int read_adopt_file(struct list_head *vg_lockd)
@@ -928,7 +872,7 @@ static int read_adopt_file(struct list_head *vg_lockd)
char vg_uuid[72];
char lm_type_str[16];
char mode[8];
struct lockspace *ls = NULL, *ls2;
struct lockspace *ls, *ls2;
struct resource *r;
FILE *fp;
@@ -943,8 +887,8 @@ static int read_adopt_file(struct list_head *vg_lockd)
continue;
else if (!strncmp(adopt_line, "lvmlockd", 8)) {
unsigned int v_major = 0, v_minor = 0;
if ((sscanf(adopt_line, "lvmlockd adopt_version %u.%u", &v_major, &v_minor) != 2) ||
(v_major != ADOPT_VERSION_MAJOR))
sscanf(adopt_line, "lvmlockd adopt_version %u.%u", &v_major, &v_minor);
if (v_major != ADOPT_VERSION_MAJOR)
goto fail;
} else if (!strncmp(adopt_line, "VG:", 3)) {
@@ -952,20 +896,16 @@ static int read_adopt_file(struct list_head *vg_lockd)
goto fail;
memset(vg_uuid, 0, sizeof(vg_uuid));
memset(lm_type_str, 0, sizeof(lm_type_str));
if (sscanf(adopt_line, "VG: %63s %64s %15s %64s",
if (sscanf(adopt_line, "VG: %63s %64s %16s %64s",
vg_uuid, ls->vg_name, lm_type_str, ls->vg_args) != 4) {
free(ls);
goto fail;
}
memcpy(ls->vg_uuid, vg_uuid, 64);
if ((ls->lm_type = str_to_lm(lm_type_str)) < 0) {
free(ls);
if ((ls->lm_type = str_to_lm(lm_type_str)) < 0)
goto fail;
}
list_add(&ls->list, vg_lockd);
@@ -976,18 +916,14 @@ static int read_adopt_file(struct list_head *vg_lockd)
r->type = LD_RT_LV;
memset(vg_uuid, 0, sizeof(vg_uuid));
memset(mode, 0, sizeof(mode));
if (sscanf(adopt_line, "LV: %64s %64s %s %7s %u",
if (sscanf(adopt_line, "LV: %64s %64s %s %8s %u",
vg_uuid, r->name, r->lv_args, mode, &r->version) != 5) {
free_resource(r);
goto fail;
}
if ((r->adopt_mode = str_to_mode(mode)) == LD_LK_IV) {
free_resource(r);
if ((r->adopt_mode = str_to_mode(mode)) == LD_LK_IV)
goto fail;
}
if (ls && !memcmp(ls->vg_uuid, vg_uuid, 64)) {
list_add(&r->list, &ls->resources);
@@ -1004,17 +940,16 @@ static int read_adopt_file(struct list_head *vg_lockd)
if (r) {
log_error("No lockspace found for resource %s vg_uuid %s", r->name, vg_uuid);
free_resource(r);
goto fail;
}
}
}
(void) fclose(fp);
fclose(fp);
return 0;
fail:
(void) fclose(fp);
fclose(fp);
return -1;
}
@@ -1031,8 +966,6 @@ static int lm_prepare_lockspace(struct lockspace *ls, struct action *act)
rv = lm_prepare_lockspace_dlm(ls);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_prepare_lockspace_sanlock(ls);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_prepare_lockspace_idm(ls);
else
return -1;
@@ -1049,8 +982,6 @@ static int lm_add_lockspace(struct lockspace *ls, struct action *act, int adopt)
rv = lm_add_lockspace_dlm(ls, adopt);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_add_lockspace_sanlock(ls, adopt);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_add_lockspace_idm(ls, adopt);
else
return -1;
@@ -1067,8 +998,6 @@ static int lm_rem_lockspace(struct lockspace *ls, struct action *act, int free_v
rv = lm_rem_lockspace_dlm(ls, free_vg);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_rem_lockspace_sanlock(ls, free_vg);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_rem_lockspace_idm(ls, free_vg);
else
return -1;
@@ -1086,9 +1015,6 @@ static int lm_lock(struct lockspace *ls, struct resource *r, int mode, struct ac
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);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_lock_idm(ls, r, mode, vb_out, act->lv_uuid,
&act->pvs, adopt);
else
return -1;
@@ -1106,8 +1032,6 @@ static int lm_convert(struct lockspace *ls, struct resource *r,
rv = lm_convert_dlm(ls, r, mode, r_version);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_convert_sanlock(ls, r, mode, r_version);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_convert_idm(ls, r, mode, r_version);
else
return -1;
@@ -1125,8 +1049,6 @@ static int lm_unlock(struct lockspace *ls, struct resource *r, struct action *ac
rv = lm_unlock_dlm(ls, r, r_version, lmu_flags);
else if (ls->lm_type == LD_LM_SANLOCK)
rv = lm_unlock_sanlock(ls, r, r_version, lmu_flags);
else if (ls->lm_type == LD_LM_IDM)
rv = lm_unlock_idm(ls, r, r_version, lmu_flags);
else
return -1;
@@ -1141,8 +1063,6 @@ static int lm_hosts(struct lockspace *ls, int notify)
return lm_hosts_dlm(ls, notify);
else if (ls->lm_type == LD_LM_SANLOCK)
return lm_hosts_sanlock(ls, notify);
else if (ls->lm_type == LD_LM_IDM)
return lm_hosts_idm(ls, notify);
return -1;
}
@@ -1152,8 +1072,6 @@ static void lm_rem_resource(struct lockspace *ls, struct resource *r)
lm_rem_resource_dlm(ls, r);
else if (ls->lm_type == LD_LM_SANLOCK)
lm_rem_resource_sanlock(ls, r);
else if (ls->lm_type == LD_LM_IDM)
lm_rem_resource_idm(ls, r);
}
static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *sector_size, int *align_size)
@@ -1162,8 +1080,6 @@ static int lm_find_free_lock(struct lockspace *ls, uint64_t *free_offset, int *s
return 0;
else if (ls->lm_type == LD_LM_SANLOCK)
return lm_find_free_lock_sanlock(ls, free_offset, sector_size, align_size);
else if (ls->lm_type == LD_LM_IDM)
return 0;
return -1;
}
@@ -1772,8 +1688,8 @@ static int res_update(struct lockspace *ls, struct resource *r,
}
/*
* For DLM and IDM locking scheme, there is nothing to deallocate when freeing a
* LV, the LV will simply be unlocked by rem_resource.
* There is nothing to deallocate when freeing a dlm LV, the LV
* will simply be unlocked by rem_resource.
*/
static int free_lv(struct lockspace *ls, struct resource *r)
@@ -1782,8 +1698,6 @@ static int free_lv(struct lockspace *ls, struct resource *r)
return lm_free_lv_sanlock(ls, r);
else if (ls->lm_type == LD_LM_DLM)
return 0;
else if (ls->lm_type == LD_LM_IDM)
return 0;
else
return -EINVAL;
}
@@ -1884,7 +1798,9 @@ static void res_process(struct lockspace *ls, struct resource *r,
act->result = -EINVAL;
list_del(&act->list);
add_client_result(act);
} else if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN) {
}
if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN) {
rv = res_unlock(ls, r, act);
if (rv == -ENOENT && (act->flags & LD_AF_UNLOCK_CANCEL))
@@ -2764,7 +2680,7 @@ out_rem:
log_debug("S %s clearing locks", ls->name);
(void) clear_locks(ls, free_vg, drop_vg);
rv = clear_locks(ls, free_vg, drop_vg);
/*
* Tell any other hosts in the lockspace to leave it
@@ -2842,8 +2758,6 @@ out_act:
ls->drop_vg = drop_vg;
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
global_dlm_lockspace_exists = 0;
if (ls->lm_type == LD_LM_IDM && !strcmp(ls->name, gl_lsname_idm))
global_idm_lockspace_exists = 0;
/*
* Avoid a name collision of the same lockspace is added again before
@@ -2935,8 +2849,6 @@ static void gl_ls_name(char *ls_name)
memcpy(ls_name, gl_lsname_dlm, MAX_NAME);
else if (gl_use_sanlock)
memcpy(ls_name, gl_lsname_sanlock, MAX_NAME);
else if (gl_use_idm)
memcpy(ls_name, gl_lsname_idm, MAX_NAME);
else
memset(ls_name, 0, MAX_NAME);
}
@@ -2965,22 +2877,10 @@ static int add_lockspace_thread(const char *ls_name,
strncpy(ls->name, ls_name, MAX_NAME);
ls->lm_type = lm_type;
if (act) {
if (act)
ls->start_client_id = act->client_id;
/*
* Copy PV list to lockspact structure, so this is
* used for VG locking for idm scheme.
*/
if (lm_type == LD_LM_IDM &&
!alloc_and_copy_pvs_path(&ls->pvs, &act->pvs)) {
free(ls);
return -ENOMEM;
}
}
if (vg_uuid)
/* coverity[buffer_size_warning] */
strncpy(ls->vg_uuid, vg_uuid, 64);
if (vg_name)
@@ -3006,18 +2906,6 @@ static int add_lockspace_thread(const char *ls_name,
pthread_mutex_lock(&lockspaces_mutex);
ls2 = find_lockspace_name(ls->name);
if (ls2) {
/*
* If find an existed lockspace, we need to update the PV list
* based on the latest information, and release for the old
* PV list in case it keeps stale information.
*/
free_pvs_path(&ls2->pvs);
if (lm_type == LD_LM_IDM &&
!alloc_and_copy_pvs_path(&ls2->pvs, &ls->pvs)) {
log_debug("add_lockspace_thread %s fails to allocate pvs", ls->name);
rv = -ENOMEM;
}
if (ls2->thread_stop) {
log_debug("add_lockspace_thread %s exists and stopping", ls->name);
rv = -EAGAIN;
@@ -3030,7 +2918,6 @@ static int add_lockspace_thread(const char *ls_name,
}
pthread_mutex_unlock(&lockspaces_mutex);
free_resource(r);
free_pvs_path(&ls->pvs);
free(ls);
return rv;
}
@@ -3044,8 +2931,6 @@ static int add_lockspace_thread(const char *ls_name,
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
global_dlm_lockspace_exists = 1;
if (ls->lm_type == LD_LM_IDM && !strcmp(ls->name, gl_lsname_idm))
global_idm_lockspace_exists = 1;
list_add_tail(&ls->list, &lockspaces);
pthread_mutex_unlock(&lockspaces_mutex);
@@ -3056,7 +2941,6 @@ static int add_lockspace_thread(const char *ls_name,
list_del(&ls->list);
pthread_mutex_unlock(&lockspaces_mutex);
free_resource(r);
free_pvs_path(&ls->pvs);
free(ls);
return rv;
}
@@ -3065,15 +2949,16 @@ static int add_lockspace_thread(const char *ls_name,
}
/*
* There is no variant for sanlock because, with sanlock, the global
* lockspace is one of the vg lockspaces.
* There is no add_sanlock_global_lockspace or
* rem_sanlock_global_lockspace because with sanlock,
* the global lockspace is one of the vg lockspaces.
*/
static int add_global_lockspace(char *ls_name, int lm_type,
struct action *act)
static int add_dlm_global_lockspace(struct action *act)
{
int rv;
if (global_dlm_lockspace_exists || global_idm_lockspace_exists)
if (global_dlm_lockspace_exists)
return 0;
/*
@@ -3081,9 +2966,9 @@ static int add_global_lockspace(char *ls_name, int lm_type,
* lock request, insert an internal gl sh lock request?
*/
rv = add_lockspace_thread(ls_name, NULL, NULL, lm_type, NULL, act);
rv = add_lockspace_thread(gl_lsname_dlm, NULL, NULL, LD_LM_DLM, NULL, act);
if (rv < 0)
log_debug("add_global_lockspace add_lockspace_thread %d", rv);
log_debug("add_dlm_global_lockspace add_lockspace_thread %d", rv);
/*
* EAGAIN may be returned for a short period because
@@ -3096,12 +2981,12 @@ static int add_global_lockspace(char *ls_name, int lm_type,
}
/*
* When DLM or IDM locking scheme is used for global lock, if the global
* lockspace is the only one left, then stop it. This is not used for
* an explicit rem_lockspace action from the client, only for auto
* remove.
* If dlm gl lockspace is the only one left, then stop it.
* This is not used for an explicit rem_lockspace action from
* the client, only for auto remove.
*/
static int rem_global_lockspace(char *ls_name)
static int rem_dlm_global_lockspace(void)
{
struct lockspace *ls, *ls_gl = NULL;
int others = 0;
@@ -3109,7 +2994,7 @@ static int rem_global_lockspace(char *ls_name)
pthread_mutex_lock(&lockspaces_mutex);
list_for_each_entry(ls, &lockspaces, list) {
if (!strcmp(ls->name, ls_name)) {
if (!strcmp(ls->name, gl_lsname_dlm)) {
ls_gl = ls;
continue;
}
@@ -3141,26 +3026,6 @@ out:
return rv;
}
static int add_dlm_global_lockspace(struct action *act)
{
return add_global_lockspace(gl_lsname_dlm, LD_LM_DLM, act);
}
static int rem_dlm_global_lockspace(void)
{
return rem_global_lockspace(gl_lsname_dlm);
}
static int add_idm_global_lockspace(struct action *act)
{
return add_global_lockspace(gl_lsname_idm, LD_LM_IDM, act);
}
static int rem_idm_global_lockspace(void)
{
return rem_global_lockspace(gl_lsname_idm);
}
/*
* When the first dlm lockspace is added for a vg, automatically add a separate
* dlm lockspace for the global lock.
@@ -3186,9 +3051,6 @@ static int add_lockspace(struct action *act)
if (gl_use_dlm) {
rv = add_dlm_global_lockspace(act);
return rv;
} else if (gl_use_idm) {
rv = add_idm_global_lockspace(act);
return rv;
} else {
return -EINVAL;
}
@@ -3197,8 +3059,6 @@ static int add_lockspace(struct action *act)
if (act->rt == LD_RT_VG) {
if (gl_use_dlm)
add_dlm_global_lockspace(NULL);
else if (gl_use_idm)
add_idm_global_lockspace(NULL);
vg_ls_name(act->vg_name, ls_name);
@@ -3266,15 +3126,14 @@ static int rem_lockspace(struct action *act)
pthread_mutex_unlock(&lockspaces_mutex);
/*
* For DLM and IDM locking scheme, the global lockspace was
* automatically added when the first vg lockspace was added,
* now reverse that by automatically removing the dlm global
* lockspace when the last vg lockspace is removed.
* The dlm global lockspace was automatically added when
* the first dlm vg lockspace was added, now reverse that
* by automatically removing the dlm global lockspace when
* the last dlm vg lockspace is removed.
*/
if (rt == LD_RT_VG && gl_use_dlm)
rem_dlm_global_lockspace();
else if (rt == LD_RT_VG && gl_use_idm)
rem_idm_global_lockspace();
return 0;
}
@@ -3398,7 +3257,6 @@ static int for_each_lockspace(int do_stop, int do_free, int do_force)
if (ls->free_vg) {
/* In future we may need to free ls->actions here */
free_ls_resources(ls);
free_pvs_path(&ls->pvs);
free(ls);
free_count++;
}
@@ -3412,7 +3270,6 @@ static int for_each_lockspace(int do_stop, int do_free, int do_force)
if (!gl_type_static) {
gl_use_dlm = 0;
gl_use_sanlock = 0;
gl_use_idm = 0;
}
}
pthread_mutex_unlock(&lockspaces_mutex);
@@ -3488,9 +3345,6 @@ static int work_init_vg(struct action *act)
rv = lm_init_vg_sanlock(ls_name, act->vg_name, act->flags, act->vg_args);
else if (act->lm_type == LD_LM_DLM)
rv = lm_init_vg_dlm(ls_name, act->vg_name, act->flags, act->vg_args);
else if (act->lm_type == LD_LM_IDM)
/* Non't do anything for IDM when initialize VG */
rv = 0;
else
rv = -EINVAL;
@@ -3594,8 +3448,6 @@ static int work_init_lv(struct action *act)
} else if (act->lm_type == LD_LM_DLM) {
return 0;
} else if (act->lm_type == LD_LM_IDM) {
return 0;
} else {
log_error("init_lv ls_name %s bad lm_type %d", ls_name, act->lm_type);
return -EINVAL;
@@ -3659,29 +3511,20 @@ static void *worker_thread_main(void *arg_in)
if (act->op == LD_OP_RUNNING_LM) {
int run_sanlock = lm_is_running_sanlock();
int run_dlm = lm_is_running_dlm();
int run_idm = lm_is_running_idm();
if (daemon_test) {
run_sanlock = gl_use_sanlock;
run_dlm = gl_use_dlm;
run_idm = gl_use_idm;
}
/*
* It's not possible to enable multiple locking schemes
* for global lock, otherwise, it must be conflict and
* reports it!
*/
if ((run_sanlock + run_dlm + run_idm) >= 2)
if (run_sanlock && run_dlm)
act->result = -EXFULL;
else if (!run_sanlock && !run_dlm && !run_idm)
else if (!run_sanlock && !run_dlm)
act->result = -ENOLCK;
else if (run_sanlock)
act->result = LD_LM_SANLOCK;
else if (run_dlm)
act->result = LD_LM_DLM;
else if (run_idm)
act->result = LD_LM_IDM;
add_client_result(act);
} else if ((act->op == LD_OP_LOCK) && (act->flags & LD_AF_SEARCH_LS)) {
@@ -3969,9 +3812,6 @@ static int client_send_result(struct client *cl, struct action *act)
} else if (gl_use_dlm) {
if (!gl_lsname_dlm[0])
strcat(result_flags, "NO_GL_LS,");
} else if (gl_use_idm) {
if (!gl_lsname_idm[0])
strcat(result_flags, "NO_GL_LS,");
} else {
int found_lm = 0;
@@ -3979,8 +3819,6 @@ static int client_send_result(struct client *cl, struct action *act)
found_lm++;
if (lm_support_sanlock() && lm_is_running_sanlock())
found_lm++;
if (lm_support_idm() && lm_is_running_idm())
found_lm++;
if (!found_lm)
strcat(result_flags, "NO_GL_LS,NO_LM");
@@ -4156,13 +3994,11 @@ static int add_lock_action(struct action *act)
if (gl_use_sanlock && (act->op == LD_OP_ENABLE || act->op == LD_OP_DISABLE)) {
vg_ls_name(act->vg_name, ls_name);
} else {
if (!gl_use_dlm && !gl_use_sanlock && !gl_use_idm) {
if (!gl_use_dlm && !gl_use_sanlock) {
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);
}
@@ -4210,17 +4046,6 @@ static int add_lock_action(struct action *act)
add_dlm_global_lockspace(NULL);
goto retry;
} else if (act->op == LD_OP_LOCK && act->rt == LD_RT_GL && act->mode != LD_LK_UN && gl_use_idm) {
/*
* Automatically start the idm global lockspace when
* a command tries to acquire the global lock.
*/
log_debug("lockspace \"%s\" not found for idm gl, adding...", ls_name);
act->flags |= LD_AF_SEARCH_LS;
act->flags |= LD_AF_WAIT_STARTING;
add_idm_global_lockspace(NULL);
goto retry;
} else if (act->op == LD_OP_LOCK && act->mode == LD_LK_UN) {
log_debug("lockspace \"%s\" not found for unlock ignored", ls_name);
return -ENOLS;
@@ -4441,8 +4266,6 @@ static int str_to_lm(const char *str)
return LD_LM_SANLOCK;
if (!strcmp(str, "dlm"))
return LD_LM_DLM;
if (!strcmp(str, "idm"))
return LD_LM_IDM;
return -2;
}
@@ -4778,14 +4601,12 @@ static void client_recv_action(struct client *cl)
const char *vg_sysid;
const char *path;
const char *str;
struct pvs pvs;
char buf[17]; /* "path[%d]\0", %d outputs signed integer so max to 10 bytes */
int64_t val;
uint32_t opts = 0;
int result = 0;
int cl_pid;
int op, rt, lm, mode;
int rv, i;
int rv;
buffer_init(&req.buffer);
@@ -4874,13 +4695,11 @@ static void client_recv_action(struct client *cl)
if (!cl->name[0] && cl_name)
strncpy(cl->name, cl_name, MAX_NAME);
if (!gl_use_dlm && !gl_use_sanlock && !gl_use_idm && (lm > 0)) {
if (!gl_use_dlm && !gl_use_sanlock && (lm > 0)) {
if (lm == LD_LM_DLM && lm_support_dlm())
gl_use_dlm = 1;
else if (lm == LD_LM_SANLOCK && lm_support_sanlock())
gl_use_sanlock = 1;
else if (lm == LD_LM_IDM && lm_support_idm())
gl_use_idm = 1;
log_debug("set gl_use_%s", lm_str(lm));
}
@@ -4937,40 +4756,6 @@ static void client_recv_action(struct client *cl)
if (val)
act->host_id = val;
/* Create PV list for idm */
if (lm == LD_LM_IDM) {
memset(&pvs, 0x0, sizeof(pvs));
pvs.num = daemon_request_int(req, "path_num", 0);
log_error("pvs_num = %d", pvs.num);
if (!pvs.num)
goto skip_pvs_path;
/* Receive the pv list which is transferred from LVM command */
if (!alloc_pvs_path(&pvs, pvs.num)) {
log_error("fail to allocate pvs path");
rv = -ENOMEM;
goto out;
}
for (i = 0; i < pvs.num; i++) {
snprintf(buf, sizeof(buf), "path[%d]", i);
pvs.path[i] = (char *)daemon_request_str(req, buf, NULL);
}
if (!alloc_and_copy_pvs_path(&act->pvs, &pvs)) {
log_error("fail to allocate pvs path");
rv = -ENOMEM;
goto out;
}
if (pvs.path)
free(pvs.path);
pvs.path = NULL;
}
skip_pvs_path:
act->max_retries = daemon_request_int(req, "max_retries", DEFAULT_MAX_RETRIES);
dm_config_destroy(req.cft);
@@ -4992,12 +4777,6 @@ skip_pvs_path:
goto out;
}
if (lm == LD_LM_IDM && !lm_support_idm()) {
log_debug("idm not supported");
rv = -EPROTONOSUPPORT;
goto out;
}
if (act->op == LD_OP_LOCK && act->mode != LD_LK_UN)
cl->lock_ops = 1;
@@ -5187,7 +4966,7 @@ static void *client_thread_main(void *arg_in)
}
out:
if (adopt_opt && lock_acquire_written)
(void) unlink(adopt_file);
unlink(adopt_file);
return NULL;
}
@@ -5596,7 +5375,6 @@ static void adopt_locks(void)
}
list_del(&ls->list);
free_pvs_path(&ls->pvs);
free(ls);
}
@@ -5637,7 +5415,6 @@ static void adopt_locks(void)
if (rv < 0) {
log_error("Failed to create lockspace thread for VG %s", ls->vg_name);
list_del(&ls->list);
free_pvs_path(&ls->pvs);
free(ls);
free_action(act);
count_start_fail++;
@@ -5961,13 +5738,13 @@ static void adopt_locks(void)
if (count_start_fail || count_adopt_fail)
goto fail;
(void) unlink(adopt_file);
unlink(adopt_file);
write_adopt_file();
log_debug("adopt_locks done");
return;
fail:
(void) unlink(adopt_file);
unlink(adopt_file);
log_error("adopt_locks failed, reset host");
}
@@ -6080,7 +5857,6 @@ static int main_loop(daemon_state *ds_arg)
}
strcpy(gl_lsname_dlm, S_NAME_GL_DLM);
strcpy(gl_lsname_idm, S_NAME_GL_IDM);
INIT_LIST_HEAD(&lockspaces);
pthread_mutex_init(&lockspaces_mutex, NULL);
@@ -6262,16 +6038,15 @@ static void usage(char *prog, FILE *file)
int main(int argc, char *argv[])
{
daemon_state ds = {
.name = "lvmlockd",
.daemon_main = main_loop,
.daemon_init = NULL,
.daemon_fini = NULL,
.pidfile = getenv("LVM_LVMLOCKD_PIDFILE"),
.socket_path = getenv("LVM_LVMLOCKD_SOCKET"),
.protocol = lvmlockd_protocol,
.protocol_version = lvmlockd_protocol_version,
.daemon_init = NULL,
.daemon_fini = NULL,
.daemon_main = main_loop,
.name = "lvmlockd",
};
daemon_host_id_file = NULL;
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
@@ -6305,7 +6080,6 @@ int main(int argc, char *argv[])
case '0':
break;
case 128:
free((void *) adopt_file);
adopt_file = strdup(optarg);
break;
case 'h':
@@ -6325,11 +6099,9 @@ int main(int argc, char *argv[])
daemon_debug = 1;
break;
case 'p':
free((void*)ds.pidfile);
ds.pidfile = strdup(optarg);
break;
case 's':
free((void*)ds.socket_path);
ds.socket_path = strdup(optarg);
break;
case 'g':
@@ -6338,8 +6110,6 @@ int main(int argc, char *argv[])
gl_use_dlm = 1;
else if (lm == LD_LM_SANLOCK && lm_support_sanlock())
gl_use_sanlock = 1;
else if (lm == LD_LM_IDM && lm_support_idm())
gl_use_idm = 1;
else {
fprintf(stderr, "invalid gl-type option\n");
exit(EXIT_FAILURE);
@@ -6349,7 +6119,6 @@ int main(int argc, char *argv[])
daemon_host_id = atoi(optarg);
break;
case 'F':
free((void*)daemon_host_id_file);
daemon_host_id_file = strdup(optarg);
break;
case 'o':

View File

@@ -119,7 +119,6 @@ static int read_cluster_name(char *clustername)
log_error(close_error_msg, fd);
return rv;
}
clustername[rv] = 0;
n = strstr(clustername, "\n");
if (n)
@@ -328,7 +327,8 @@ int lm_rem_resource_dlm(struct lockspace *ls, struct resource *r)
log_error("S %s R %s rem_resource_dlm unlock error %d", ls->name, r->name, rv);
}
out:
free(rdd->vb);
if (rdd->vb)
free(rdd->vb);
memset(rdd, 0, sizeof(struct rd_dlm));
r->lm_init = 0;
@@ -791,18 +791,17 @@ int lm_is_running_dlm(void)
int lm_refresh_lv_start_dlm(struct action *act)
{
char path[PATH_MAX] = { 0 };
char path[PATH_MAX];
char command[DLMC_RUN_COMMAND_LEN];
char run_uuid[DLMC_RUN_UUID_LEN];
char *p, *vgname, *lvname;
int rv;
/* split /dev/vgname/lvname into vgname and lvname strings */
strncpy(path, act->path, PATH_MAX-1);
strncpy(path, act->path, strlen(act->path));
/* skip past dev */
if (!(p = strchr(path + 1, '/')))
return -EINVAL;
p = strchr(path + 1, '/');
/* skip past slashes */
while (*p == '/')

View File

@@ -1,837 +0,0 @@
/*
* Copyright (C) 2020-2021 Seagate Ltd.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*/
#define _XOPEN_SOURCE 500 /* pthread */
#define _ISOC99_SOURCE
#include "tools/tool.h"
#include "daemon-server.h"
#include "lib/mm/xlate.h"
#include "lvmlockd-internal.h"
#include "daemons/lvmlockd/lvmlockd-client.h"
#include "ilm.h"
#include <blkid/blkid.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <poll.h>
#include <regex.h>
#include <stddef.h>
#include <syslog.h>
#include <sys/sysmacros.h>
#include <time.h>
#define IDM_TIMEOUT 60000 /* unit: millisecond, 60 seconds */
/*
* Each lockspace thread has its own In-Drive Mutex (IDM) lock manager's
* connection. After established socket connection, the lockspace has
* been created in IDM lock manager and afterwards use the socket file
* descriptor to send any requests for lock related operations.
*/
struct lm_idm {
int sock; /* IDM lock manager connection */
};
struct rd_idm {
struct idm_lock_id id;
struct idm_lock_op op;
uint64_t vb_timestamp;
struct val_blk *vb;
};
int lm_data_size_idm(void)
{
return sizeof(struct rd_idm);
}
static uint64_t read_utc_us(void)
{
struct timespec cur_time;
clock_gettime(CLOCK_REALTIME, &cur_time);
/*
* Convert to microseconds unit. IDM reserves the MSB in 8 bytes
* and the low 56 bits are used for timestamp; 56 bits can support
* calendar year to 2284, so it has 260 years for overflow. Thus it
* is quite safe for overflow issue when wrote this code.
*/
return cur_time.tv_sec * 1000000 + cur_time.tv_nsec / 1000;
}
static int uuid_read_format(char *uuid_str, const char *buffer)
{
int out = 0;
/* just strip out any dashes */
while (*buffer) {
if (*buffer == '-') {
buffer++;
continue;
}
if (out >= 32) {
log_error("Too many characters to be uuid.");
return -1;
}
uuid_str[out++] = *buffer;
buffer++;
}
if (out != 32) {
log_error("Couldn't read uuid: incorrect number of "
"characters.");
return -1;
}
return 0;
}
#define SYSFS_ROOT "/sys"
#define BUS_SCSI_DEVS "/bus/scsi/devices"
static struct idm_lock_op glb_lock_op;
static void lm_idm_free_dir_list(struct dirent **dir_list, int dir_num)
{
int i;
for (i = 0; i < dir_num; ++i)
free(dir_list[i]);
free(dir_list);
}
static int lm_idm_scsi_directory_select(const struct dirent *s)
{
regex_t regex;
int ret;
/* Only select directory with the format x:x:x:x */
ret = regcomp(&regex, "^[0-9]+:[0-9]+:[0-9]+:[0-9]+$", REG_EXTENDED);
if (ret)
return 0;
ret = regexec(&regex, s->d_name, 0, NULL, 0);
if (!ret) {
regfree(&regex);
return 1;
}
regfree(&regex);
return 0;
}
static int lm_idm_scsi_find_block_dirctory(const char *block_path)
{
struct stat stats;
if ((stat(block_path, &stats) >= 0) && S_ISDIR(stats.st_mode))
return 0;
return -1;
}
static int lm_idm_scsi_block_node_select(const struct dirent *s)
{
if (DT_LNK != s->d_type && DT_DIR != s->d_type)
return 0;
if (DT_DIR == s->d_type) {
/* Skip this directory: '.' and parent: '..' */
if (!strcmp(s->d_name, ".") || !strcmp(s->d_name, ".."))
return 0;
}
return 1;
}
static int lm_idm_scsi_find_block_node(const char *blk_path, char **blk_dev)
{
struct dirent **dir_list;
int dir_num;
dir_num = scandir(blk_path, &dir_list, lm_idm_scsi_block_node_select, NULL);
if (dir_num < 0) {
log_error("Cannot find valid directory entry in %s", blk_path);
return -1;
}
/*
* Should have only one block name under the path, if the dir_num is
* not 1 (e.g. 0 or any number bigger than 1), it must be wrong and
* should never happen.
*/
if (dir_num == 1)
*blk_dev = strdup(dir_list[0]->d_name);
else
*blk_dev = NULL;
lm_idm_free_dir_list(dir_list, dir_num);
if (!*blk_dev)
return -1;
return dir_num;
}
static int lm_idm_scsi_search_propeller_partition(char *dev)
{
int i, nparts;
blkid_probe pr;
blkid_partlist ls;
int found = -1;
pr = blkid_new_probe_from_filename(dev);
if (!pr) {
log_error("%s: failed to create a new libblkid probe", dev);
return -1;
}
/* Binary interface */
ls = blkid_probe_get_partitions(pr);
if (!ls) {
log_error("%s: failed to read partitions", dev);
return -1;
}
/* List partitions */
nparts = blkid_partlist_numof_partitions(ls);
if (!nparts)
goto done;
for (i = 0; i < nparts; i++) {
const char *p;
blkid_partition par = blkid_partlist_get_partition(ls, i);
p = blkid_partition_get_name(par);
if (p) {
log_debug("partition name='%s'", p);
if (!strcmp(p, "propeller"))
found = blkid_partition_get_partno(par);
}
if (found >= 0)
break;
}
done:
blkid_free_probe(pr);
return found;
}
static char *lm_idm_scsi_get_block_device_node(const char *scsi_path)
{
char *blk_path = NULL;
char *blk_dev = NULL;
char *dev_node = NULL;
int ret;
/*
* Locate the "block" directory, such like:
* /sys/bus/scsi/devices/1:0:0:0/block
*/
ret = asprintf(&blk_path, "%s/%s", scsi_path, "block");
if (ret < 0) {
log_error("Fail to allocate block path for %s", scsi_path);
goto fail;
}
ret = lm_idm_scsi_find_block_dirctory(blk_path);
if (ret < 0) {
log_error("Fail to find block path %s", blk_path);
goto fail;
}
/*
* Locate the block device name, such like:
* /sys/bus/scsi/devices/1:0:0:0/block/sdb
*
* After return from this function and if it makes success,
* the global variable "blk_dev" points to the block device
* name, in this example it points to string "sdb".
*/
ret = lm_idm_scsi_find_block_node(blk_path, &blk_dev);
if (ret < 0) {
log_error("Fail to find block node");
goto fail;
}
ret = asprintf(&dev_node, "/dev/%s", blk_dev);
if (ret < 0) {
log_error("Fail to allocate memory for blk node path");
goto fail;
}
ret = lm_idm_scsi_search_propeller_partition(dev_node);
if (ret < 0)
goto fail;
free(blk_path);
free(blk_dev);
return dev_node;
fail:
free(blk_path);
free(blk_dev);
free(dev_node);
return NULL;
}
static int lm_idm_get_gl_lock_pv_list(void)
{
struct dirent **dir_list;
char scsi_bus_path[PATH_MAX];
char *drive_path;
int i, dir_num, ret;
if (glb_lock_op.drive_num)
return 0;
snprintf(scsi_bus_path, sizeof(scsi_bus_path), "%s%s",
SYSFS_ROOT, BUS_SCSI_DEVS);
dir_num = scandir(scsi_bus_path, &dir_list,
lm_idm_scsi_directory_select, NULL);
if (dir_num < 0) { /* scsi mid level may not be loaded */
log_error("Attached devices: none");
return -1;
}
for (i = 0; i < dir_num; i++) {
char *scsi_path;
ret = asprintf(&scsi_path, "%s/%s", scsi_bus_path,
dir_list[i]->d_name);
if (ret < 0) {
log_error("Fail to allocate memory for scsi directory");
goto failed;
}
if (glb_lock_op.drive_num >= ILM_DRIVE_MAX_NUM) {
log_error("Global lock: drive number %d exceeds limitation (%d) ?!",
glb_lock_op.drive_num, ILM_DRIVE_MAX_NUM);
free(scsi_path);
goto failed;
}
drive_path = lm_idm_scsi_get_block_device_node(scsi_path);
if (!drive_path) {
free(scsi_path);
continue;
}
glb_lock_op.drives[glb_lock_op.drive_num] = drive_path;
glb_lock_op.drive_num++;
free(scsi_path);
}
lm_idm_free_dir_list(dir_list, dir_num);
return 0;
failed:
lm_idm_free_dir_list(dir_list, dir_num);
for (i = 0; i < glb_lock_op.drive_num; i++) {
if (glb_lock_op.drives[i]) {
free(glb_lock_op.drives[i]);
glb_lock_op.drives[i] = NULL;
}
}
return -1;
}
static void lm_idm_update_vb_timestamp(uint64_t *vb_timestamp)
{
uint64_t utc_us = read_utc_us();
/*
* It's possible that the multiple nodes have no clock
* synchronization with microsecond prcision and the time
* is going backward. For this case, simply increment the
* existing timestamp and write out to drive.
*/
if (*vb_timestamp >= utc_us)
(*vb_timestamp)++;
else
*vb_timestamp = utc_us;
}
int lm_prepare_lockspace_idm(struct lockspace *ls)
{
struct lm_idm *lm = NULL;
lm = malloc(sizeof(struct lm_idm));
if (!lm) {
log_error("S %s prepare_lockspace_idm fail to allocate lm_idm for %s",
ls->name, ls->vg_name);
return -ENOMEM;
}
memset(lm, 0x0, sizeof(struct lm_idm));
ls->lm_data = lm;
log_debug("S %s prepare_lockspace_idm done", ls->name);
return 0;
}
int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
{
char killpath[IDM_FAILURE_PATH_LEN];
char killargs[IDM_FAILURE_ARGS_LEN];
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
int rv;
if (daemon_test)
return 0;
if (!strcmp(ls->name, S_NAME_GL_IDM)) {
/*
* Prepare the pv list for global lock, if the drive contains
* "propeller" partition, then this drive will be considered
* as a member of pv list.
*/
rv = lm_idm_get_gl_lock_pv_list();
if (rv < 0) {
log_error("S %s add_lockspace_idm fail to get pv list for glb lock",
ls->name);
return -EIO;
} else {
log_error("S %s add_lockspace_idm get pv list for glb lock",
ls->name);
}
}
/*
* Construct the execution path for command "lvmlockctl" by using the
* path to the lvm binary and appending "lockctl".
*/
memset(killpath, 0, sizeof(killpath));
snprintf(killpath, IDM_FAILURE_PATH_LEN, "%slockctl", LVM_PATH);
/* Pass the argument "--kill vg_name" for killpath */
memset(killargs, 0, sizeof(killargs));
snprintf(killargs, IDM_FAILURE_ARGS_LEN, "--kill %s", ls->vg_name);
/* Connect with IDM lock manager per every lockspace. */
rv = ilm_connect(&lmi->sock);
if (rv < 0) {
log_error("S %s add_lockspace_idm fail to connect the lock manager %d",
ls->name, lmi->sock);
lmi->sock = 0;
rv = -EMANAGER;
goto fail;
}
rv = ilm_set_killpath(lmi->sock, killpath, killargs);
if (rv < 0) {
log_error("S %s add_lockspace_idm fail to set kill path %d",
ls->name, rv);
rv = -EMANAGER;
goto fail;
}
log_debug("S %s add_lockspace_idm kill path is: \"%s %s\"",
ls->name, killpath, killargs);
log_debug("S %s add_lockspace_idm done", ls->name);
return 0;
fail:
if (lmi && lmi->sock)
close(lmi->sock);
free(lmi);
return rv;
}
int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
int i, rv = 0;
if (daemon_test)
goto out;
rv = ilm_disconnect(lmi->sock);
if (rv < 0)
log_error("S %s rem_lockspace_idm error %d", ls->name, rv);
/* Release pv list for global lock */
if (!strcmp(ls->name, "lvm_global")) {
for (i = 0; i < glb_lock_op.drive_num; i++) {
if (glb_lock_op.drives[i]) {
free(glb_lock_op.drives[i]);
glb_lock_op.drives[i] = NULL;
}
}
}
out:
free(lmi);
ls->lm_data = NULL;
return rv;
}
static int lm_add_resource_idm(struct lockspace *ls, struct resource *r)
{
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
if (r->type == LD_RT_GL || r->type == LD_RT_VG) {
rdi->vb = zalloc(sizeof(struct val_blk));
if (!rdi->vb)
return -ENOMEM;
}
return 0;
}
int lm_rem_resource_idm(struct lockspace *ls, struct resource *r)
{
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
free(rdi->vb);
memset(rdi, 0, sizeof(struct rd_idm));
r->lm_init = 0;
return 0;
}
static int to_idm_mode(int ld_mode)
{
switch (ld_mode) {
case LD_LK_EX:
return IDM_MODE_EXCLUSIVE;
case LD_LK_SH:
return IDM_MODE_SHAREABLE;
default:
break;
};
return -1;
}
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)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
char **drive_path = NULL;
uint64_t timestamp;
int reset_vb = 0;
int rv, i;
if (!r->lm_init) {
rv = lm_add_resource_idm(ls, r);
if (rv < 0)
return rv;
r->lm_init = 1;
}
rdi->op.mode = to_idm_mode(ld_mode);
if (rv < 0) {
log_error("lock_idm invalid mode %d", ld_mode);
return -EINVAL;
}
log_debug("S %s R %s lock_idm", ls->name, r->name);
if (daemon_test) {
if (rdi->vb) {
vb_out->version = le16_to_cpu(rdi->vb->version);
vb_out->flags = le16_to_cpu(rdi->vb->flags);
vb_out->r_version = le32_to_cpu(rdi->vb->r_version);
}
return 0;
}
rdi->op.timeout = IDM_TIMEOUT;
/*
* Generate the UUID string, for RT_VG, it only needs to generate
* UUID string for VG level, for RT_LV, it needs to generate
* UUID strings for both VG and LV levels. At the end, these IDs
* are used as identifier for IDM in drive firmware.
*/
if (r->type == LD_RT_VG || r->type == LD_RT_LV)
log_debug("S %s R %s VG uuid %s", ls->name, r->name, ls->vg_uuid);
if (r->type == LD_RT_LV)
log_debug("S %s R %s LV uuid %s", ls->name, r->name, lv_uuid);
memset(&rdi->id, 0x0, sizeof(struct idm_lock_id));
if (r->type == LD_RT_VG) {
uuid_read_format(rdi->id.vg_uuid, ls->vg_uuid);
} else if (r->type == LD_RT_LV) {
uuid_read_format(rdi->id.vg_uuid, ls->vg_uuid);
uuid_read_format(rdi->id.lv_uuid, lv_uuid);
}
/*
* Establish the drive path list for lock, since different lock type
* has different drive list; the GL lock uses the global pv list,
* the VG lock uses the pv list spanned for the whole volume group,
* the LV lock uses the pv list for the logical volume.
*/
switch (r->type) {
case LD_RT_GL:
drive_path = glb_lock_op.drives;
rdi->op.drive_num = glb_lock_op.drive_num;
break;
case LD_RT_VG:
drive_path = (char **)ls->pvs.path;
rdi->op.drive_num = ls->pvs.num;
break;
case LD_RT_LV:
drive_path = (char **)pvs->path;
rdi->op.drive_num = pvs->num;
break;
default:
break;
}
if (!drive_path) {
log_error("S %s R %s cannot find the valid drive path array",
ls->name, r->name);
return -EINVAL;
}
if (rdi->op.drive_num >= ILM_DRIVE_MAX_NUM) {
log_error("S %s R %s exceeds limitation for drive path array",
ls->name, r->name);
return -EINVAL;
}
for (i = 0; i < rdi->op.drive_num; i++)
rdi->op.drives[i] = drive_path[i];
log_debug("S %s R %s mode %d drive_num %d timeout %d",
ls->name, r->name, rdi->op.mode,
rdi->op.drive_num, rdi->op.timeout);
for (i = 0; i < rdi->op.drive_num; i++)
log_debug("S %s R %s drive path[%d] %s",
ls->name, r->name, i, rdi->op.drives[i]);
rv = ilm_lock(lmi->sock, &rdi->id, &rdi->op);
if (rv < 0) {
log_debug("S %s R %s lock_idm acquire mode %d rv %d",
ls->name, r->name, ld_mode, rv);
return -ELOCKIO;
}
if (rdi->vb) {
rv = ilm_read_lvb(lmi->sock, &rdi->id, (char *)&timestamp,
sizeof(uint64_t));
/*
* If fail to read value block, which might be caused by drive
* failure, notify up layer to invalidate metadata.
*/
if (rv < 0) {
log_error("S %s R %s lock_idm get_lvb error %d",
ls->name, r->name, rv);
reset_vb = 1;
/* Reset timestamp */
rdi->vb_timestamp = 0;
/*
* If the cached timestamp mismatches with the stored value
* in the IDM, this means another host has updated timestamp
* for the new VB. Let's reset VB and notify up layer to
* invalidate metadata.
*/
} else if (rdi->vb_timestamp != timestamp) {
log_debug("S %s R %s lock_idm get lvb timestamp %lu:%lu",
ls->name, r->name, rdi->vb_timestamp,
timestamp);
rdi->vb_timestamp = timestamp;
reset_vb = 1;
}
if (reset_vb == 1) {
memset(rdi->vb, 0, sizeof(struct val_blk));
memset(vb_out, 0, sizeof(struct val_blk));
/*
* The lock is still acquired, but the vb values has
* been invalidated.
*/
rv = 0;
goto out;
}
/* Otherwise, copy the cached VB to up layer */
memcpy(vb_out, rdi->vb, sizeof(struct val_blk));
}
out:
return rv;
}
int lm_convert_idm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
int mode, rv;
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
if (!rdi->vb->version) {
/* first time vb has been written */
rdi->vb->version = VAL_BLK_VERSION;
}
rdi->vb->r_version = r_version;
log_debug("S %s R %s convert_idm set r_version %u",
ls->name, r->name, r_version);
lm_idm_update_vb_timestamp(&rdi->vb_timestamp);
log_debug("S %s R %s convert_idm vb %x %x %u timestamp %lu",
ls->name, r->name, rdi->vb->version, rdi->vb->flags,
rdi->vb->r_version, rdi->vb_timestamp);
}
mode = to_idm_mode(ld_mode);
if (mode < 0) {
log_error("S %s R %s convert_idm invalid mode %d",
ls->name, r->name, ld_mode);
return -EINVAL;
}
log_debug("S %s R %s convert_idm", ls->name, r->name);
if (daemon_test)
return 0;
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
rv = ilm_write_lvb(lmi->sock, &rdi->id,
(char *)rdi->vb_timestamp, sizeof(uint64_t));
if (rv < 0) {
log_error("S %s R %s convert_idm write lvb error %d",
ls->name, r->name, rv);
return -ELMERR;
}
}
rv = ilm_convert(lmi->sock, &rdi->id, mode);
if (rv < 0)
log_error("S %s R %s convert_idm convert error %d",
ls->name, r->name, rv);
return rv;
}
int lm_unlock_idm(struct lockspace *ls, struct resource *r,
uint32_t r_version, uint32_t lmu_flags)
{
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi = (struct rd_idm *)r->lm_data;
int rv;
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
if (!rdi->vb->version) {
/* first time vb has been written */
rdi->vb->version = VAL_BLK_VERSION;
}
if (r_version)
rdi->vb->r_version = r_version;
lm_idm_update_vb_timestamp(&rdi->vb_timestamp);
log_debug("S %s R %s unlock_idm vb %x %x %u timestamp %lu",
ls->name, r->name, rdi->vb->version, rdi->vb->flags,
rdi->vb->r_version, rdi->vb_timestamp);
}
log_debug("S %s R %s unlock_idm", ls->name, r->name);
if (daemon_test)
return 0;
if (rdi->vb && r_version && (r->mode == LD_LK_EX)) {
rv = ilm_write_lvb(lmi->sock, &rdi->id,
(char *)&rdi->vb_timestamp, sizeof(uint64_t));
if (rv < 0) {
log_error("S %s R %s unlock_idm set_lvb error %d",
ls->name, r->name, rv);
return -ELMERR;
}
}
rv = ilm_unlock(lmi->sock, &rdi->id);
if (rv < 0)
log_error("S %s R %s unlock_idm error %d", ls->name, r->name, rv);
return rv;
}
int lm_hosts_idm(struct lockspace *ls, int notify)
{
struct resource *r;
struct lm_idm *lmi = (struct lm_idm *)ls->lm_data;
struct rd_idm *rdi;
int count, self, found_others = 0;
int rv;
list_for_each_entry(r, &ls->resources, list) {
if (!r->lm_init)
continue;
rdi = (struct rd_idm *)r->lm_data;
rv = ilm_get_host_count(lmi->sock, &rdi->id, &rdi->op,
&count, &self);
if (rv < 0) {
log_error("S %s lm_hosts_idm error %d", ls->name, rv);
return rv;
}
/* Fixup: need to reduce self count */
if (count > found_others)
found_others = count;
}
return found_others;
}
int lm_get_lockspaces_idm(struct list_head *ls_rejoin)
{
/* TODO: Need to add support for adoption. */
return -1;
}
int lm_is_running_idm(void)
{
int sock, rv;
if (daemon_test)
return gl_use_idm;
rv = ilm_connect(&sock);
if (rv < 0) {
log_error("Fail to connect seagate IDM lock manager %d", rv);
return 0;
}
ilm_disconnect(sock);
return 1;
}

View File

@@ -20,7 +20,6 @@
#define R_NAME_GL "GLLK"
#define R_NAME_VG "VGLK"
#define S_NAME_GL_DLM "lvm_global"
#define S_NAME_GL_IDM "lvm_global"
#define LVM_LS_PREFIX "lvm_" /* ls name is prefix + vg_name */
/* global lockspace name for sanlock is a vg name */
@@ -30,7 +29,6 @@ enum {
LD_LM_UNUSED = 1, /* place holder so values match lib/locking/lvmlockd.h */
LD_LM_DLM = 2,
LD_LM_SANLOCK = 3,
LD_LM_IDM = 4,
};
/* operation types */
@@ -120,11 +118,6 @@ struct client {
*/
#define DEFAULT_MAX_RETRIES 4
struct pvs {
char **path;
int num;
};
struct action {
struct list_head list;
uint32_t client_id;
@@ -147,7 +140,6 @@ struct action {
char vg_args[MAX_ARGS+1];
char lv_args[MAX_ARGS+1];
char vg_sysid[MAX_NAME+1];
struct pvs pvs; /* PV list for idm */
};
struct resource {
@@ -166,7 +158,7 @@ struct resource {
struct list_head locks;
struct list_head actions;
char lv_args[MAX_ARGS+1];
char lm_data[]; /* lock manager specific data */
char lm_data[0]; /* lock manager specific data */
};
#define LD_LF_PERSISTENT 0x00000001
@@ -192,7 +184,6 @@ struct lockspace {
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
int free_lock_sector_size; /* for sanlock */
int free_lock_align_size; /* for sanlock */
struct pvs pvs; /* for idm: PV list */
uint32_t start_client_id; /* client_id that started the lockspace */
pthread_t thread; /* makes synchronous lock requests */
@@ -334,13 +325,10 @@ static inline int list_empty(const struct list_head *head)
EXTERN int gl_type_static;
EXTERN int gl_use_dlm;
EXTERN int gl_use_sanlock;
EXTERN int gl_use_idm;
EXTERN int gl_vg_removed;
EXTERN char gl_lsname_dlm[MAX_NAME+1];
EXTERN char gl_lsname_sanlock[MAX_NAME+1];
EXTERN char gl_lsname_idm[MAX_NAME+1];
EXTERN int global_dlm_lockspace_exists;
EXTERN int global_idm_lockspace_exists;
EXTERN int daemon_test; /* run as much as possible without a live lock manager */
EXTERN int daemon_debug;
@@ -631,102 +619,4 @@ static inline int lm_support_sanlock(void)
#endif /* sanlock support */
#ifdef LOCKDIDM_SUPPORT
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);
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);
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,
uint32_t r_version, uint32_t lmu_flags);
int lm_hosts_idm(struct lockspace *ls, int notify);
int lm_get_lockspaces_idm(struct list_head *ls_rejoin);
int lm_is_running_idm(void);
int lm_rem_resource_idm(struct lockspace *ls, struct resource *r);
static inline int lm_support_idm(void)
{
return 1;
}
#else
static inline int lm_data_size_idm(void)
{
return -1;
}
static inline int lm_init_vg_idm(char *ls_name, char *vg_name, uint32_t flags,
char *vg_args)
{
return -1;
}
static inline int lm_prepare_lockspace_idm(struct lockspace *ls)
{
return -1;
}
static inline int lm_add_lockspace_idm(struct lockspace *ls, int adopt)
{
return -1;
}
static inline int lm_rem_lockspace_idm(struct lockspace *ls, int free_vg)
{
return -1;
}
static inline int lm_lock_idm(struct lockspace *ls, struct resource *r, int ld_mode,
struct val_blk *vb_out, char *lv_uuid, struct pvs *pvs,
int adopt)
{
return -1;
}
static inline int lm_convert_idm(struct lockspace *ls, struct resource *r,
int ld_mode, uint32_t r_version)
{
return -1;
}
static inline int lm_unlock_idm(struct lockspace *ls, struct resource *r,
uint32_t r_version, uint32_t lmu_flags)
{
return -1;
}
static inline int lm_hosts_idm(struct lockspace *ls, int notify)
{
return -1;
}
static inline int lm_get_lockspaces_idm(struct list_head *ls_rejoin)
{
return -1;
}
static inline int lm_is_running_idm(void)
{
return 0;
}
static inline int lm_rem_resource_idm(struct lockspace *ls, struct resource *r)
{
return -1;
}
static inline int lm_support_idm(void)
{
return 0;
}
#endif /* Seagate IDM support */
#endif /* _LVM_LVMLOCKD_INTERNAL_H */

View File

@@ -227,17 +227,6 @@ int lm_data_size_sanlock(void)
static uint64_t daemon_test_lv_count;
/*
* Copy a null-terminated string "str" into a fixed
* size (SANLK_NAME_LEN) struct field "buf" which is
* not null terminated.
*/
static void strcpy_name_len(char *buf, char *str, int 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)
{
return last_string_from_args(vg_args, lock_lv_name);
@@ -585,7 +574,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
}
}
strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN);
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
ss.host_id_disk.offset = 0;
ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
@@ -618,7 +607,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, (char *)gl_name, SANLK_NAME_LEN);
strncpy(rd.rs.name, 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;
@@ -633,7 +622,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, (char *)R_NAME_VG, SANLK_NAME_LEN);
strncpy(rd.rs.name, 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;
@@ -667,8 +656,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(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, (char *)"#unused", SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strcpy(rd.rs.name, "#unused");
offset = align_size * LV_LOCK_BEGIN;
@@ -736,7 +725,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
return 0;
}
strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
return rv;
@@ -811,7 +800,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
log_debug("S %s init_lv_san %s found unused area at %llu",
ls_name, lv_name, (unsigned long long)offset);
strcpy_name_len(rd.rs.name, lv_name, SANLK_NAME_LEN);
strncpy(rd.rs.name, lv_name, SANLK_NAME_LEN);
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -910,7 +899,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
if (!sector_size || !align_size)
return -1;
strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN);
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
@@ -935,7 +924,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return rv;
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -960,7 +949,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return rv;
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -994,7 +983,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
break;
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv) {
@@ -1020,7 +1009,7 @@ int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
if (daemon_test)
return 0;
strcpy_name_len(rs->name, (char *)"#unused", SANLK_NAME_LEN);
strcpy(rs->name, "#unused");
rv = sanlock_write_resource(rs, 0, 0, 0);
if (rv < 0) {
@@ -1054,14 +1043,14 @@ int lm_ex_disable_gl_sanlock(struct lockspace *ls)
memset(&rd1, 0, sizeof(rd1));
memset(&rd2, 0, sizeof(rd2));
strcpy_name_len(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd1.rs.name, (char *)R_NAME_GL, SANLK_NAME_LEN);
strncpy(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd1.rs.name, R_NAME_GL, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.name, (char *)R_NAME_GL_DISABLED, SANLK_NAME_LEN);
strncpy(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd2.rs.name, 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);
strncpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
rd1.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
@@ -1123,11 +1112,11 @@ 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, (char *)gl_name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd.rs.name, 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);
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -1164,12 +1153,12 @@ static int gl_is_enabled(struct lockspace *ls, struct lm_sanlock *lms)
memset(&rd, 0, sizeof(rd));
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
/* leave rs.name empty, it is what we're checking */
rd.rs.num_disks = 1;
memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
offset = lms->align_size * GL_LOCK_BEGIN;
rd.rs.disks[0].offset = offset;
@@ -1235,9 +1224,9 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *
memset(&rd, 0, sizeof(rd));
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls->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);
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -1422,7 +1411,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
memcpy(lms->ss.name, lsname, SANLK_NAME_LEN);
lms->ss.host_id_disk.offset = 0;
lms->ss.host_id = ls->host_id;
memcpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1);
strncpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1);
if (daemon_test) {
if (!gl_lsname_sanlock[0]) {
@@ -1514,7 +1503,8 @@ out:
fail:
if (lms && lms->sock)
close(lms->sock);
free(lms);
if (lms)
free(lms);
return ret;
}
@@ -1588,7 +1578,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, (char *)"#unused", SANLK_NAME_LEN);
strncpy(lms->ss.name, "#unused", SANLK_NAME_LEN);
rv = sanlock_write_lockspace(&lms->ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
@@ -1616,8 +1606,8 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
strcpy_name_len(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rds->rs.name, r->name, SANLK_NAME_LEN);
strncpy(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rds->rs.name, r->name, SANLK_NAME_LEN);
rds->rs.num_disks = 1;
memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN);
rds->rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -1644,7 +1634,8 @@ int lm_rem_resource_sanlock(struct lockspace *ls, struct resource *r)
/* FIXME: assert r->mode == UN or unlock if it's not? */
free(rds->vb);
if (rds->vb)
free(rds->vb);
memset(rds, 0, sizeof(struct rd_sanlock));
r->lm_init = 0;
@@ -1660,7 +1651,7 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
struct sanlk_options opt;
uint64_t lock_lv_offset;
uint32_t flags = 0;
struct val_blk vb = { 0 };
struct val_blk vb;
int added = 0;
int rv;
@@ -2046,7 +2037,7 @@ 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, (char *)"invalid_removed", SANLK_NAME_LEN);
strcpy(res2->name, "invalid_removed");
res_args[0] = res1;
res_args[1] = res2;
@@ -2239,8 +2230,8 @@ int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin)
ls->lm_type = LD_LM_SANLOCK;
ls->host_id = ss->host_id;
memcpy(ls->name, ss->name, SANLK_NAME_LEN);
memcpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), SANLK_NAME_LEN - strlen(LVM_LS_PREFIX));
strncpy(ls->name, ss->name, MAX_NAME);
strncpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), MAX_NAME);
list_add_tail(&ls->list, ls_rejoin);
ss++;

View File

@@ -19,11 +19,12 @@ SOURCES = lvmpolld-core.c lvmpolld-data-utils.c lvmpolld-cmd-utils.c
TARGETS = lvmpolld
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
CFLOW_TARGET := $(TARGETS)
.PHONY: install_lvmpolld
CFLOW_LIST = $(SOURCES)
CFLOW_LIST_TARGET = $(LIB_NAME).cflow
CFLOW_TARGET = lvmpolld
include $(top_builddir)/make.tmpl
CFLAGS += $(EXTRA_EXEC_CFLAGS)

View File

@@ -92,12 +92,6 @@ const char **cmdargv_ctr(const struct lvmpolld_lv *pdlv, const char *lvm_binary,
if (!add_to_cmd_arr(&cmd_argv, "-An", &i))
goto err;
if (pdlv->devicesfile) {
if (!add_to_cmd_arr(&cmd_argv, "--devicesfile", &i) ||
!add_to_cmd_arr(&cmd_argv, pdlv->devicesfile, &i))
goto err;
}
/* terminating NULL */
if (!add_to_cmd_arr(&cmd_argv, NULL, &i))
goto err;

View File

@@ -149,7 +149,7 @@ static void _lvmpolld_global_unlock(struct lvmpolld_state *ls)
static int _fini(struct daemon_state *s)
{
int done;
const struct timespec t = { .tv_nsec = 10000000 }; /* .01 sec */
const struct timespec t = { .tv_nsec = 250000000 }; /* .25 sec */
struct lvmpolld_state *ls = s->private;
DEBUGLOG(s, "fini");
@@ -236,7 +236,9 @@ static int poll_for_output(struct lvmpolld_lv *pdlv, struct lvmpolld_thread_data
}
while (1) {
r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000);
do {
r = poll(fds, 2, pdlv_get_timeout(pdlv) * 1000);
} while (r < 0 && errno == EINTR);
DEBUGLOG(pdlv->ls, "%s: %s %d", PD_LOG_PREFIX, "poll() returned", r);
if (r < 0) {
@@ -372,7 +374,7 @@ static void debug_print(struct lvmpolld_state *ls, const char * const* ptr)
static void *fork_and_poll(void *args)
{
int outfd, errfd, state = 0;
int outfd, errfd, state;
struct lvmpolld_thread_data *data;
pid_t r;
@@ -553,15 +555,14 @@ static struct lvmpolld_lv *construct_pdlv(request req, struct lvmpolld_state *ls
const char *interval, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
unsigned abort_polling, unsigned uinterval,
const char *devicesfile)
unsigned abort_polling, unsigned uinterval)
{
const char **cmdargv, **cmdenvp;
struct lvmpolld_lv *pdlv;
unsigned handle_missing_pvs = daemon_request_int(req, LVMPD_PARM_HANDLE_MISSING_PVS, 0);
pdlv = pdlv_create(ls, id, vgname, lvname, sysdir, type,
interval, uinterval, pdst, devicesfile);
interval, uinterval, pdst);
if (!pdlv) {
ERROR(ls, "%s: %s", PD_LOG_PREFIX, "failed to create internal LV data structure.");
@@ -620,7 +621,6 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
const char *lvname = daemon_request_str(req, LVMPD_PARM_LVNAME, NULL);
const char *vgname = daemon_request_str(req, LVMPD_PARM_VGNAME, NULL);
const char *sysdir = daemon_request_str(req, LVMPD_PARM_SYSDIR, NULL);
const char *devicesfile = daemon_request_str(req, LVMPD_PARM_DEVICESFILE, NULL);
unsigned abort_polling = daemon_request_int(req, LVMPD_PARM_ABORT, 0);
assert(type < POLL_TYPE_MAX);
@@ -680,7 +680,7 @@ static response poll_init(client_handle h, struct lvmpolld_state *ls, request re
pdlv->init_rq_count++; /* safe. protected by store lock */
} else {
pdlv = construct_pdlv(req, ls, pdst, interval, id, vgname,
lvname, sysdir, type, abort_polling, 2 * uinterval, devicesfile);
lvname, sysdir, type, abort_polling, 2 * uinterval);
if (!pdlv) {
pdst_unlock(pdst);
free(id);

View File

@@ -93,13 +93,11 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
const char *sinterval, unsigned pdtimeout,
struct lvmpolld_store *pdst,
const char *devicesfile)
struct lvmpolld_store *pdst)
{
char *lvmpolld_id = strdup(id), /* copy */
*full_lvname = _construct_full_lvname(vgname, lvname), /* copy */
*lvm_system_dir_env = _construct_lvm_system_dir_env(sysdir); /* copy */
char *devicesfile_dup = devicesfile ? strdup(devicesfile) : NULL;
struct lvmpolld_lv tmp = {
.ls = ls,
@@ -107,7 +105,6 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
.lvmpolld_id = lvmpolld_id,
.lvid = _get_lvid(lvmpolld_id, sysdir),
.lvname = full_lvname,
.devicesfile = devicesfile_dup,
.lvm_system_dir_env = lvm_system_dir_env,
.sinterval = strdup(sinterval), /* copy */
.pdtimeout = pdtimeout < MIN_POLLING_TIMEOUT ? MIN_POLLING_TIMEOUT : pdtimeout,
@@ -127,7 +124,6 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
return pdlv;
err:
free((void *)devicesfile_dup);
free((void *)full_lvname);
free((void *)lvmpolld_id);
free((void *)lvm_system_dir_env);
@@ -140,7 +136,6 @@ err:
void pdlv_destroy(struct lvmpolld_lv *pdlv)
{
free((void *)pdlv->lvmpolld_id);
free((void *)pdlv->devicesfile);
free((void *)pdlv->lvname);
free((void *)pdlv->sinterval);
free((void *)pdlv->lvm_system_dir_env);

View File

@@ -49,7 +49,6 @@ struct lvmpolld_lv {
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;
@@ -102,8 +101,7 @@ struct lvmpolld_lv *pdlv_create(struct lvmpolld_state *ls, const char *id,
const char *vgname, const char *lvname,
const char *sysdir, enum poll_type type,
const char *sinterval, unsigned pdtimeout,
struct lvmpolld_store *pdst,
const char *devicesfile);
struct lvmpolld_store *pdst);
/* only call with appropriate struct lvmpolld_store lock held */
void pdlv_destroy(struct lvmpolld_lv *pdlv);

View File

@@ -35,7 +35,6 @@
#define LVMPD_PARM_SYSDIR "sysdir"
#define LVMPD_PARM_VALUE "value" /* either retcode or signal value */
#define LVMPD_PARM_VGNAME "vgname"
#define LVMPD_PARM_DEVICESFILE "devicesfile"
#define LVMPD_RESP_FAILED "failed"
#define LVMPD_RESP_FINISHED "finished"

View File

@@ -164,20 +164,20 @@ struct dm_info {
struct dm_deps {
uint32_t count;
uint32_t filler;
uint64_t device[];
uint64_t device[0];
};
struct dm_names {
uint64_t dev;
uint32_t next; /* Offset to next struct from start of this struct */
char name[];
char name[0];
};
struct dm_versions {
uint32_t next; /* Offset to next struct from start of this struct */
uint32_t version[3];
char name[];
char name[0];
};
int dm_get_library_version(char *version, size_t size);
@@ -234,7 +234,6 @@ int dm_task_suppress_identical_reload(struct dm_task *dmt);
int dm_task_secure_data(struct dm_task *dmt);
int dm_task_retry_remove(struct dm_task *dmt);
int dm_task_deferred_remove(struct dm_task *dmt);
int dm_task_ima_measurement(struct dm_task *dmt);
void dm_task_skip_reload_params_compare(struct dm_task *dmt);
/*
@@ -952,8 +951,6 @@ struct writecache_settings {
uint64_t autocommit_time; /* in milliseconds */
uint32_t fua;
uint32_t nofua;
uint32_t cleaner;
uint32_t max_age;
/*
* Allow an unrecognized key and its val to be passed to the kernel for
@@ -973,8 +970,6 @@ struct writecache_settings {
unsigned autocommit_time_set:1;
unsigned fua_set:1;
unsigned nofua_set:1;
unsigned cleaner_set:1;
unsigned max_age_set:1;
};
int dm_tree_node_add_writecache_target(struct dm_tree_node *node,
@@ -1020,7 +1015,6 @@ int dm_tree_node_add_integrity_target(struct dm_tree_node *node,
*/
int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
uint64_t size,
const char *vdo_pool_name,
const char *data_uuid,
uint64_t data_size,
const struct dm_vdo_target_params *param);
@@ -1073,10 +1067,10 @@ int dm_tree_node_add_replicator_dev_target(struct dm_tree_node *node,
#define DM_THIN_MIN_DATA_BLOCK_SIZE (UINT32_C(128))
#define DM_THIN_MAX_DATA_BLOCK_SIZE (UINT32_C(2097152))
/*
* Max supported size for thin pool metadata device (17045913600 bytes)
* Max supported size for thin pool metadata device (17112760320 bytes)
* Limitation is hardcoded into the kernel and bigger device size
* is not accepted.
* drivers/md/dm-thin-metadata.h THIN_METADATA_MAX_SECTORS
* But here DM_THIN_MAX_METADATA_SIZE got defined incorrectly
* Correct size is (UINT64_C(255) * ((1 << 14) - 64) * (4096 / (1 << 9)))
*/
#define DM_THIN_MAX_METADATA_SIZE (UINT64_C(255) * (1 << 14) * (4096 / (1 << 9)) - 256 * 1024)
@@ -1089,16 +1083,6 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint64_t low_water_mark,
unsigned skip_block_zeroing);
int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
uint64_t size,
uint64_t transaction_id,
const char *metadata_uuid,
const char *pool_uuid,
uint32_t data_block_size,
uint64_t low_water_mark,
unsigned skip_block_zeroing,
unsigned crop_metadata);
/* Supported messages for thin provision target */
typedef enum {
DM_THIN_MESSAGE_CREATE_SNAP, /* device_id, origin_id */
@@ -1329,7 +1313,7 @@ int dm_bit_get_next(dm_bitset_t bs, int last_bit);
int dm_bit_get_last(dm_bitset_t bs);
int dm_bit_get_prev(dm_bitset_t bs, int last_bit);
#define DM_BITS_PER_INT ((unsigned)sizeof(int) * CHAR_BIT)
#define DM_BITS_PER_INT (sizeof(int) * CHAR_BIT)
#define dm_bit(bs, i) \
((bs)[((i) / DM_BITS_PER_INT) + 1] & (0x1 << ((i) & (DM_BITS_PER_INT - 1))))

View File

@@ -150,8 +150,7 @@ dm_bitset_t dm_bitset_parse_list(const char *str, struct dm_pool *mem,
size_t min_num_bits)
{
unsigned a, b;
int c, old_c, totaldigits, ndigits;
size_t nmaskbits;
int c, old_c, totaldigits, ndigits, nmaskbits;
int at_start, in_range;
dm_bitset_t mask = NULL;
const char *start = str;
@@ -243,3 +242,18 @@ bad:
}
return NULL;
}
#if defined(__GNUC__)
/*
* Maintain backward compatibility with older versions that did not
* accept a 'min_num_bits' argument to dm_bitset_parse_list().
*/
dm_bitset_t dm_bitset_parse_list_v1_02_129(const char *str, struct dm_pool *mem);
dm_bitset_t dm_bitset_parse_list_v1_02_129(const char *str, struct dm_pool *mem)
{
return dm_bitset_parse_list(str, mem, 0);
}
#else /* if defined(__GNUC__) */
#endif

View File

@@ -205,7 +205,7 @@ static int _get_proc_number(const char *file, const char *name,
}
while (getline(&line, &len, fl) != -1) {
if (sscanf(line, "%u %255s\n", &num, &nm[0]) == 2) {
if (sscanf(line, "%d %255s\n", &num, &nm[0]) == 2) {
if (!strcmp(name, nm)) {
if (number) {
*number = num;
@@ -493,10 +493,7 @@ static void _dm_task_free_targets(struct dm_task *dmt)
for (t = dmt->head; t; t = n) {
n = t->next;
if (dmt->secure_data)
_dm_zfree_string(t->params);
else
free(t->params);
_dm_zfree_string(t->params);
free(t->type);
free(t);
}
@@ -507,10 +504,7 @@ static void _dm_task_free_targets(struct dm_task *dmt)
void dm_task_destroy(struct dm_task *dmt)
{
_dm_task_free_targets(dmt);
if (dmt->secure_data)
_dm_zfree_dmi(dmt->dmi.v4);
else
free(dmt->dmi.v4);
_dm_zfree_dmi(dmt->dmi.v4);
free(dmt->dev_name);
free(dmt->mangled_dev_name);
free(dmt->newname);
@@ -926,13 +920,6 @@ int dm_task_secure_data(struct dm_task *dmt)
return 1;
}
int dm_task_ima_measurement(struct dm_task *dmt)
{
dmt->ima_measurement = 1;
return 1;
}
int dm_task_retry_remove(struct dm_task *dmt)
{
dmt->retry_remove = 1;
@@ -1125,7 +1112,7 @@ static int _add_params(int type)
static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
{
size_t min_size;
const size_t min_size = 16 * 1024;
const int (*version)[3];
struct dm_ioctl *dmi;
@@ -1144,18 +1131,6 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
else if (dmt->head)
log_debug_activation(INTERNAL_ERROR "dm '%s' ioctl should not define parameters.",
_cmd_data_v4[dmt->type].name);
switch (dmt->type) {
case DM_DEVICE_CREATE:
case DM_DEVICE_DEPS:
case DM_DEVICE_LIST:
case DM_DEVICE_STATUS:
case DM_DEVICE_TABLE:
case DM_DEVICE_TARGET_MSG:
min_size = 16 * 1024;
break;
default:
min_size = 2 * 1024;
}
if (count && (dmt->sector || dmt->message)) {
log_error("targets and message are incompatible");
@@ -1257,11 +1232,9 @@ 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))
/* coverity[buffer_size_warning] */
strncpy(dmi->name, DEV_NAME(dmt), sizeof(dmi->name));
if (DEV_UUID(dmt))
/* coverity[buffer_size_warning] */
strncpy(dmi->uuid, DEV_UUID(dmt), sizeof(dmi->uuid));
if (dmt->type == DM_DEVICE_SUSPEND)
@@ -1300,14 +1273,6 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
}
dmi->flags |= DM_UUID_FLAG;
}
if (dmt->ima_measurement) {
if (_dm_version_minor < 45) {
log_error("WARNING: IMA measurement unsupported by "
"kernel. Aborting operation.");
goto bad;
}
dmi->flags |= DM_IMA_MEASUREMENT_FLAG;
}
dmi->target_count = count;
dmi->event_nr = dmt->event_nr;
@@ -1369,7 +1334,7 @@ static int _process_mapper_dir(struct dm_task *dmt)
}
if (closedir(d))
log_sys_debug("closedir", dir);
log_sys_error("closedir", dir);
return r;
}
@@ -1503,7 +1468,6 @@ static int _create_and_load_v4(struct dm_task *dmt)
task->head = dmt->head;
task->tail = dmt->tail;
task->secure_data = dmt->secure_data;
task->ima_measurement = dmt->ima_measurement;
r = dm_task_run(task);
@@ -1618,30 +1582,23 @@ static int _reload_with_suppression_v4(struct dm_task *dmt)
t2->params[len] = '\0';
if (t1->start != t2->start) {
log_debug("reload %u:%u diff start %llu %llu type %s %s", task->major, task->minor,
(unsigned long long)t1->start, (unsigned long long)t2->start, t1->type, t2->type);
log_debug("reload %u:%u start diff", task->major, task->minor);
goto no_match;
}
if (t1->length != t2->length) {
log_debug("reload %u:%u diff length %llu %llu type %s %s", task->major, task->minor,
(unsigned long long)t1->length, (unsigned long long)t2->length, t1->type, t2->type);
log_debug("reload %u:%u length diff", task->major, task->minor);
goto no_match;
}
if (strcmp(t1->type, t2->type)) {
log_debug("reload %u:%u diff type %s %s", task->major, task->minor, t1->type, t2->type);
log_debug("reload %u:%u type diff %s %s", task->major, task->minor, t1->type, t2->type);
goto no_match;
}
if (strcmp(t1->params, t2->params)) {
if (dmt->skip_reload_params_compare) {
log_debug("reload %u:%u diff params ignore for type %s",
task->major, task->minor, t1->type);
log_debug("reload params1 %s", t1->params);
log_debug("reload params2 %s", t2->params);
} else {
log_debug("reload %u:%u diff params for type %s",
task->major, task->minor, t1->type);
log_debug("reload params1 %s", t1->params);
log_debug("reload params2 %s", t2->params);
if (dmt->skip_reload_params_compare)
log_debug("reload %u:%u skip params ignore %s %s",
task->major, task->minor, t1->params, t2->params);
else {
log_debug("reload %u:%u params diff", task->major, task->minor);
goto no_match;
}
}
@@ -1917,7 +1874,7 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
}
log_debug_activation("dm %s %s%s %s%s%s %s%.0d%s%.0d%s"
"%s[ %s%s%s%s%s%s%s%s%s%s] %.0" PRIu64 " %s [%u] (*%u)",
"%s[ %s%s%s%s%s%s%s%s%s] %.0" PRIu64 " %s [%u] (*%u)",
_cmd_data_v4[dmt->type].name,
dmt->new_uuid ? "UUID " : "",
dmi->name, dmi->uuid, dmt->newname ? " " : "",
@@ -1935,7 +1892,6 @@ static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned command,
dmt->retry_remove ? "retryremove " : "",
dmt->deferred_remove ? "deferredremove " : "",
dmt->secure_data ? "securedata " : "",
dmt->ima_measurement ? "ima_measurement " : "",
dmt->query_inactive_table ? "inactive " : "",
dmt->enable_checks ? "enablechecks " : "",
dmt->sector, _sanitise_message(dmt->message),
@@ -2228,3 +2184,52 @@ void dm_lib_exit(void)
_version_ok = 1;
_version_checked = 0;
}
#if defined(__GNUC__)
/*
* Maintain binary backward compatibility.
* Version script mechanism works with 'gcc' compatible compilers only.
*/
/*
* This following code is here to retain ABI compatibility after adding
* the field deferred_remove to struct dm_info in version 1.02.89.
*
* Binaries linked against version 1.02.88 of libdevmapper or earlier
* will use this function that returns dm_info without the
* deferred_remove field.
*
* Binaries compiled against version 1.02.89 onwards will use
* the new function dm_task_get_info_with_deferred_remove due to the
* #define.
*
* N.B. Keep this function at the end of the file to make sure that
* no code in this file accidentally calls it.
*/
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info);
int dm_task_get_info_base(struct dm_task *dmt, struct dm_info *info)
{
struct dm_info new_info;
if (!dm_task_get_info(dmt, &new_info))
return 0;
memcpy(info, &new_info, offsetof(struct dm_info, deferred_remove));
return 1;
}
int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *info);
int dm_task_get_info_with_deferred_remove(struct dm_task *dmt, struct dm_info *info)
{
struct dm_info new_info;
if (!dm_task_get_info(dmt, &new_info))
return 0;
memcpy(info, &new_info, offsetof(struct dm_info, internal_suspend));
return 1;
}
#endif

View File

@@ -70,7 +70,6 @@ struct dm_task {
int enable_checks;
int expected_errno;
int ioctl_errno;
int ima_measurement;
int record_timestamp;

View File

@@ -338,7 +338,6 @@ struct dm_task *dm_task_create(int type)
dmt->new_uuid = 0;
dmt->secure_data = 0;
dmt->record_timestamp = 0;
dmt->ima_measurement = 0;
return dmt;
}
@@ -383,7 +382,7 @@ static int _find_dm_name_of_device(dev_t st_rdev, char *buf, size_t buf_len)
}
if (closedir(d))
log_sys_debug("closedir", _dm_dir);
log_sys_error("closedir", _dm_dir);
return r;
}
@@ -513,7 +512,7 @@ int unmangle_string(const char *str, const char *str_name, size_t len,
int strict = mode != DM_STRING_MANGLING_NONE;
char str_rest[DM_NAME_LEN];
size_t i, j;
unsigned int code;
int code;
int r = 0;
if (!str || !buf)
@@ -932,7 +931,7 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
#ifdef HAVE_SELINUX
static int _selabel_lookup(const char *path, mode_t mode,
char **scontext)
security_context_t *scontext)
{
#ifdef HAVE_SELINUX_LABEL_H
if (!_selabel_handle &&
@@ -975,7 +974,7 @@ static int _is_selinux_enabled(void)
int dm_prepare_selinux_context(const char *path, mode_t mode)
{
#ifdef HAVE_SELINUX
char *scontext = NULL;
security_context_t scontext = NULL;
if (_is_selinux_enabled() <= 0)
return 1;
@@ -1003,7 +1002,7 @@ int dm_prepare_selinux_context(const char *path, mode_t mode)
int dm_set_selinux_context(const char *path, mode_t mode)
{
#ifdef HAVE_SELINUX
char *scontext = NULL;
security_context_t scontext = NULL;
if (_is_selinux_enabled() <= 0)
return 1;
@@ -1225,7 +1224,7 @@ int get_dev_node_read_ahead(const char *dev_name, uint32_t major, uint32_t minor
int len;
int r = 1;
int fd;
long read_ahead_long = 0;
long read_ahead_long;
/*
* If we know the device number, use sysfs if we can.
@@ -1921,7 +1920,7 @@ static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, si
continue;
if ((sz = dm_snprintf(path, sizeof(path), "%sblock/%s/dev",
_sysfs_dir, name)) < 5) {
_sysfs_dir, name)) == -1) {
log_warn("Couldn't create path for %s.", name);
continue;
}

View File

@@ -599,7 +599,7 @@ static struct dm_config_node *_section(struct parser *p, struct dm_config_node *
match(TOK_IDENTIFIER);
}
if (!*str) {
if (!strlen(str)) {
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): empty section identifier",
p->tb - p->fb + 1, p->line);
return NULL;
@@ -983,7 +983,7 @@ static const char *_find_config_str(const void *start, node_lookup_fn find_fn,
}
if (fail)
log_very_verbose("%s not found in config: defaulting to \"%s\"",
log_very_verbose("%s not found in config: defaulting to %s",
path, fail);
return fail;
}

View File

@@ -330,7 +330,16 @@ struct dm_tree_node {
dm_node_callback_fn callback;
void *callback_data;
int activated; /* tracks activation during preload */
/*
* TODO:
* Add advanced code which tracks of send ioctls and their
* proper revert operation for more advanced recovery
* Current code serves mostly only to recovery when
* thin pool metadata check fails and command would
* have left active thin data and metadata subvolumes.
*/
struct dm_list activated; /* Head of activated nodes for preload revert */
struct dm_list activated_list; /* List of activated nodes for preload revert */
};
struct dm_tree {
@@ -365,18 +374,19 @@ struct dm_tree *dm_tree_create(void)
dtree->root.dtree = dtree;
dm_list_init(&dtree->root.uses);
dm_list_init(&dtree->root.used_by);
dm_list_init(&dtree->root.activated);
dtree->skip_lockfs = 0;
dtree->no_flush = 0;
dtree->mem = dmem;
dtree->optional_uuid_suffixes = NULL;
if (!(dtree->devs = dm_hash_create(61))) {
if (!(dtree->devs = dm_hash_create(8))) {
log_error("dtree hash creation failed");
dm_pool_destroy(dtree->mem);
return NULL;
}
if (!(dtree->uuids = dm_hash_create(31))) {
if (!(dtree->uuids = dm_hash_create(32))) {
log_error("dtree uuid hash creation failed");
dm_hash_destroy(dtree->devs);
dm_pool_destroy(dtree->mem);
@@ -549,6 +559,7 @@ static struct dm_tree_node *_create_dm_tree_node(struct dm_tree *dtree,
dm_list_init(&node->uses);
dm_list_init(&node->used_by);
dm_list_init(&node->activated);
dm_list_init(&node->props.segs);
dev = MKDEV(info->major, info->minor);
@@ -604,7 +615,7 @@ 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 (suffix_list && (suffix_position = strrchr(uuid, '-'))) {
if (suffix_list && (suffix_position = rindex(uuid, '-'))) {
while ((suffix = suffix_list[i++])) {
if (strcmp(suffix_position + 1, suffix))
continue;
@@ -1578,37 +1589,8 @@ static int _thin_pool_node_message(struct dm_tree_node *dnode, struct thin_messa
}
if (!_node_message(dnode->info.major, dnode->info.minor,
tm->expected_errno, buf)) {
switch (m->type) {
case DM_THIN_MESSAGE_CREATE_SNAP:
case DM_THIN_MESSAGE_CREATE_THIN:
if (errno == EEXIST) {
/*
* ATM errno from ioctl() is preserved through code error path chain
* If this would ever change, another way need to be used to
* obtain result from failed DM message
*/
log_error("Thin pool %s already contain thin device with device_id %u.",
_node_name(dnode), m->u.m_create_snap.device_id);
/*
* TODO:
*
* Give some useful advice how to solve this problem,
* until lvconvert --repair can handle this automatically
*/
log_error("Manual intervention may be required to remove device dev_id=%u in thin pool metadata.",
m->u.m_create_snap.device_id);
log_error("Optionally new thin volume with device_id=%u can be manually added into a volume group.",
m->u.m_create_snap.device_id);
log_warn("WARNING: When uncertain how to do this, contact support!");
return 0;
}
/* fall through */
default:
return_0;
}
}
tm->expected_errno, buf))
return_0;
return 1;
}
@@ -1655,15 +1637,6 @@ static int _thin_pool_node_send_messages(struct dm_tree_node *dnode,
if (!have_messages || !send)
return 1; /* transaction_id is matching */
if (stp.fail || stp.read_only || stp.needs_check) {
log_error("Cannot send messages to thin pool %s%s%s%s.",
_node_name(dnode),
stp.fail ? " in failed state" : "",
stp.read_only ? " with read only metadata" : "",
stp.needs_check ? " which needs check first" : "");
return 0;
}
dm_list_iterate_items(tmsg, &seg->thin_messages) {
if (!(_thin_pool_node_message(dnode, tmsg)))
return_0;
@@ -2125,7 +2098,7 @@ int dm_tree_activate_children(struct dm_tree_node *dnode,
return r;
}
static int _create_node(struct dm_tree_node *dnode, struct dm_tree_node *parent)
static int _create_node(struct dm_tree_node *dnode)
{
int r = 0;
struct dm_task *dmt;
@@ -2174,15 +2147,38 @@ static int _create_node(struct dm_tree_node *dnode, struct dm_tree_node *parent)
"Unable to get DM task info for %s.",
dnode->name);
}
if (r)
dnode->activated = 1;
out:
dm_task_destroy(dmt);
return r;
}
/*
* _remove_node
*
* This function is only used to remove a DM device that has failed
* to load any table.
*/
static int _remove_node(struct dm_tree_node *dnode)
{
if (!dnode->info.exists)
return 1;
if (dnode->info.live_table || dnode->info.inactive_table) {
log_error(INTERNAL_ERROR
"_remove_node called on device with loaded table(s).");
return 0;
}
if (!_deactivate_node(dnode->name, dnode->info.major, dnode->info.minor,
&dnode->dtree->cookie, dnode->udev_flags, 0)) {
log_error("Failed to clean-up device with no table: %s.",
_node_name(dnode));
return 0;
}
return 1;
}
static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *node)
{
if (!dm_format_dev(devbuf, bufsize, node->info.major, node->info.minor)) {
@@ -2371,7 +2367,7 @@ static int _mirror_emit_segment_line(struct dm_task *dmt, struct load_segment *s
EMIT_PARAMS(pos, " %u ", seg->mirror_area_count);
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
return_0;
if (handle_errors)
@@ -2573,7 +2569,7 @@ static int _raid_emit_segment_line(struct dm_task *dmt, uint32_t major,
/* Print number of metadata/data device pairs */
EMIT_PARAMS(pos, " %u", area_count);
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
if (_emit_areas_line(dmt, seg, params, paramsize, &pos) <= 0)
return_0;
return 1;
@@ -2633,7 +2629,7 @@ static int _cache_emit_segment_line(struct dm_task *dmt,
EMIT_PARAMS(pos, " %s", name);
/* Do not pass migration_threshold 2048 which is default */
EMIT_PARAMS(pos, " %u", (seg->policy_argc + ((seg->migration_threshold != 2048) ? 1 : 0)) * 2);
EMIT_PARAMS(pos, " %u", (seg->policy_argc + (seg->migration_threshold != 2048) ? 1 : 0) * 2);
if (seg->migration_threshold != 2048)
EMIT_PARAMS(pos, " migration_threshold %u", seg->migration_threshold);
if (seg->policy_settings)
@@ -2674,10 +2670,6 @@ static int _writecache_emit_segment_line(struct dm_task *dmt,
count += 1;
if (seg->writecache_settings.nofua_set)
count += 1;
if (seg->writecache_settings.cleaner_set && seg->writecache_settings.cleaner)
count += 1;
if (seg->writecache_settings.max_age_set)
count += 2;
if (seg->writecache_settings.new_key)
count += 2;
@@ -2721,14 +2713,6 @@ static int _writecache_emit_segment_line(struct dm_task *dmt,
EMIT_PARAMS(pos, " nofua");
}
if (seg->writecache_settings.cleaner_set && seg->writecache_settings.cleaner) {
EMIT_PARAMS(pos, " cleaner");
}
if (seg->writecache_settings.max_age_set) {
EMIT_PARAMS(pos, " max_age %u", seg->writecache_settings.max_age);
}
if (seg->writecache_settings.new_key) {
EMIT_PARAMS(pos, " %s %s",
seg->writecache_settings.new_key,
@@ -2813,9 +2797,6 @@ static int _integrity_emit_segment_line(struct dm_task *dmt,
if (set->sectors_per_bit_set)
EMIT_PARAMS(pos, " sectors_per_bit:%llu", (unsigned long long)set->sectors_per_bit);
if (!dm_task_secure_data(dmt))
stack;
return 1;
}
@@ -2874,8 +2855,7 @@ static int _vdo_emit_segment_line(struct dm_task *dmt,
seg->vdo_params.block_map_era_length,
seg->vdo_params.use_metadata_hints ? "on" : "off" ,
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_SYNC) ? "sync" :
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC) ? "async" :
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC_UNSAFE) ? "async-unsafe" : "auto", // policy
(seg->vdo_params.write_policy == DM_VDO_WRITE_POLICY_ASYNC) ? "async" : "auto", // policy
seg->vdo_name,
seg->vdo_params.max_discard,
seg->vdo_params.ack_threads,
@@ -2920,6 +2900,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
size_t paramsize)
{
int pos = 0;
int r;
int target_type_is_raid = 0;
char originbuf[DM_FORMAT_DEV_BUFSIZE], cowbuf[DM_FORMAT_DEV_BUFSIZE];
@@ -2930,7 +2911,8 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
break;
case SEG_MIRRORED:
/* Mirrors are pretty complicated - now in separate function */
if (!_mirror_emit_segment_line(dmt, seg, params, paramsize))
r = _mirror_emit_segment_line(dmt, seg, params, paramsize);
if (!r)
return_0;
break;
case SEG_SNAPSHOT:
@@ -2951,7 +2933,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
EMIT_PARAMS(pos, "%u %u ", seg->area_count, seg->stripe_size);
break;
case SEG_VDO:
if (!_vdo_emit_segment_line(dmt, seg, params, paramsize))
if (!(r = _vdo_emit_segment_line(dmt, seg, params, paramsize)))
return_0;
break;
case SEG_CRYPT:
@@ -2980,8 +2962,9 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
case SEG_RAID6_LA_6:
case SEG_RAID6_RA_6:
target_type_is_raid = 1;
if (!_raid_emit_segment_line(dmt, major, minor, seg, seg_start,
params, paramsize))
r = _raid_emit_segment_line(dmt, major, minor, seg, seg_start,
params, paramsize);
if (!r)
return_0;
break;
@@ -3022,9 +3005,10 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
case SEG_CRYPT:
case SEG_LINEAR:
case SEG_STRIPED:
if (!_emit_areas_line(dmt, seg, params, paramsize, &pos))
return_0;
if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) {
stack;
return r;
}
if (!params[0]) {
log_error("No parameters supplied for %s target "
"%u:%u.", _dm_segtypes[seg->type].target,
@@ -3169,45 +3153,32 @@ out:
return r;
}
/* Try to deactivate only nodes created during preload. */
static int _dm_tree_revert_activated(struct dm_tree_node *dnode)
/*
* Currently try to deactivate only nodes created during preload.
* New node is always attached to the front of activated_list
*/
static int _dm_tree_revert_activated(struct dm_tree_node *parent)
{
void *handle = NULL;
struct dm_tree_node *child;
while ((child = dm_tree_next_child(&handle, dnode, 0))) {
if (child->activated) {
if (child->callback) {
log_debug_activation("Dropping callback for %s.", _node_name(child));
child->callback = NULL;
}
log_debug_activation("Reverting %s.", _node_name(child));
if (!_deactivate_node(child->name, child->info.major, child->info.minor,
&child->dtree->cookie, child->udev_flags, 0)) {
log_debug_activation("Unable to deactivate %s.", _node_name(child));
return 0;
}
dm_list_iterate_items_gen(child, &parent->activated, activated_list) {
log_debug_activation("Reverting %s.", _node_name(child));
if (child->callback) {
log_debug_activation("Dropping callback for %s.", _node_name(child));
child->callback = NULL;
}
if (dm_tree_node_num_children(child, 0) &&
!_dm_tree_revert_activated(child))
if (!_deactivate_node(child->name, child->info.major, child->info.minor,
&child->dtree->cookie, child->udev_flags, 0)) {
log_error("Unable to deactivate %s.", _node_name(child));
return 0;
}
if (!_dm_tree_revert_activated(child))
return_0;
}
return 1;
}
static int _dm_tree_wait_and_revert_activated(struct dm_tree_node *dnode)
{
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
stack;
dm_tree_set_cookie(dnode, 0);
return _dm_tree_revert_activated(dnode);
}
int dm_tree_preload_children(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len)
@@ -3237,7 +3208,7 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
return_0;
/* FIXME Cope if name exists with no uuid? */
if (!child->info.exists && !(node_created = _create_node(child, dnode)))
if (!child->info.exists && !(node_created = _create_node(child)))
return_0;
/* Propagate delayed resume from exteded child node */
@@ -3247,15 +3218,24 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
if (!child->info.inactive_table &&
child->props.segment_count &&
!_load_node(child)) {
stack;
/*
* If the table load fails, try to device in the kernel
* together with other created and preloaded devices.
* If the table load does not succeed, we remove the
* device in the kernel that would otherwise have an
* empty table. This makes the create + load of the
* device atomic. However, if other dependencies have
* already been created and loaded; this code is
* insufficient to remove those - only the node
* encountering the table load failure is removed.
*/
if (!_dm_tree_wait_and_revert_activated(dnode))
stack;
r = 0;
continue;
if (node_created) {
if (!_remove_node(child))
return_0;
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
stack;
dm_tree_set_cookie(dnode, 0);
(void) _dm_tree_revert_activated(child);
}
return_0;
}
/* No resume for a device without parents or with unchanged or smaller size */
@@ -3273,19 +3253,28 @@ int dm_tree_preload_children(struct dm_tree_node *dnode,
&child->info, &child->dtree->cookie, child->udev_flags,
child->info.suspended)) {
log_error("Unable to resume %s.", _node_name(child));
if (!_dm_tree_wait_and_revert_activated(dnode))
stack;
/* If the device was not previously active, we might as well remove this node. */
if (!child->info.live_table &&
!_deactivate_node(child->name, child->info.major, child->info.minor,
&child->dtree->cookie, child->udev_flags, 0))
log_error("Unable to deactivate %s.", _node_name(child));
r = 0;
/* Each child is handled independently */
continue;
}
if (node_created) {
/* Collect newly introduced devices for revert */
dm_list_add_h(&dnode->activated, &child->activated_list);
/* When creating new node also check transaction_id. */
if (child->props.send_messages &&
!_node_send_messages(child, uuid_prefix, uuid_prefix_len, 0)) {
stack;
if (!_dm_tree_wait_and_revert_activated(dnode))
if (!dm_udev_wait(dm_tree_get_cookie(dnode)))
stack;
dm_tree_set_cookie(dnode, 0);
(void) _dm_tree_revert_activated(dnode);
r = 0;
continue;
}
@@ -3970,24 +3959,6 @@ int dm_tree_node_add_thin_pool_target(struct dm_tree_node *node,
uint32_t data_block_size,
uint64_t low_water_mark,
unsigned skip_block_zeroing)
{
return dm_tree_node_add_thin_pool_target_v1(node, size, transaction_id,
metadata_uuid, pool_uuid,
data_block_size,
low_water_mark,
skip_block_zeroing,
1);
}
int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
uint64_t size,
uint64_t transaction_id,
const char *metadata_uuid,
const char *pool_uuid,
uint32_t data_block_size,
uint64_t low_water_mark,
unsigned skip_block_zeroing,
unsigned crop_metadata)
{
struct load_segment *seg, *mseg;
uint64_t devsize = 0;
@@ -4015,18 +3986,17 @@ int dm_tree_node_add_thin_pool_target_v1(struct dm_tree_node *node,
if (!_link_tree_nodes(node, seg->metadata))
return_0;
if (crop_metadata)
/* FIXME: more complex target may need more tweaks */
dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
devsize += mseg->size;
if (devsize > DM_THIN_MAX_METADATA_SIZE) {
log_debug_activation("Ignoring %" PRIu64 " of device.",
devsize - DM_THIN_MAX_METADATA_SIZE);
mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
devsize = DM_THIN_MAX_METADATA_SIZE;
/* FIXME: drop remaining segs */
}
/* FIXME: more complex target may need more tweaks */
dm_list_iterate_items(mseg, &seg->metadata->props.segs) {
devsize += mseg->size;
if (devsize > DM_THIN_MAX_METADATA_SIZE) {
log_debug_activation("Ignoring %" PRIu64 " of device.",
devsize - DM_THIN_MAX_METADATA_SIZE);
mseg->size -= (devsize - DM_THIN_MAX_METADATA_SIZE);
devsize = DM_THIN_MAX_METADATA_SIZE;
/* FIXME: drop remaining segs */
}
}
if (!(seg->pool = dm_tree_find_node_by_uuid(node->dtree, pool_uuid))) {
log_error("Missing pool uuid %s.", pool_uuid);
@@ -4321,9 +4291,63 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode,
dnode->callback_data = data;
}
#if defined(__GNUC__)
/*
* Backward compatible implementations.
*
* Keep these at the end of the file to make sure that
* no code in this file accidentally calls it.
*/
/* Backward compatible dm_tree_node_size_changed() implementations. */
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode);
int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode)
{
/* Base does not make difference between smaller and bigger */
return dm_tree_node_size_changed(dnode) ? 1 : 0;
}
/*
* Retain ABI compatibility after adding the DM_CACHE_FEATURE_METADATA2
* in version 1.02.138.
*
* Binaries compiled against version 1.02.138 onwards will use
* the new function dm_tree_node_add_cache_target which detects unknown
* feature flags and returns error for them.
*/
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
uint64_t size,
uint64_t feature_flags, /* DM_CACHE_FEATURE_* */
const char *metadata_uuid,
const char *data_uuid,
const char *origin_uuid,
const char *policy_name,
const struct dm_config_node *policy_settings,
uint32_t data_block_size);
int dm_tree_node_add_cache_target_base(struct dm_tree_node *node,
uint64_t size,
uint64_t feature_flags,
const char *metadata_uuid,
const char *data_uuid,
const char *origin_uuid,
const char *policy_name,
const struct dm_config_node *policy_settings,
uint32_t data_block_size)
{
/* Old version supported only these FEATURE bits, others were ignored so masked them */
static const uint64_t _mask =
DM_CACHE_FEATURE_WRITEBACK |
DM_CACHE_FEATURE_WRITETHROUGH |
DM_CACHE_FEATURE_PASSTHROUGH;
return dm_tree_node_add_cache_target(node, size, feature_flags & _mask,
metadata_uuid, data_uuid, origin_uuid,
policy_name, policy_settings, 0, 0, 0, 0, data_block_size);
}
#endif
int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
uint64_t size,
const char *vdo_pool_name,
const char *data_uuid,
uint64_t data_size,
const struct dm_vdo_target_params *vtp)
@@ -4345,7 +4369,7 @@ int dm_tree_node_add_vdo_target(struct dm_tree_node *node,
return_0;
seg->vdo_params = *vtp;
seg->vdo_name = vdo_pool_name;
seg->vdo_name = node->name;
seg->vdo_data_size = data_size;
node->props.send_messages = 2;

View File

@@ -110,7 +110,7 @@ int dm_is_empty_dir(const char *dir)
DIR *d;
if (!(d = opendir(dir))) {
log_sys_debug("opendir", dir);
log_sys_error("opendir", dir);
return 0;
}
@@ -119,7 +119,7 @@ int dm_is_empty_dir(const char *dir)
break;
if (closedir(d))
log_sys_debug("closedir", dir);
log_sys_error("closedir", dir);
return dirent ? 0 : 1;
}

View File

@@ -492,7 +492,7 @@ static int _report_field_string_list(struct dm_report *rh,
delimiter = ",";
delimiter_len = strlen(delimiter);
i = pos = 0;
i = pos = len = 0;
dm_list_iterate_items(sl, data) {
arr[i].str = sl->str;
if (!sort) {
@@ -749,11 +749,10 @@ static void _display_fields_more(struct dm_report *rh,
id_len = strlen(type->prefix) + 3;
for (f = 0; fields[f].report_fn; f++) {
if (!(type = _find_type(rh, fields[f].type))) {
log_debug(INTERNAL_ERROR "Field type undefined.");
continue;
}
desc = (type->desc) ? : " ";
if ((type = _find_type(rh, fields[f].type)) && type->desc)
desc = type->desc;
else
desc = " ";
if (desc != last_desc) {
if (*last_desc)
log_warn(" ");
@@ -2332,7 +2331,7 @@ static const char *_reserved_name(struct dm_report *rh,
uint32_t field_num, const char *s, size_t len)
{
dm_report_reserved_handler handler;
const char *canonical_name = NULL;
const char *canonical_name;
const char **name;
char *tmp_s;
char c;
@@ -2474,7 +2473,7 @@ dm_percent_t dm_make_percent(uint64_t numerator, uint64_t denominator)
int dm_report_value_cache_set(struct dm_report *rh, const char *name, const void *data)
{
if (!rh->value_cache && (!(rh->value_cache = dm_hash_create(63)))) {
if (!rh->value_cache && (!(rh->value_cache = dm_hash_create(64)))) {
log_error("Failed to create cache for values used during reporting.");
return 0;
}
@@ -3774,7 +3773,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh,
struct field_selection *fs;
struct selection_node *sn;
const char *ws, *we; /* field name */
const char *vs = NULL, *ve = NULL; /* value */
const char *vs, *ve; /* value */
const char *last;
uint32_t flags, field_num;
int implicit;
@@ -3910,7 +3909,7 @@ static struct selection_node *_parse_ex(struct dm_report *rh,
static const char _pe_expected_msg[] = "Syntax error: right parenthesis expected at \'%s\'";
struct selection_node *sn = NULL;
uint32_t t;
const char *tmp = NULL;
const char *tmp;
t = _tok_op_log(s, next, SEL_MODIFIER_NOT | SEL_PRECEDENCE_PS);
if (t == SEL_MODIFIER_NOT) {
@@ -3956,7 +3955,7 @@ static struct selection_node *_parse_and_ex(struct dm_report *rh,
struct selection_node *and_sn)
{
struct selection_node *n;
const char *tmp = NULL;
const char *tmp;
n = _parse_ex(rh, s, next);
if (!n)
@@ -3988,7 +3987,7 @@ static struct selection_node *_parse_or_ex(struct dm_report *rh,
struct selection_node *or_sn)
{
struct selection_node *n;
const char *tmp = NULL;
const char *tmp;
n = _parse_and_ex(rh, s, next, NULL);
if (!n)

View File

@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.0+ WITH Linux-syscall-note */
/*
* Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
* Copyright (C) 2004 - 2021 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004 - 2017 Red Hat, Inc. All rights reserved.
*
* This file is released under the LGPL.
*/
@@ -195,22 +194,8 @@ struct dm_name_list {
uint32_t next; /* offset to the next record from
the _start_ of this */
char name[0];
/*
* The following members can be accessed by taking a pointer that
* points immediately after the terminating zero character in "name"
* and aligning this pointer to next 8-byte boundary.
* Uuid is present if the flag DM_NAME_LIST_FLAG_HAS_UUID is set.
*
* uint32_t event_nr;
* uint32_t flags;
* char uuid[0];
*/
};
#define DM_NAME_LIST_FLAG_HAS_UUID 1
#define DM_NAME_LIST_FLAG_DOESNT_HAVE_UUID 2
/*
* Used to retrieve the target versions
*/
@@ -289,9 +274,9 @@ enum {
#define DM_GET_TARGET_VERSION _IOWR(DM_IOCTL, DM_GET_TARGET_VERSION_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
#define DM_VERSION_MINOR 45
#define DM_VERSION_MINOR 36
#define DM_VERSION_PATCHLEVEL 0
#define DM_VERSION_EXTRA "-ioctl (2021-03-22)"
#define DM_VERSION_EXTRA "-ioctl (2017-06-09)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
@@ -379,10 +364,4 @@ enum {
*/
#define DM_INTERNAL_SUSPEND_FLAG (1 << 18) /* Out */
/*
* If set, returns in the in buffer passed by UM, the raw table information
* that would be measured by IMA subsystem on device state change.
*/
#define DM_IMA_MEASUREMENT_FLAG (1 << 19) /* In */
#endif /* _LINUX_DM_IOCTL_H */

View File

@@ -98,7 +98,7 @@ void dm_pools_check_leaks(void)
p->orig_pool,
p->name, p->stats.bytes);
#else
log_error(" [%p] %s", (void *)p, p->name);
log_error(" [%p] %s", p, p->name);
#endif
}
pthread_mutex_unlock(&_dm_pools_mutex);

View File

@@ -69,8 +69,7 @@ bool dm_vdo_status_parse(struct dm_pool *mem, const char *input,
enum dm_vdo_write_policy {
DM_VDO_WRITE_POLICY_AUTO = 0,
DM_VDO_WRITE_POLICY_SYNC,
DM_VDO_WRITE_POLICY_ASYNC,
DM_VDO_WRITE_POLICY_ASYNC_UNSAFE
DM_VDO_WRITE_POLICY_ASYNC
};
// FIXME: review whether we should use the createParams from the userlib

View File

@@ -100,7 +100,6 @@ bool dm_vdo_validate_target_params(const struct dm_vdo_target_params *vtp,
switch (vtp->write_policy) {
case DM_VDO_WRITE_POLICY_SYNC:
case DM_VDO_WRITE_POLICY_ASYNC:
case DM_VDO_WRITE_POLICY_ASYNC_UNSAFE:
case DM_VDO_WRITE_POLICY_AUTO:
break;
default:

View File

@@ -94,7 +94,7 @@ journal_watermark:number
commit_time:number
Commit time in milliseconds. When this time passes, the journal is
written. The journal is also written immediately if the FLUSH
written. The journal is also written immediatelly if the FLUSH
request is received.
internal_hash:algorithm(:key) (the key is optional)

2
include/.gitignore vendored
View File

@@ -1,3 +1 @@
*.h
.symlinks
.symlinks_created

View File

@@ -1,8 +1,5 @@
/* include/configure.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 to include code that uses libsystemd machine-id apis. */
#undef APP_MACHINEID_SUPPORT
/* Define to 1 to use libblkid detection of signatures when wiping. */
#undef BLKID_WIPING_SUPPORT
@@ -90,9 +87,6 @@
/* Use blkid wiping by default. */
#undef DEFAULT_USE_BLKID_WIPING
/* Default for lvm.conf use_devicefile. */
#undef DEFAULT_USE_DEVICES_FILE
/* Use lvmlockd by default. */
#undef DEFAULT_USE_LVMLOCKD
@@ -132,15 +126,9 @@
/* Library version */
#undef DM_LIB_VERSION
/* Define to 1 to include the LVM editline shell. */
#undef EDITLINE_SUPPORT
/* Path to fsadm binary. */
#undef FSADM_PATH
/* Define to use GNU versioning in the shared library. */
#undef GNU_SYMVER
/* Define to 1 if you have the `alarm' function. */
#undef HAVE_ALARM
@@ -163,9 +151,6 @@
/* Define to 1 if you have the `atexit' function. */
#undef HAVE_ATEXIT
/* 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
@@ -191,18 +176,12 @@
/* 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. */
#undef HAVE_EDITLINE_READLINE_H
/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* 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
@@ -528,9 +507,6 @@
/* valgrind.h found */
#undef HAVE_VALGRIND
/* Define to 1 if you have the `versionsort' function. */
#undef HAVE_VERSIONSORT
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
@@ -555,12 +531,6 @@
/* Define to 1 if the system has the `__builtin_clzll' built-in function */
#undef HAVE___BUILTIN_CLZLL
/* Define to 1 if the system has the `__builtin_ffs' built-in function */
#undef HAVE___BUILTIN_FFS
/* Define to 1 to include built-in support for integrity. */
#undef INTEGRITY_INTERNAL
/* Internalization package */
#undef INTL_PACKAGE
@@ -573,9 +543,6 @@
/* Define to 1 to include code that uses lvmlockd dlm option. */
#undef LOCKDDLM_SUPPORT
/* Define to 1 to include code that uses lvmlockd IDM option. */
#undef LOCKDIDM_SUPPORT
/* Define to 1 to include code that uses lvmlockd sanlock option. */
#undef LOCKDSANLOCK_SUPPORT
@@ -586,9 +553,6 @@
/* Path to lvmconfig binary. */
#undef LVMCONFIG_PATH
/* Path to lvm_import_vdo script. */
#undef LVMIMPORTVDO_PATH
/* Path to lvmlockd pidfile. */
#undef LVMLOCKD_PIDFILE
@@ -671,9 +635,6 @@
/* Define to 1 if strerror_r returns char *. */
#undef STRERROR_R_CHAR_P
/* Define to 1 to include code that uses systemd journal. */
#undef SYSTEMD_JOURNAL_SUPPORT
/* Path to testsuite data */
#undef TESTSUITE_DATA
@@ -717,6 +678,9 @@
/* Define to 1 to include built-in support for writecache. */
#undef WRITECACHE_INTERNAL
/* Define to 1 to include built-in support for integrity. */
#undef INTEGRITY_INTERNAL
/* Define to get access to GNU/Linux extension */
#undef _GNU_SOURCE

View File

@@ -15,7 +15,6 @@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
abs_srcdir = @abs_srcdir@
SOURCES =\
activate/activate.c \
@@ -34,7 +33,6 @@ SOURCES =\
device/dev-ext.c \
device/dev-io.c \
device/dev-md.c \
device/dev-mpath.c \
device/dev-swap.c \
device/dev-type.c \
device/dev-luks.c \

View File

@@ -29,7 +29,6 @@
#include "lib/metadata/segtype.h"
#include "lib/misc/sharedlib.h"
#include "lib/metadata/metadata.h"
#include "lib/misc/lvm-signal.h"
#include <limits.h>
#include <fcntl.h>
@@ -178,22 +177,6 @@ int lv_passes_auto_activation_filter(struct cmd_context *cmd, struct logical_vol
return _lv_passes_volumes_filter(cmd, lv, cn, activation_auto_activation_volume_list_CFG);
}
static int _passes_readonly_filter(struct cmd_context *cmd,
const struct logical_volume *lv)
{
const struct dm_config_node *cn;
if (!(cn = find_config_tree_array(cmd, activation_read_only_volume_list_CFG, NULL)))
return 0;
return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
}
int lv_passes_readonly_filter(const struct logical_volume *lv)
{
return _passes_readonly_filter(lv->vg->cmd, lv);
}
#ifndef DEVMAPPER_SUPPORT
void set_activation(int act, int silent)
{
@@ -202,8 +185,8 @@ void set_activation(int act, int silent)
if (warned || !act)
return;
log_warn("WARNING: Compiled without libdevmapper support. "
"Can't enable activation.");
log_error("Compiled without libdevmapper support. "
"Can't enable activation.");
warned = 1;
}
@@ -238,13 +221,23 @@ int lv_info(struct cmd_context *cmd, const struct logical_volume *lv, int use_la
{
return 0;
}
int lv_info_with_seg_status(struct cmd_context *cmd,
const struct lv_segment *lv_seg,
int lv_info_by_lvid(struct cmd_context *cmd, const char *lvid_s, int use_layer,
struct lvinfo *info, int with_open_count, int with_read_ahead)
{
return 0;
}
int lv_info_with_seg_status(struct cmd_context *cmd, const struct logical_volume *lv,
const struct lv_segment *lv_seg, int use_layer,
struct lv_with_info_and_seg_status *status,
int with_open_count, int with_read_ahead)
{
return 0;
}
int lv_status(struct cmd_context *cmd, const struct lv_segment *lv_seg,
int use_layer, struct lv_seg_status *lv_seg_status)
{
return 0;
}
int lv_cache_status(const struct logical_volume *cache_lv,
struct lv_status_cache **status)
{
@@ -291,21 +284,18 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
{
return 0;
}
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status)
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
dm_percent_t *percent)
{
return 0;
}
int lv_writecache_message(const struct logical_volume *lv, const char *msg)
int lv_thin_percent(const struct logical_volume *lv, int mapped,
dm_percent_t *percent)
{
return 0;
}
int lv_thin_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **thin_pool_status)
{
return 0;
}
int lv_thin_status(const struct logical_volume *lv, int flush,
struct lv_status_thin **thin_status)
int lv_thin_pool_transaction_id(const struct logical_volume *lv,
uint64_t *transaction_id)
{
return 0;
}
@@ -313,15 +303,6 @@ int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
{
return 0;
}
int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_vdo **vdo_status)
{
return 0;
}
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent)
{
return 0;
}
int lvs_in_vg_activated(const struct volume_group *vg)
{
return 0;
@@ -413,7 +394,7 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
{
return 0;
}
int device_is_usable(struct device *dev, struct dev_usable_check_params check, int *is_lv)
int device_is_usable(struct device *dev, struct dev_usable_check_params check)
{
return 0;
}
@@ -476,6 +457,17 @@ static int _passes_activation_filter(struct cmd_context *cmd,
return _lv_passes_volumes_filter(cmd, lv, cn, activation_volume_list_CFG);
}
static int _passes_readonly_filter(struct cmd_context *cmd,
const struct logical_volume *lv)
{
const struct dm_config_node *cn;
if (!(cn = find_config_tree_array(cmd, activation_read_only_volume_list_CFG, NULL)))
return 0;
return _lv_passes_volumes_filter(cmd, lv, cn, activation_read_only_volume_list_CFG);
}
int library_version(char *version, size_t size)
{
if (!activation())
@@ -563,7 +555,7 @@ int module_present(struct cmd_context *cmd, const char *target_name)
dm_sysfs_dir(), target_name);
if (i > 0) {
while ((i > 0) && path[--i] != '/') /* stop on dm_ */
while (path[--i] != '/') /* stop on dm_ */
if (path[i] == '-')
path[i] = '_'; /* replace '-' with '_' */
@@ -574,9 +566,13 @@ int module_present(struct cmd_context *cmd, const char *target_name)
}
#ifdef MODPROBE_CMD
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) {
if (strcmp(target_name, MODULE_NAME_VDO) == 0) {
argv[1] = target_name; /* ATM kvdo is without dm- prefix */
if ((ret = exec_cmd(cmd, argv, NULL, 0)))
return ret;
}
if (dm_snprintf(module, sizeof(module), "dm-%s", target_name) < 0) {
log_error("module_present module name too long: %s",
target_name);
return 0;
@@ -829,15 +825,12 @@ int lv_info_with_seg_status(struct cmd_context *cmd,
#define OPEN_COUNT_CHECK_USLEEP_DELAY 200000
/* Only report error if error_if_used is set */
/* Returns 0 if in use, 1 if it is unused, 2 when it is not present in table */
int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
{
struct lvinfo info;
unsigned int open_count_check_retries;
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists)
return 2;
else if (!info.open_count)
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists || !info.open_count)
return 1;
/* If sysfs is not used, use open_count information only. */
@@ -864,24 +857,25 @@ int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
}
open_count_check_retries = retry_deactivation() ? OPEN_COUNT_CHECK_RETRIES : 1;
while (open_count_check_retries--) {
if (interruptible_usleep(OPEN_COUNT_CHECK_USLEEP_DELAY))
break; /* interrupted */
while (info.open_count > 0 && open_count_check_retries--) {
if (!open_count_check_retries) {
if (error_if_used)
log_error("Logical volume %s in use.", display_lvname(lv));
else
log_debug_activation("Logical volume %s in use.", display_lvname(lv));
return 0;
}
usleep(OPEN_COUNT_CHECK_USLEEP_DELAY);
log_debug_activation("Retrying open_count check for %s.",
display_lvname(lv));
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0) || !info.exists) {
if (!lv_info(lv->vg->cmd, lv, 0, &info, 1, 0)) {
stack; /* device dissappeared? */
return 1;
} else if (!info.open_count)
return 1;
break;
}
}
if (error_if_used)
log_error("Logical volume %s in use.", display_lvname(lv));
else
log_debug_activation("Logical volume %s in use.", display_lvname(lv));
return 0;
return 1;
}
/*
@@ -972,28 +966,35 @@ int lv_raid_percent(const struct logical_volume *lv, dm_percent_t *percent)
int lv_raid_data_offset(const struct logical_volume *lv, uint64_t *data_offset)
{
struct lv_status_raid *raid_status;
int r;
struct dev_manager *dm;
struct dm_status_raid *status;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
log_debug_activation("Checking raid data offset and dev sectors for LV %s/%s",
lv->vg->name, lv->name);
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!lv_raid_status(lv, &raid_status))
return_0;
if (!(r = dev_manager_raid_status(dm, lv, &status))) {
dev_manager_destroy(dm);
return_0;
}
*data_offset = raid_status->raid->data_offset;
*data_offset = status->data_offset;
dm_pool_destroy(raid_status->mem);
dev_manager_destroy(dm);
return 1;
return r;
}
int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
{
int r = 1;
struct lv_status_raid *raid_status;
int r;
struct dev_manager *dm;
struct dm_status_raid *status;
*dev_health = NULL;
@@ -1003,23 +1004,25 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health)
log_debug_activation("Checking raid device health for LV %s.",
display_lvname(lv));
if (!lv_raid_status(lv, &raid_status))
return_0;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem,
raid_status->raid->dev_health))) {
stack;
r = 0;
if (!(r = dev_manager_raid_status(dm, lv, &status)) ||
!(*dev_health = dm_pool_strdup(lv->vg->cmd->mem,
status->dev_health))) {
dev_manager_destroy(dm);
return_0;
}
dm_pool_destroy(raid_status->mem);
dev_manager_destroy(dm);
return r;
}
int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
{
struct lv_status_raid *raid_status;
struct dev_manager *dm;
struct dm_status_raid *status;
*dev_cnt = 0;
@@ -1028,20 +1031,24 @@ int lv_raid_dev_count(const struct logical_volume *lv, uint32_t *dev_cnt)
log_debug_activation("Checking raid device count for LV %s/%s",
lv->vg->name, lv->name);
if (!lv_raid_status(lv, &raid_status))
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
*dev_cnt = raid_status->raid->dev_count;
if (!dev_manager_raid_status(dm, lv, &status)) {
dev_manager_destroy(dm);
return_0;
}
*dev_cnt = status->dev_count;
dm_pool_destroy(raid_status->mem);
dev_manager_destroy(dm);
return 1;
}
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
{
struct lv_status_raid *raid_status;
struct dev_manager *dm;
struct dm_status_raid *status;
*cnt = 0;
@@ -1051,20 +1058,25 @@ int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt)
log_debug_activation("Checking raid mismatch count for LV %s.",
display_lvname(lv));
if (!lv_raid_status(lv, &raid_status))
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
*cnt = raid_status->raid->mismatch_count;
if (!dev_manager_raid_status(dm, lv, &status)) {
dev_manager_destroy(dm);
return_0;
}
*cnt = status->mismatch_count;
dm_pool_destroy(raid_status->mem);
dev_manager_destroy(dm);
return 1;
}
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
{
struct lv_status_raid *raid_status;
int r = 1;
struct dev_manager *dm;
struct dm_status_raid *status;
char *action;
*sync_action = NULL;
@@ -1074,27 +1086,30 @@ int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action)
log_debug_activation("Checking raid sync_action for LV %s.",
display_lvname(lv));
if (!lv_raid_status(lv, &raid_status))
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
/* status->sync_action can be NULL if dm-raid version < 1.5.0 */
if (!raid_status->raid->sync_action ||
!(*sync_action = dm_pool_strdup(lv->vg->cmd->mem,
raid_status->raid->sync_action))) {
stack;
r = 0;
if (!dev_manager_raid_status(dm, lv, &status) ||
!status->sync_action ||
!(action = dm_pool_strdup(lv->vg->cmd->mem,
status->sync_action))) {
dev_manager_destroy(dm);
return_0;
}
dm_pool_destroy(raid_status->mem);
*sync_action = action;
return r;
dev_manager_destroy(dm);
return 1;
}
int lv_raid_message(const struct logical_volume *lv, const char *msg)
{
struct lv_status_raid *raid_status;
struct dev_manager *dm = NULL;
int r = 0;
struct dev_manager *dm;
struct dm_status_raid *status;
if (!seg_is_raid(first_seg(lv))) {
/*
@@ -1119,10 +1134,16 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
return 0;
}
if (!lv_raid_status(lv, &raid_status))
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!raid_status->raid->sync_action) {
if (!(r = dev_manager_raid_status(dm, lv, &status))) {
log_error("Failed to retrieve status of %s.",
display_lvname(lv));
goto out;
}
if (!status->sync_action) {
log_error("Kernel driver does not support this action: %s", msg);
goto out;
}
@@ -1144,43 +1165,19 @@ int lv_raid_message(const struct logical_volume *lv, const char *msg)
log_error("\"%s\" is not a supported sync operation.", msg);
goto out;
}
if (strcmp(raid_status->raid->sync_action, "idle")) {
if (strcmp(status->sync_action, "idle")) {
log_error("%s state is currently \"%s\". Unable to switch to \"%s\".",
display_lvname(lv), raid_status->raid->sync_action, msg);
display_lvname(lv), status->sync_action, msg);
goto out;
}
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
r = dev_manager_raid_message(dm, lv, msg);
out:
if (dm)
dev_manager_destroy(dm);
dm_pool_destroy(raid_status->mem);
dev_manager_destroy(dm);
return r;
}
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status)
{
struct dev_manager *dm;
int exists;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!dev_manager_raid_status(dm, lv, status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
}
/* User has to call dm_pool_destroy(status->mem)! */
return 1;
}
int lv_writecache_message(const struct logical_volume *lv, const char *msg)
{
int r = 0;
@@ -1213,7 +1210,6 @@ int lv_cache_status(const struct logical_volume *cache_lv,
{
struct dev_manager *dm;
struct lv_segment *cache_seg;
int exists;
if (lv_is_cache_pool(cache_lv)) {
if (dm_list_empty(&cache_lv->segs_using_this_lv) ||
@@ -1231,74 +1227,125 @@ int lv_cache_status(const struct logical_volume *cache_lv,
return 0;
}
if (!lv_info(cache_lv->vg->cmd, cache_lv, 1, NULL, 0, 0)) {
log_error("Cannot check status for locally inactive cache volume %s.",
display_lvname(cache_lv));
return 0;
}
log_debug_activation("Checking status for cache volume %s.",
display_lvname(cache_lv));
if (!(dm = dev_manager_create(cache_lv->vg->cmd, cache_lv->vg->name, 1)))
return_0;
if (!dev_manager_cache_status(dm, cache_lv, status, &exists)) {
if (!dev_manager_cache_status(dm, cache_lv, status)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
return_0;
}
/* User has to call dm_pool_destroy(status->mem)! */
return 1;
}
int lv_thin_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **thin_pool_status)
/*
* Returns data or metadata percent usage, depends on metadata 0/1.
* Returns 1 if percent set, else 0 on failure.
*/
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
dm_percent_t *percent)
{
int r;
struct dev_manager *dm;
int exists;
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
return 0;
log_debug_activation("Checking thin %sdata percent for LV %s.",
(metadata) ? "meta" : "", display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!dev_manager_thin_pool_status(dm, lv, flush, thin_pool_status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
}
if (!(r = dev_manager_thin_pool_percent(dm, lv, metadata, percent)))
stack;
/* User has to call dm_pool_destroy(thin_pool_status->mem)! */
dev_manager_destroy(dm);
return 1;
return r;
}
int lv_thin_status(const struct logical_volume *lv, int flush,
struct lv_status_thin **thin_status)
/*
* Returns 1 if percent set, else 0 on failure.
*/
int lv_thin_percent(const struct logical_volume *lv,
int mapped, dm_percent_t *percent)
{
int r;
struct dev_manager *dm;
int exists;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
log_debug_activation("Checking thin percent for LV %s.",
display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!dev_manager_thin_status(dm, lv, flush, thin_status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
if (!(r = dev_manager_thin_percent(dm, lv, mapped, percent)))
stack;
dev_manager_destroy(dm);
return r;
}
/*
* Returns 1 if transaction_id set, else 0 on failure.
*/
int lv_thin_pool_transaction_id(const struct logical_volume *lv,
uint64_t *transaction_id)
{
int r;
struct dev_manager *dm;
struct dm_status_thin_pool *status;
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
return 0;
}
/* User has to call dm_pool_destroy(thin_status->mem)! */
log_debug_activation("Checking thin-pool transaction id for LV %s.",
display_lvname(lv));
return 1;
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_thin_pool_status(dm, lv, &status, 0)))
stack;
else
*transaction_id = status->transaction_id;
dev_manager_destroy(dm);
return r;
}
int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
{
struct dev_manager *dm;
int exists;
int r;
struct dev_manager *dm;
if (!lv_info(lv->vg->cmd, lv, 0, NULL, 0, 0))
return 0;
log_debug_activation("Checking device id for LV %s.",
display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, 1)))
return_0;
if (!(r = dev_manager_thin_device_id(dm, lv, device_id, &exists)))
if (exists)
stack;
if (!(r = dev_manager_thin_device_id(dm, lv, device_id)))
stack;
dev_manager_destroy(dm);
@@ -1315,22 +1362,28 @@ int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id)
int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_vdo **vdo_status)
{
int r = 0;
struct dev_manager *dm;
int exists;
if (!lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
return 0;
log_debug_activation("Checking VDO pool status for LV %s.",
display_lvname(lv));
if (!(dm = dev_manager_create(lv->vg->cmd, lv->vg->name, !lv_is_pvmove(lv))))
return_0;
if (!dev_manager_vdo_pool_status(dm, lv, flush, vdo_status, &exists)) {
dev_manager_destroy(dm);
if (exists)
stack;
return 0;
}
if (!dev_manager_vdo_pool_status(dm, lv, vdo_status, flush))
goto_out;
/* User has to call dm_pool_destroy(vdo_status->mem) */
r = 1;
out:
if (!r)
dev_manager_destroy(dm);
return 1;
return r;
}
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent)
@@ -1491,7 +1544,7 @@ int lvs_in_vg_opened(const struct volume_group *vg)
*/
int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype)
{
unsigned attrs = 0;
unsigned attrs;
if (segtype_is_raid4(segtype) &&
(!segtype->ops->target_present ||
@@ -2026,6 +2079,12 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
if (!activation())
return 1;
/* Ignore origin_only unless LV is origin in both old and new metadata */
/* or LV is thin or thin pool volume */
if (!lv_is_thin_volume(lv) && !lv_is_thin_pool(lv) &&
!(lv_is_origin(lv) && lv_is_origin(lv_pre)))
laopts->origin_only = 0;
if (test_mode()) {
_skip("Suspending %s%s.", display_lvname(lv),
laopts->origin_only ? " origin without snapshots" : "");
@@ -2047,12 +2106,6 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
lv_calculate_readahead(lv, NULL);
/* Ignore origin_only unless LV is origin in both old and new metadata */
/* or LV is thin or thin pool volume */
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.
* If the PVMOVE LV is being removed, it's only present in the old
@@ -2144,6 +2197,8 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
if (laopts->origin_only && lv_is_thin_volume(lv) && lv_is_thin_volume(lv_pre))
lockfs = 1;
critical_section_inc(cmd, "suspending");
if (!lv_is_locked(lv) && lv_is_locked(lv_pre) &&
(pvmove_lv = find_pvmove_lv_in_lv(lv_pre))) {
/*
@@ -2185,23 +2240,16 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
}
dm_list_add(&suspend_lvs, &lvl->list);
}
critical_section_inc(cmd, "suspending");
dm_list_iterate_items(lvl, &suspend_lvs)
if (!_lv_suspend_lv(lvl->lv, laopts, lockfs, 1)) {
critical_section_dec(cmd, "failed suspend");
goto_out; /* FIXME: resume on recovery path? */
}
} else { /* Standard suspend */
critical_section_inc(cmd, "suspending");
} else /* Standard suspend */
if (!_lv_suspend_lv(lv, laopts, lockfs, flush_required)) {
critical_section_dec(cmd, "failed suspend");
goto_out;
}
}
r = 1;
out:
@@ -2221,8 +2269,8 @@ int lv_suspend_if_active(struct cmd_context *cmd, const char *lvid_s, unsigned o
const struct logical_volume *lv, const struct logical_volume *lv_pre)
{
struct lv_activate_opts laopts = {
.exclusive = exclusive,
.origin_only = origin_only
.origin_only = origin_only,
.exclusive = exclusive
};
return _lv_suspend(cmd, lvid_s, &laopts, 0, lv, lv_pre);
@@ -2274,9 +2322,6 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
lv_is_thin_volume(lv) ? " thin only" : " without snapshots") : "",
laopts->revert ? " (reverting)" : "");
if (laopts->revert)
goto needs_resume;
if (!lv_info(cmd, lv, laopts->origin_only, &info, 0, 0))
goto_out;
@@ -2336,8 +2381,8 @@ int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s,
unsigned revert, const struct logical_volume *lv)
{
struct lv_activate_opts laopts = {
.exclusive = exclusive,
.origin_only = origin_only,
.exclusive = exclusive,
.revert = revert
};
@@ -2386,47 +2431,44 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, const struct logi
log_debug_activation("Deactivating %s.", display_lvname(lv));
if (!lv_info(cmd, lv, 0, &info, 0, 0))
goto_out;
if (!info.exists) {
r = 1;
/* Check attached snapshot segments are also inactive */
dm_list_iterate(snh, &lv->snapshot_segs) {
if (!lv_info(cmd, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow,
0, &info, 0, 0))
goto_out;
if (info.exists) {
r = 0; /* Snapshot left in table? */
break;
}
}
if (lv_is_vdo_pool(lv)) {
/* If someone has remove 'linear' mapping over VDO device
* we may still be able to deactivate the rest of the tree
* i.e. in test-suite we simulate this via 'dmsetup remove' */
if (!lv_info(cmd, lv, 1, &info, 1, 0))
goto_out;
if (info.exists && !info.open_count)
r = 0; /* Unused VDO device left in table? */
}
if (r)
goto out;
}
if (lv_is_visible(lv) || lv_is_virtual_origin(lv) ||
lv_is_merging_thin_snapshot(lv)) {
switch (lv_check_not_in_use(lv, 1)) {
case 0: goto_out;
case 2: goto no_exists;
}
if (!lv_check_not_in_use(lv, 1))
goto_out;
if (lv_is_origin(lv) && _lv_has_open_snapshots(lv))
goto_out;
} else {
if (!lv_info(cmd, lv, 0, &info, 0, 0))
goto_out;
if (!info.exists) {
no_exists:
r = 1;
/* Check attached snapshot segments are also inactive */
dm_list_iterate(snh, &lv->snapshot_segs) {
if (!lv_info(cmd, dm_list_struct_base(snh, struct lv_segment, origin_list)->cow,
0, &info, 0, 0))
goto_out;
if (info.exists) {
r = 0; /* Snapshot left in table? */
break;
}
}
if (lv_is_vdo_pool(lv)) {
/* If someone has remove 'linear' mapping over VDO device
* we may still be able to deactivate the rest of the tree
* i.e. in test-suite we simulate this via 'dmsetup remove' */
if (!lv_info(cmd, lv, 1, &info, 1, 0))
goto_out;
if (info.exists && !info.open_count)
r = 0; /* Unused VDO device left in table? */
}
if (r)
goto out;
}
}
if (!monitor_dev_for_events(cmd, lv, &laopts, 0))
@@ -2516,14 +2558,6 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
}
}
if ((cmd->partial_activation || cmd->degraded_activation) && lv_is_writecache(lv)) {
struct logical_volume *lv_fast = first_seg(lv)->writecache;
if (lv_is_partial(lv) || (lv_fast && lv_is_partial(lv_fast))) {
log_error("Cannot use partial or degraded activation with writecache.");
goto out;
}
}
if (lv_has_unknown_segments(lv)) {
log_error("Refusing activation of LV %s containing "
"an unrecognised segment.", display_lvname(lv));
@@ -2740,10 +2774,7 @@ static int _component_cb(struct logical_volume *lv, void *data)
(lv_is_thin_pool(lv) && pool_is_active(lv)))
return -1;
/* External origin is activated through thinLV and uses -real suffix.
* Note: for old clustered logic we would need to check for all thins */
if ((lv_is_external_origin(lv) && lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0)) ||
lv_is_active(lv)) {
if (lv_is_active(lv)) {
if (!lv_is_component(lv) || lv_is_visible(lv))
return -1; /* skip whole subtree */
@@ -2826,7 +2857,7 @@ static int _deactivate_sub_lv_cb(struct logical_volume *lv, void *data)
*/
int deactivate_lv_with_sub_lv(const struct logical_volume *lv)
{
struct logical_volume *flv = NULL;
struct logical_volume *flv;
if (!deactivate_lv(lv->vg->cmd, lv)) {
log_error("Cannot deactivate logical volume %s.",
@@ -2836,7 +2867,7 @@ int deactivate_lv_with_sub_lv(const struct logical_volume *lv)
if (!for_each_sub_lv((struct logical_volume *)lv, _deactivate_sub_lv_cb, &flv)) {
log_error("Cannot deactivate subvolume %s of logical volume %s.",
(flv) ? display_lvname(flv) : "", display_lvname(lv));
display_lvname(flv), display_lvname(lv));
return 0;
}
@@ -2931,7 +2962,8 @@ int revert_lv(struct cmd_context *cmd, const struct logical_volume *lv)
ret = lv_resume_if_active(cmd, NULL, 0, 0, 1, lv_committed(lv));
critical_section_dec(cmd, "unlocking on revert");
critical_section_dec(cmd, "unlocking on resume");
return ret;
}

View File

@@ -188,15 +188,16 @@ int lv_raid_dev_health(const struct logical_volume *lv, char **dev_health);
int lv_raid_mismatch_count(const struct logical_volume *lv, uint64_t *cnt);
int lv_raid_sync_action(const struct logical_volume *lv, char **sync_action);
int lv_raid_message(const struct logical_volume *lv, const char *msg);
int lv_raid_status(const struct logical_volume *lv, struct lv_status_raid **status);
int lv_writecache_message(const struct logical_volume *lv, const char *msg);
int lv_cache_status(const struct logical_volume *cache_lv,
struct lv_status_cache **status);
int lv_thin_pool_percent(const struct logical_volume *lv, int metadata,
dm_percent_t *percent);
int lv_thin_percent(const struct logical_volume *lv, int mapped,
dm_percent_t *percent);
int lv_thin_pool_transaction_id(const struct logical_volume *lv,
uint64_t *transaction_id);
int lv_thin_device_id(const struct logical_volume *lv, uint32_t *device_id);
int lv_thin_status(const struct logical_volume *lv, int flush,
struct lv_status_thin **status);
int lv_thin_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **status);
int lv_vdo_pool_status(const struct logical_volume *lv, int flush,
struct lv_status_vdo **status);
int lv_vdo_pool_percent(const struct logical_volume *lv, dm_percent_t *percent);
@@ -209,8 +210,6 @@ int lvs_in_vg_opened(const struct volume_group *vg);
int lv_is_active(const struct logical_volume *lv);
int lv_passes_readonly_filter(const struct logical_volume *lv);
/* Check is any component LV is active */
const struct logical_volume *lv_component_is_active(const struct logical_volume *lv);
const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv);
@@ -254,7 +253,7 @@ struct dev_usable_check_params {
* Returns 1 if mapped device is not suspended, blocked or
* is using a reserved name.
*/
int device_is_usable(struct device *dev, struct dev_usable_check_params check, int *is_lv);
int device_is_usable(struct device *dev, struct dev_usable_check_params check);
/*
* Declaration moved here from fs.h to keep header fs.h hidden

View File

@@ -26,7 +26,6 @@
#include "lib/activate/activate.h"
#include "lib/misc/lvm-exec.h"
#include "lib/datastruct/str_list.h"
#include "lib/misc/lvm-signal.h"
#include <limits.h>
#include <dirent.h>
@@ -157,7 +156,6 @@ out:
static int _get_segment_status_from_target_params(const char *target_name,
const char *params,
const struct dm_info *dminfo,
struct lv_seg_status *seg_status)
{
const struct lv_segment *seg = seg_status->seg;
@@ -217,7 +215,7 @@ static int _get_segment_status_from_target_params(const char *target_name,
return_0;
seg_status->type = SEG_STATUS_SNAPSHOT;
} else if (segtype_is_vdo_pool(segtype)) {
if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, dminfo, &seg_status->vdo_pool))
if (!parse_vdo_pool_status(seg_status->mem, seg->lv, params, &seg_status->vdo_pool))
return_0;
seg_status->type = SEG_STATUS_VDO_POOL;
} else if (segtype_is_writecache(segtype)) {
@@ -263,7 +261,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
int dmtask;
int with_flush; /* TODO: arg for _info_run */
void *target = NULL;
uint64_t target_start, target_length, start, length, length_crop = 0;
uint64_t target_start, target_length, start, length;
char *target_name, *target_params;
const char *devname;
@@ -299,7 +297,7 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
/* Uses max DM_THIN_MAX_METADATA_SIZE sectors for metadata device */
if (lv_is_thin_pool_metadata(seg_status->seg->lv) &&
(length > DM_THIN_MAX_METADATA_SIZE))
length_crop = DM_THIN_MAX_METADATA_SIZE;
length = DM_THIN_MAX_METADATA_SIZE;
/* Uses virtual size with headers for VDO pool device */
if (lv_is_vdo_pool(seg_status->seg->lv))
@@ -312,16 +310,14 @@ static int _info_run(const char *dlid, struct dm_info *dminfo,
target = dm_get_next_target(dmt, target, &target_start,
&target_length, &target_name, &target_params);
if ((start == target_start) &&
((length == target_length) ||
(length_crop && (length_crop == target_length))))
if ((start == target_start) && (length == target_length))
break; /* Keep target_params when matching segment is found */
target_params = NULL; /* Marking this target_params unusable */
} while (target);
if (!target_name ||
!_get_segment_status_from_target_params(target_name, target_params, dminfo, seg_status))
!_get_segment_status_from_target_params(target_name, target_params, seg_status))
stack;
}
@@ -407,7 +403,7 @@ static int _ignore_blocked_mirror_devices(struct device *dev,
.check_blocked = 1,
.check_suspended = ignore_suspended_devices(),
.check_error_target = 1,
.check_reserved = 0 }, NULL))
.check_reserved = 0 }))
goto out; /* safe to use */
stack;
}
@@ -622,17 +618,16 @@ static int _ignore_frozen_raid(struct device *dev, const char *params)
*
* Returns: 1 if usable, 0 otherwise
*/
int device_is_usable(struct device *dev, struct dev_usable_check_params check, int *is_lv)
int device_is_usable(struct device *dev, struct dev_usable_check_params check)
{
struct dm_task *dmt;
struct dm_info info;
const char *name, *uuid;
uint64_t start, length;
char *target_type = NULL;
char *params, *vgname, *lvname, *layer;
char vg_name[NAME_LEN];
char *params, *vgname = NULL, *lvname, *layer;
void *next = NULL;
int only_error_or_zero_target = 1;
int only_error_target = 1;
int r = 0;
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, NULL, NULL,
@@ -655,49 +650,42 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check, i
goto out;
}
if (uuid && (check.check_reserved || check.check_lv)) {
if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) { /* with LVM- prefix */
if (check.check_reserved) {
/* Check internal lvm devices */
if (strlen(uuid) > (sizeof(UUID_PREFIX) + 2 * ID_LEN)) { /* 68 with suffix */
log_debug_activation("%s: Reserved uuid %s on internal LV device %s not usable.",
dev_name(dev), uuid, name);
goto out;
}
/* Recognize some older reserved LVs just from the LV name (snapshot, pvmove...) */
vgname = vg_name;
if (!dm_strncpy(vg_name, name, sizeof(vg_name)) ||
!dm_split_lvm_name(NULL, NULL, &vgname, &lvname, &layer))
goto_out;
/* FIXME: fails to handle dev aliases i.e. /dev/dm-5, replace with UUID suffix */
if (lvname && (is_reserved_lvname(lvname) || *layer)) {
log_debug_activation("%s: Reserved internal LV device %s/%s%s%s not usable.",
dev_name(dev), vgname, lvname, *layer ? "-" : "", layer);
goto out;
}
}
if (check.check_lv) {
/* Skip LVs */
if (is_lv)
*is_lv = 1;
goto out;
}
}
if (check.check_reserved &&
(!strncmp(uuid, CRYPT_TEMP, sizeof(CRYPT_TEMP) - 1) ||
!strncmp(uuid, CRYPT_SUBDEV, sizeof(CRYPT_SUBDEV) - 1) ||
!strncmp(uuid, STRATIS, sizeof(STRATIS) - 1))) {
/* Skip private crypto devices */
log_debug_activation("%s: Reserved uuid %s on %s device %s not usable.",
dev_name(dev), uuid,
uuid[0] == 'C' ? "crypto" : "stratis",
name);
/* Check internal lvm devices */
if (check.check_reserved &&
uuid && !strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) {
if (strlen(uuid) > (sizeof(UUID_PREFIX) + 2 * ID_LEN)) { /* 68 */
log_debug_activation("%s: Reserved uuid %s on internal LV device %s not usable.",
dev_name(dev), uuid, name);
goto out;
}
if (!(vgname = strdup(name)) ||
!dm_split_lvm_name(NULL, NULL, &vgname, &lvname, &layer))
goto_out;
/* FIXME: fails to handle dev aliases i.e. /dev/dm-5, replace with UUID suffix */
if (lvname && (is_reserved_lvname(lvname) || *layer)) {
log_debug_activation("%s: Reserved internal LV device %s/%s%s%s not usable.",
dev_name(dev), vgname, lvname, *layer ? "-" : "", layer);
goto out;
}
}
if (check.check_lv && uuid && !strncmp(uuid, "LVM-", 4)) {
/* Skip LVs */
goto out;
}
if (check.check_reserved && uuid &&
(!strncmp(uuid, CRYPT_TEMP, sizeof(CRYPT_TEMP) - 1) ||
!strncmp(uuid, CRYPT_SUBDEV, sizeof(CRYPT_SUBDEV) - 1) ||
!strncmp(uuid, STRATIS, sizeof(STRATIS) - 1))) {
/* Skip private crypto devices */
log_debug_activation("%s: Reserved uuid %s on %s device %s not usable.",
dev_name(dev), uuid,
uuid[0] == 'C' ? "crypto" : "stratis",
name);
goto out;
}
/* FIXME Also check for mpath no paths */
@@ -768,15 +756,13 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check, i
goto out;
}
if (only_error_or_zero_target &&
strcmp(target_type, TARGET_NAME_ERROR) &&
strcmp(target_type, TARGET_NAME_ZERO))
only_error_or_zero_target = 0;
if (strcmp(target_type, TARGET_NAME_ERROR))
only_error_target = 0;
} while (next);
/* Skip devices consisting entirely of error or zero targets. */
/* Skip devices consisting entirely of error targets. */
/* FIXME Deal with device stacked above error targets? */
if (check.check_error_target && only_error_or_zero_target) {
if (check.check_error_target && only_error_target) {
log_debug_activation("%s: Error device %s not usable.",
dev_name(dev), name);
goto out;
@@ -787,6 +773,7 @@ int device_is_usable(struct device *dev, struct dev_usable_check_params check, i
r = 1;
out:
free(vgname);
dm_task_destroy(dmt);
return r;
}
@@ -838,12 +825,13 @@ static int _info(struct cmd_context *cmd,
return 1;
/* Check for original version of dlid before the suffixes got added in 2.02.106 */
if ((suffix_position = strrchr(dlid, '-'))) {
if ((suffix_position = rindex(dlid, '-'))) {
while ((suffix = uuid_suffix_list[i++])) {
if (strcmp(suffix_position + 1, suffix))
continue;
(void) dm_strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
(void) strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
old_style_dlid[sizeof(old_style_dlid) - 1] = '\0';
if (!_info_run(old_style_dlid, dminfo, read_ahead, seg_status,
name_check, with_open_count, with_read_ahead,
0, 0))
@@ -1125,8 +1113,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
const char *dlid,
const char *target_type, int wait,
const struct logical_volume *lv, dm_percent_t *overall_percent,
uint32_t *event_nr, int fail_if_percent_unsupported,
int *interrupted)
uint32_t *event_nr, int fail_if_percent_unsupported)
{
int r = 0;
struct dm_task *dmt;
@@ -1147,12 +1134,9 @@ static int _percent_run(struct dev_manager *dm, const char *name,
if (!(segtype = get_segtype_from_string(dm->cmd, target_type)))
return_0;
if (wait)
sigint_allow();
if (!(dmt = _setup_task_run(wait ? DM_DEVICE_WAITEVENT : DM_DEVICE_STATUS, &info,
name, dlid, event_nr, 0, 0, 0, 0, 0)))
goto_bad;
return_0;
if (!info.exists)
goto_out;
@@ -1220,19 +1204,8 @@ static int _percent_run(struct dev_manager *dm, const char *name,
display_percent(dm->cmd, *overall_percent));
r = 1;
out:
out:
dm_task_destroy(dmt);
bad:
if (wait) {
sigint_restore();
if (sigint_caught()) {
*interrupted = 1;
return_0;
}
}
return r;
}
@@ -1241,24 +1214,20 @@ static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
const struct logical_volume *lv, dm_percent_t *percent,
uint32_t *event_nr, int fail_if_percent_unsupported)
{
int interrupted = 0;
if (dlid && *dlid) {
if (_percent_run(dm, NULL, dlid, target_type, wait, lv, percent,
event_nr, fail_if_percent_unsupported, &interrupted))
event_nr, fail_if_percent_unsupported))
return 1;
if (!interrupted &&
_original_uuid_format_check_required(dm->cmd) &&
if (_original_uuid_format_check_required(dm->cmd) &&
_percent_run(dm, NULL, dlid + sizeof(UUID_PREFIX) - 1,
target_type, wait, lv, percent,
event_nr, fail_if_percent_unsupported, &interrupted))
event_nr, fail_if_percent_unsupported))
return 1;
}
if (!interrupted && name &&
_percent_run(dm, name, NULL, target_type, wait, lv, percent,
event_nr, fail_if_percent_unsupported, &interrupted))
if (name && _percent_run(dm, name, NULL, target_type, wait, lv, percent,
event_nr, fail_if_percent_unsupported))
return 1;
return_0;
@@ -1460,7 +1429,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
int dev_manager_raid_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_raid **status, int *exists)
struct dm_status_raid **status)
{
int r = 0;
const char *dlid;
@@ -1470,11 +1439,6 @@ int dev_manager_raid_status(struct dev_manager *dm,
char *type = NULL;
char *params = NULL;
const char *layer = lv_layer(lv);
struct dm_status_raid *sr;
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
return_0;
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
return_0;
@@ -1482,11 +1446,8 @@ int dev_manager_raid_status(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0)))
return_0;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking raid status for volume %s.",
display_lvname(lv));
if (!info.exists)
goto_out;
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
@@ -1498,13 +1459,9 @@ int dev_manager_raid_status(struct dev_manager *dm,
/* FIXME Check there's only one target */
if (!dm_get_status_raid(dm->mem, params, &sr))
if (!dm_get_status_raid(dm->mem, params, status))
goto_out;
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
(*status)->raid = sr;
(*status)->in_sync = dm_make_percent(sr->insync_regions, sr->total_regions);
r = 1;
out:
dm_task_destroy(dmt);
@@ -1593,7 +1550,7 @@ out:
int dev_manager_cache_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_cache **status, int *exists)
struct lv_status_cache **status)
{
int r = 0;
const char *dlid;
@@ -1604,18 +1561,17 @@ int dev_manager_cache_status(struct dev_manager *dm,
char *params = NULL;
struct dm_status_cache *c;
*exists = -1;
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
return_0;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
return_0;
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, 0, 0)))
return_0;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking status for cache volume %s.",
display_lvname(lv));
if (!info.exists)
goto_out;
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
@@ -1633,11 +1589,8 @@ int dev_manager_cache_status(struct dev_manager *dm,
if (!dm_get_status_cache(dm->mem, params, &c))
goto_out;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_cache))))
goto_out;
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
(*status)->cache = c;
(*status)->mem = dm->mem; /* User has to destroy this mem pool later */
if (c->fail || c->error) {
(*status)->data_usage =
(*status)->metadata_usage =
@@ -1659,10 +1612,10 @@ out:
}
int dev_manager_thin_pool_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **status, int *exists)
const struct logical_volume *lv,
struct dm_status_thin_pool **status,
int flush)
{
struct dm_status_thin_pool *dm_status;
const char *dlid;
struct dm_task *dmt;
struct dm_info info;
@@ -1671,10 +1624,6 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
char *params = NULL;
int r = 0;
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin_pool))))
return_0;
/* Build dlid for the thin pool layer */
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
return_0;
@@ -1682,36 +1631,16 @@ int dev_manager_thin_pool_status(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
return_0;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking thin pool status for LV %s.",
display_lvname(lv));
if (!info.exists)
goto_out;
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
if (!type || strcmp(type, TARGET_NAME_THIN_POOL)) {
log_error("Expected %s segment type but got %s instead.",
TARGET_NAME_THIN_POOL, type ? type : "NULL");
goto out;
}
/* FIXME Check for thin and check there's exactly one target */
if (!dm_get_status_thin_pool(dm->mem, params, &dm_status))
if (!dm_get_status_thin_pool(dm->mem, params, status))
goto_out;
(*status)->mem = dm->mem;
(*status)->thin_pool = dm_status;
if (dm_status->fail || dm_status->error) {
(*status)->data_usage =
(*status)->metadata_usage = DM_PERCENT_INVALID;
} else {
(*status)->data_usage = dm_make_percent(dm_status->used_data_blocks,
dm_status->total_data_blocks);
(*status)->metadata_usage = dm_make_percent(dm_status->used_metadata_blocks,
dm_status->total_metadata_blocks);
}
r = 1;
out:
dm_task_destroy(dmt);
@@ -1719,72 +1648,52 @@ out:
return r;
}
int dev_manager_thin_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_thin **status, int *exists)
int dev_manager_thin_pool_percent(struct dev_manager *dm,
const struct logical_volume *lv,
int metadata, dm_percent_t *percent)
{
struct dm_status_thin *dm_status;
char *name;
const char *dlid;
struct dm_task *dmt;
struct dm_info info;
uint64_t start, length;
char *type = NULL;
char *params = NULL;
uint64_t csize;
int r = 0;
const char *layer = lv_layer(lv);
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_thin))))
/* Build a name for the top layer */
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
return_0;
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
return_0;
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
log_debug_activation("Getting device status percentage for %s.", name);
if (!(_percent(dm, name, dlid, TARGET_NAME_THIN_POOL, 0,
(metadata) ? lv : NULL, percent, NULL, 1)))
return_0;
if (!(*exists = info.exists))
goto out;
return 1;
}
log_debug_activation("Checking thin status for LV %s.",
display_lvname(lv));
int dev_manager_thin_percent(struct dev_manager *dm,
const struct logical_volume *lv,
int mapped, dm_percent_t *percent)
{
char *name;
const char *dlid;
const char *layer = lv_layer(lv);
dm_get_next_target(dmt, NULL, &start, &length, &type, &params);
/* Build a name for the top layer */
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
return_0;
if (!type || strcmp(type, TARGET_NAME_THIN)) {
log_error("Expected %s segment type but got %s instead.",
TARGET_NAME_THIN, type ? type : "NULL");
goto out;
}
if (!(dlid = build_dm_uuid(dm->mem, lv, layer)))
return_0;
if (!dm_get_status_thin(dm->mem, params, &dm_status))
goto_out;
log_debug_activation("Getting device status percentage for %s", name);
(*status)->mem = dm->mem;
(*status)->thin = dm_status;
if (!(_percent(dm, name, dlid, TARGET_NAME_THIN, 0,
(mapped) ? NULL : lv, percent, NULL, 1)))
return_0;
if (dm_status->fail)
(*status)->usage = DM_PERCENT_INVALID;
else {
/* Pool allocates whole chunk so round-up to nearest one */
csize = first_seg(first_seg(lv)->pool_lv)->chunk_size;
csize = ((lv->size + csize - 1) / csize) * csize;
if (dm_status->mapped_sectors > csize) {
log_warn("WARNING: LV %s maps %s while the size is only %s.",
display_lvname(lv),
display_size(dm->cmd, dm_status->mapped_sectors),
display_size(dm->cmd, csize));
/* Don't show nonsense numbers like i.e. 1000% full */
dm_status->mapped_sectors = csize;
}
(*status)->usage = dm_make_percent(dm_status->mapped_sectors, csize);
}
r = 1;
out:
dm_task_destroy(dmt);
return r;
return 1;
}
/*
@@ -1792,7 +1701,7 @@ out:
*/
int dev_manager_thin_device_id(struct dev_manager *dm,
const struct logical_volume *lv,
uint32_t *device_id, int *exists)
uint32_t *device_id)
{
const char *dlid;
struct dm_task *dmt;
@@ -1802,7 +1711,6 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
const char *layer = lv_layer(lv);
int r = 0;
*exists = -1;
if (lv_is_merging_origin(lv) && !lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0))
/* If the merge has already happened, that table
* can already be using correct LV without -real layer */
@@ -1815,11 +1723,8 @@ int dev_manager_thin_device_id(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_TABLE, &info, NULL, dlid, 0, 0, 0, 0, 1, 0)))
return_0;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking device id for LV %s.",
display_lvname(lv));
if (!info.exists)
goto_out;
if (dm_get_next_target(dmt, NULL, &start, &length,
&target_type, &params)) {
@@ -1848,9 +1753,11 @@ out:
}
int dev_manager_vdo_pool_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_vdo **status, int *exists)
const struct logical_volume *lv,
struct lv_status_vdo **vdo_status,
int flush)
{
struct lv_status_vdo *status;
const char *dlid;
struct dm_info info;
uint64_t start, length;
@@ -1859,9 +1766,12 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
char *params = NULL;
int r = 0;
*exists = -1;
if (!(*status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_vdo))))
return_0;
*vdo_status = NULL;
if (!(status = dm_pool_zalloc(dm->mem, sizeof(struct lv_status_vdo)))) {
log_error("Cannot allocate VDO status structure.");
return 0;
}
if (!(dlid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
return_0;
@@ -1869,11 +1779,8 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
if (!(dmt = _setup_task_run(DM_DEVICE_STATUS, &info, NULL, dlid, 0, 0, 0, 0, flush, 0)))
return_0;
if (!(*exists = info.exists))
goto out;
log_debug_activation("Checking VDO pool status for LV %s.",
display_lvname(lv));
if (!info.exists)
goto_out;
if (dm_get_next_target(dmt, NULL, &start, &length, &type, &params)) {
log_error("More then one table line found for %s.",
@@ -1887,10 +1794,11 @@ int dev_manager_vdo_pool_status(struct dev_manager *dm,
goto out;
}
if (!parse_vdo_pool_status(dm->mem, lv, params, &info, *status))
if (!parse_vdo_pool_status(dm->mem, lv, params, status))
goto_out;
(*status)->mem = dm->mem;
status->mem = dm->mem;
*vdo_status = status;
r = 1;
out:
@@ -2119,7 +2027,7 @@ static int _check_holder(struct dev_manager *dm, struct dm_tree *dtree,
if (!strncmp(default_uuid_prefix, uuid, default_uuid_prefix_len))
uuid += default_uuid_prefix_len;
if (!memcmp(uuid, &lv->vg->id, ID_LEN) &&
if (!strncmp(uuid, (char*)&lv->vg->id, sizeof(lv->vg->id)) &&
!dm_tree_find_node_by_uuid(dtree, uuid)) {
/* trims any UUID suffix (i.e. -cow) */
(void) dm_strncpy((char*)&id, uuid, 2 * sizeof(struct id) + 1);
@@ -2326,31 +2234,21 @@ static int _pool_callback(struct dm_tree_node *node,
const struct pool_cb_data *data = cb_data;
const struct logical_volume *pool_lv = data->pool_lv;
const struct logical_volume *mlv = first_seg(pool_lv)->metadata_lv;
struct cmd_context *cmd = pool_lv->vg->cmd;
long buf[64 / sizeof(long)]; /* buffer for short disk header (64B) */
int args = 0;
char *mpath;
const char *argv[19] = { /* Max supported 15 args */
find_config_tree_str_allow_empty(cmd, data->exec, NULL)
find_config_tree_str_allow_empty(pool_lv->vg->cmd, data->exec, NULL)
};
if (!*argv[0]) /* *_check tool is unconfigured/disabled with "" setting */
return 1;
if (lv_is_cache_vol(pool_lv)) {
if (!(mpath = lv_dmpath_suffix_dup(data->dm->mem, pool_lv, "-cmeta"))) {
log_error("Failed to build device path for checking cachevol metadata %s.",
display_lvname(pool_lv));
return 0;
}
} else {
if (!(mpath = lv_dmpath_dup(data->dm->mem, mlv))) {
log_error("Failed to build device path for checking pool metadata %s.",
display_lvname(mlv));
return 0;
}
if (!(mpath = lv_dmpath_dup(data->dm->mem, mlv))) {
log_error("Failed to build device path for checking pool metadata %s.",
display_lvname(mlv));
return 0;
}
log_debug("Running check command on %s", mpath);
if (data->skip_zero) {
if ((fd = open(mpath, O_RDONLY)) < 0) {
@@ -2378,7 +2276,7 @@ static int _pool_callback(struct dm_tree_node *node,
}
}
if (!(cn = find_config_tree_array(cmd, data->opts, NULL))) {
if (!(cn = find_config_tree_array(mlv->vg->cmd, data->opts, NULL))) {
log_error(INTERNAL_ERROR "Unable to find configuration for pool check options.");
return 0;
}
@@ -2400,7 +2298,7 @@ static int _pool_callback(struct dm_tree_node *node,
argv[++args] = mpath;
if (!(ret = exec_cmd(cmd, (const char * const *)argv,
if (!(ret = exec_cmd(pool_lv->vg->cmd, (const char * const *)argv,
&status, 0))) {
if (status == ENOENT) {
log_warn("WARNING: Check is skipped, please install recommended missing binary %s!",
@@ -2409,7 +2307,7 @@ static int _pool_callback(struct dm_tree_node *node,
}
if ((data->version.maj || data->version.min || data->version.patch) &&
!_check_tool_version(cmd, argv[0],
!_check_tool_version(pool_lv->vg->cmd, argv[0],
data->version.maj, data->version.min, data->version.patch)) {
log_warn("WARNING: Check is skipped, please upgrade installed version of %s!",
argv[0]);
@@ -2453,6 +2351,10 @@ static int _pool_register_callback(struct dev_manager *dm,
return 1;
#endif
/* Skip for single-device cache pool */
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv))
return 1;
if (!(data = dm_pool_zalloc(dm->mem, sizeof(*data)))) {
log_error("Failed to allocated path for callback.");
return 0;
@@ -3545,12 +3447,6 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
!_pool_register_callback(dm, dnode, lv))
return_0;
if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv) &&
/* Register callback only for layer activation or non-layered cache LV */
(layer || !lv_layer(lv)) &&
!_pool_register_callback(dm, dnode, lv))
return_0;
/*
* Update tables for ANY PVMOVE holders for active LV where the name starts with 'pvmove',
* but it's not anymore PVMOVE LV and also it's not a PVMOVE _mimage LV.

View File

@@ -59,7 +59,7 @@ int dev_manager_mirror_percent(struct dev_manager *dm,
dm_percent_t *percent, uint32_t *event_nr);
int dev_manager_raid_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_raid **status, int *exists);
struct dm_status_raid **status);
int dev_manager_raid_message(struct dev_manager *dm,
const struct logical_volume *lv,
const char *msg);
@@ -68,19 +68,24 @@ int dev_manager_writecache_message(struct dev_manager *dm,
const char *msg);
int dev_manager_cache_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct lv_status_cache **status, int *exists);
int dev_manager_thin_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_thin **status, int *exists);
struct lv_status_cache **status);
int dev_manager_thin_pool_status(struct dev_manager *dm,
const struct logical_volume *lv,
struct dm_status_thin_pool **status,
int flush);
int dev_manager_thin_pool_percent(struct dev_manager *dm,
const struct logical_volume *lv,
int metadata, dm_percent_t *percent);
int dev_manager_thin_percent(struct dev_manager *dm,
const struct logical_volume *lv,
int mapped, dm_percent_t *percent);
int dev_manager_thin_device_id(struct dev_manager *dm,
const struct logical_volume *lv,
uint32_t *device_id, int *exist);
int dev_manager_thin_pool_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_thin_pool **status, int *exists);
uint32_t *device_id);
int dev_manager_vdo_pool_status(struct dev_manager *dm,
const struct logical_volume *lv, int flush,
struct lv_status_vdo **status, int *exists);
const struct logical_volume *lv,
struct lv_status_vdo **vdo_status,
int flush);
int dev_manager_suspend(struct dev_manager *dm, const struct logical_volume *lv,
struct lv_activate_opts *laopts, int lockfs, int flush_required);
int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv,

View File

@@ -76,7 +76,7 @@ static int _rm_dir(const char *dev_dir, const char *vg_name)
return 0;
}
if (dir_exists(vg_path) && dm_is_empty_dir(vg_path)) {
if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
log_very_verbose("Removing directory %s", vg_path);
rmdir(vg_path);
}
@@ -93,7 +93,7 @@ static void _rm_blks(const char *dir)
DIR *d;
if (!(d = opendir(dir))) {
log_sys_debug("opendir", dir);
log_sys_error("opendir", dir);
return;
}
@@ -104,7 +104,7 @@ static void _rm_blks(const char *dir)
continue;
if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
log_debug("Couldn't create path for %s.", name);
log_error("Couldn't create path for %s", name);
continue;
}
@@ -113,12 +113,12 @@ static void _rm_blks(const char *dir)
continue;
log_very_verbose("Removing %s", path);
if (unlink(path) < 0)
log_sys_debug("unlink", path);
log_sys_error("unlink", path);
}
}
if (closedir(d))
log_sys_debug("closedir", dir);
log_sys_error("closedir", dir);
}
static int _mk_link(const char *dev_dir, const char *vg_name,
@@ -169,7 +169,7 @@ static int _mk_link(const char *dev_dir, const char *vg_name,
log_very_verbose("Removing %s", lvm1_group_path);
if (unlink(lvm1_group_path) < 0)
log_sys_debug("unlink", lvm1_group_path);
log_sys_error("unlink", lvm1_group_path);
}
}

576
lib/cache/lvmcache.c vendored

File diff suppressed because it is too large Load Diff

19
lib/cache/lvmcache.h vendored
View File

@@ -47,7 +47,7 @@ struct lvmcache_vginfo;
*/
struct lvmcache_vgsummary {
const char *vgname;
char vgid[ID_LEN + 1];
struct id vgid;
uint64_t vgstatus;
char *creation_host;
const char *system_id;
@@ -69,7 +69,6 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset);
int lvmcache_label_scan(struct cmd_context *cmd);
int lvmcache_label_rescan_vg(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_label_rescan_vg_rw(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_label_reopen_vg_rw(struct cmd_context *cmd, const char *vgname, const char *vgid);
/* Add/delete a device */
struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *labeller, const char *pvid,
@@ -96,10 +95,9 @@ struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *dev, int valid_only);
struct lvmcache_info *lvmcache_info_from_pv_id(const struct id *pv_id, struct device *dev, int valid_only);
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgname);
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pv_id, uint64_t *label_sector);
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
@@ -182,7 +180,7 @@ int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const ch
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);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid);
uint64_t lvmcache_max_metadata_size(void);
void lvmcache_save_metadata_size(uint64_t val);
@@ -210,8 +208,6 @@ void lvmcache_del_outdated_devs(struct cmd_context *cmd,
void lvmcache_save_bad_mda(struct lvmcache_info *info, struct metadata_area *mda);
void lvmcache_del_save_bad_mda(struct lvmcache_info *info, int mda_num, int bad_mda_flag);
void lvmcache_get_bad_mdas(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct dm_list *bad_mda_list);
@@ -220,13 +216,4 @@ void lvmcache_get_mdas(struct cmd_context *cmd,
const char *vgname, const char *vgid,
struct dm_list *mda_list);
const char *dev_filtered_reason(struct device *dev);
const char *devname_error_reason(const char *devname);
struct metadata_area *lvmcache_get_dev_mda(struct device *dev, int mda_num);
void lvmcache_extra_md_component_checks(struct cmd_context *cmd);
unsigned int lvmcache_vg_info_count(void);
#endif

View File

@@ -335,7 +335,7 @@ static int _lookup_kallsyms(const char *symbol)
static int _target_present(struct cmd_context *cmd,
const struct lv_segment *seg __attribute__((unused)),
unsigned *attributes)
unsigned *attributes __attribute__((unused)))
{
/* List of features with their kernel target version */
static const struct feature {
@@ -618,9 +618,6 @@ static int _cache_add_target_line(struct dev_manager *dm,
{
struct lv_segment *cache_pool_seg;
struct lv_segment *setting_seg;
struct dm_config_node *policy_settings;
struct dm_config_node *cn;
unsigned i, j;
union lvid metadata_lvid;
union lvid data_lvid;
char *metadata_uuid, *data_uuid, *origin_uuid;
@@ -721,61 +718,6 @@ static int _cache_add_target_line(struct dev_manager *dm,
return_0;
}
policy_settings = seg->cleaner_policy ? NULL : setting_seg->policy_settings;
if (policy_settings && cache_pool_seg->policy_name) {
static const struct act {
const char *name;
const char *settings[20];
} _accepted[] = {
{
"MQ", {
"migration_threshold", "sequential_threshold", "random_threshold",
"read_promote_adjustment", "write_promote_adjustment",
"discard_promote_adjustment", NULL
},
}, {
"SMQ", {
"migration_threshold", NULL
}
}
};
/* Check if cache settings are acceptable to knownm policies */
for (i = 0; i < DM_ARRAY_SIZE(_accepted); i++) {
if (strcasecmp(cache_pool_seg->policy_name, _accepted[i].name))
continue;
for (cn = policy_settings->child; cn; cn = cn->sib) {
for (j = 0; _accepted[i].settings[j]; j++)
if (strcmp(cn->key, _accepted[i].settings[j]) == 0)
break; /* -> Valid setting */
/* Have we found 'unsupported' cache setting? */
if (!_accepted[i].settings[j]) {
/* Make a copy of policy settings a remove unsupported settings and Warn */
if (!(policy_settings = dm_config_clone_node_with_mem(mem, policy_settings, 0)))
return_0;
restart:
for (cn = policy_settings->child; cn; cn = cn->sib) {
for (j = 0; _accepted[i].settings[j]; j++) {
if (strcmp(cn->key, _accepted[i].settings[j]) == 0)
break; /* need to be dropped */
}
if (!_accepted[i].settings[j]) {
log_warn("WARNING: %s cache policy does not support \"%s=" FMTu64 "\" setting, "
"remove with 'lvchange --cachesettings \"%s=default\" ...'.",
_accepted[i].name, cn->key, cn->v->v.i, cn->key);
dm_config_remove_node(policy_settings, cn);
goto restart;
}
}
break;
}
}
break;
}
}
if (!dm_tree_node_add_cache_target(node, len,
feature_flags,
metadata_uuid,
@@ -784,7 +726,7 @@ static int _cache_add_target_line(struct dev_manager *dm,
seg->cleaner_policy ? "cleaner" :
/* undefined policy name -> likely an old "mq" */
cache_pool_seg->policy_name ? : "mq",
policy_settings,
seg->cleaner_policy ? NULL : setting_seg->policy_settings,
seg->metadata_start,
seg->metadata_len,
seg->data_start,

View File

@@ -32,7 +32,6 @@
#include "lib/cache/lvmcache.h"
#include "lib/format_text/archiver.h"
#include "lib/lvmpolld/lvmpolld-client.h"
#include "lib/device/device_id.h"
#include <locale.h>
#include <sys/stat.h>
@@ -41,10 +40,6 @@
#include <syslog.h>
#include <time.h>
#ifdef APP_MACHINEID_SUPPORT
#include <systemd/sd-id128.h>
#endif
#ifdef __linux__
# include <malloc.h>
#endif
@@ -133,12 +128,9 @@ static const char *_read_system_id_from_file(struct cmd_context *cmd, const char
return system_id;
}
/* systemd-id128 new produced: f64406832c2140e8ac5422d1089aae03 */
#define LVM_APPLICATION_ID SD_ID128_MAKE(f6,44,06,83,2c,21,40,e8,ac,54,22,d1,08,9a,ae,03)
static const char *_system_id_from_source(struct cmd_context *cmd, const char *source)
{
char buf[PATH_MAX];
char filebuf[PATH_MAX];
const char *file;
const char *etc_str;
const char *str;
@@ -157,23 +149,10 @@ static const char *_system_id_from_source(struct cmd_context *cmd, const char *s
goto out;
}
#ifdef APP_MACHINEID_SUPPORT
if (!strcasecmp(source, "appmachineid")) {
sd_id128_t id;
sd_id128_get_machine_app_specific(LVM_APPLICATION_ID, &id);
if (dm_snprintf(buf, PATH_MAX, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)) < 0)
stack;
system_id = system_id_from_string(cmd, buf);
goto out;
}
#endif
if (!strcasecmp(source, "machineid") || !strcasecmp(source, "machine-id")) {
etc_str = find_config_tree_str(cmd, global_etc_CFG, NULL);
if (dm_snprintf(buf, sizeof(buf), "%s/machine-id", etc_str) != -1)
system_id = _read_system_id_from_file(cmd, buf);
if (dm_snprintf(filebuf, sizeof(filebuf), "%s/machine-id", etc_str) != -1)
system_id = _read_system_id_from_file(cmd, filebuf);
goto out;
}
@@ -250,7 +229,7 @@ static void _get_sysfs_dir(struct cmd_context *cmd, char *buf, size_t buf_size)
return;
}
(void) dm_strncpy(buf, sys_mnt, buf_size);
strncpy(buf, sys_mnt, buf_size);
}
static uint32_t _parse_debug_fields(struct cmd_context *cmd, int cfg, const char *cfgname)
@@ -340,33 +319,6 @@ static int _parse_debug_classes(struct cmd_context *cmd)
return debug_classes;
}
static uint32_t _parse_log_journal(struct cmd_context *cmd, int cfg, const char *cfgname)
{
const struct dm_config_node *cn;
const struct dm_config_value *cv;
uint32_t fields = 0;
uint32_t val;
if (!(cn = find_config_tree_array(cmd, cfg, NULL))) {
log_debug("Unable to find configuration for log/%s.", cfgname);
return 0;
}
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != DM_CFG_STRING) {
log_verbose("log/%s contains a value which is not a string. Ignoring.", cfgname);
continue;
}
if ((val = log_journal_str_to_val(cv->v.str)))
fields |= val;
else
log_verbose("Unrecognised value for log/%s: %s", cfgname, cv->v.str);
}
return fields;
}
static void _init_logging(struct cmd_context *cmd)
{
int append = 1;
@@ -377,11 +329,12 @@ static void _init_logging(struct cmd_context *cmd)
/* Syslog */
cmd->default_settings.syslog = find_config_tree_bool(cmd, log_syslog_CFG, NULL);
if (cmd->default_settings.syslog)
init_syslog(1, DEFAULT_LOG_FACILITY);
else
if (cmd->default_settings.syslog != 1)
fin_syslog();
if (cmd->default_settings.syslog > 1)
init_syslog(cmd->default_settings.syslog);
/* Debug level for log file output */
cmd->default_settings.debug = find_config_tree_int(cmd, log_level_CFG, NULL);
init_debug(cmd->default_settings.debug);
@@ -434,9 +387,6 @@ static void _init_logging(struct cmd_context *cmd)
init_debug_file_fields(_parse_debug_fields(cmd, log_debug_file_fields_CFG, "debug_file_fields"));
init_debug_output_fields(_parse_debug_fields(cmd, log_debug_output_fields_CFG, "debug_output_fields"));
cmd->default_settings.journal = _parse_log_journal(cmd, log_journal_CFG, "journal");
init_log_journal(cmd->default_settings.journal);
t = time(NULL);
ctime_r(&t, &timebuf[0]);
timebuf[24] = '\0';
@@ -451,12 +401,15 @@ static void _init_logging(struct cmd_context *cmd)
reset_lvm_errno(1);
}
static int _check_disable_udev(const char *msg)
{
static int _check_disable_udev(const char *msg) {
if (getenv("DM_DISABLE_UDEV")) {
log_very_verbose("DM_DISABLE_UDEV environment variable set.");
log_very_verbose("Overriding configuration to use udev_rules=0, udev_sync=0, verify_udev_operations=1.");
log_very_verbose("LVM will %s.", msg);
log_very_verbose("DM_DISABLE_UDEV environment variable set. "
"Overriding configuration to use "
"udev_rules=0, udev_sync=0, verify_udev_operations=1.");
if (udev_is_running())
log_warn("Udev is running and DM_DISABLE_UDEV environment variable is set. "
"Bypassing udev, LVM will %s.", msg);
return 1;
}
@@ -609,7 +562,7 @@ static int _init_system_id(struct cmd_context *cmd)
static int _process_config(struct cmd_context *cmd)
{
mode_t old_umask;
const char *dev_ext_info_src = NULL;
const char *dev_ext_info_src;
const char *read_ahead;
struct stat st;
const struct dm_config_node *cn;
@@ -643,25 +596,14 @@ static int _process_config(struct cmd_context *cmd)
#endif
dev_ext_info_src = find_config_tree_str(cmd, devices_external_device_info_source_CFG, NULL);
if (dev_ext_info_src &&
strcmp(dev_ext_info_src, "none") &&
strcmp(dev_ext_info_src, "udev")) {
log_warn("WARNING: unknown external device info source, using none.");
dev_ext_info_src = NULL;
}
if (dev_ext_info_src && !strcmp(dev_ext_info_src, "udev")) {
if (udev_init_library_context()) {
init_external_device_info_source(DEV_EXT_UDEV);
} else {
log_warn("WARNING: failed to init udev for external device info, using none.");
dev_ext_info_src = NULL;
}
}
if (!dev_ext_info_src || !strcmp(dev_ext_info_src, "none"))
if (dev_ext_info_src && !strcmp(dev_ext_info_src, "none"))
init_external_device_info_source(DEV_EXT_NONE);
else if (dev_ext_info_src && !strcmp(dev_ext_info_src, "udev"))
init_external_device_info_source(DEV_EXT_UDEV);
else {
log_error("Invalid external device info source specification.");
return 0;
}
/* proc dir */
if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
@@ -718,8 +660,6 @@ static int _process_config(struct cmd_context *cmd)
*/
cmd->default_settings.udev_fallback = udev_disabled ? 1 : -1;
cmd->default_settings.issue_discards = find_config_tree_bool(cmd, devices_issue_discards_CFG, NULL);
init_retry_deactivation(find_config_tree_bool(cmd, activation_retry_deactivation_CFG, NULL));
init_activation_checks(find_config_tree_bool(cmd, activation_checks_CFG, NULL));
@@ -765,7 +705,6 @@ static int _process_config(struct cmd_context *cmd)
init_pv_min_size((uint64_t)pv_min_kb * (1024 >> SECTOR_SHIFT));
cmd->check_pv_dev_sizes = find_config_tree_bool(cmd, metadata_check_pv_device_sizes_CFG, NULL);
cmd->event_activation = find_config_tree_bool(cmd, global_event_activation_CFG, NULL);
if (!process_profilable_config(cmd))
return_0;
@@ -1024,13 +963,8 @@ static void _destroy_config(struct cmd_context *cmd)
/* CONFIG_FILE/CONFIG_MERGED_FILES */
if ((cft = remove_config_tree_by_source(cmd, CONFIG_MERGED_FILES)))
config_destroy(cft);
else if ((cft = remove_config_tree_by_source(cmd, CONFIG_FILE))) {
dm_list_iterate_items(cfl, &cmd->config_files) {
if (cfl->cft == cft)
dm_list_del(&cfl->list);
}
config_destroy(cft);
}
else
remove_config_tree_by_source(cmd, CONFIG_FILE);
dm_list_iterate_items(cfl, &cmd->config_files)
config_destroy(cfl->cft);
@@ -1076,10 +1010,16 @@ static int _init_dev_cache(struct cmd_context *cmd)
if (!dev_cache_init(cmd))
return_0;
if ((device_list_from_udev = find_config_tree_bool(cmd, devices_obtain_device_list_from_udev_CFG, NULL))) {
if (!udev_init_library_context())
device_list_from_udev = 0;
}
/*
* Override existing config and hardcode device_list_from_udev = 0 if:
* - udev is not running
* - udev is disabled using DM_DISABLE_UDEV environment variable
*/
if (_check_disable_udev("obtain device list by scanning device directory"))
device_list_from_udev = 0;
else
device_list_from_udev = udev_is_running() ?
find_config_tree_bool(cmd, devices_obtain_device_list_from_udev_CFG, NULL) : 0;
init_obtain_device_list_from_udev(device_list_from_udev);
@@ -1126,6 +1066,13 @@ static int _init_dev_cache(struct cmd_context *cmd)
return 1;
}
static int _init_device_ids(struct cmd_context *cmd)
{
dm_list_init(&cmd->use_device_ids);
cmd->devices_file = find_config_tree_str(cmd, devices_devicesfile_CFG, NULL);
return 1;
}
#define MAX_FILTERS 11
static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
@@ -1163,7 +1110,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
/* global regex filter. Optional. */
if ((cn = find_config_tree_node(cmd, devices_global_filter_CFG, NULL))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v, 0, 1))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
log_error("Failed to create global regex device filter");
goto bad;
}
@@ -1172,7 +1119,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
/* regex filter. Optional. */
if ((cn = find_config_tree_node(cmd, devices_filter_CFG, NULL))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v, 1, 0))) {
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
log_error("Failed to create regex device filter");
goto bad;
}
@@ -1186,7 +1133,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
}
nr_filt++;
/* filter based on the device_ids saved in the devices file */
/* filter based on the device_ids saved in the lvm_devices file */
if (!(filters[nr_filt] = deviceid_filter_create(cmd))) {
log_error("Failed to create deviceid device filter");
goto bad;
@@ -1234,7 +1181,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
nr_filt++;
}
if (!(composite = composite_filter_create(nr_filt, filters)))
if (!(composite = composite_filter_create(nr_filt, 1, filters)))
goto_bad;
return composite;
@@ -1555,7 +1502,6 @@ int init_run_by_dmeventd(struct cmd_context *cmd)
init_dmeventd_monitor(DMEVENTD_MONITOR_IGNORE);
init_ignore_suspended_devices(1);
init_disable_dmeventd_monitoring(1); /* Lock settings */
cmd->run_by_dmeventd = 1;
return 0;
}
@@ -1653,6 +1599,8 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
bindtextdomain(INTL_PACKAGE, LOCALEDIR);
#endif
init_syslog(DEFAULT_LOG_FACILITY);
if (!(cmd = zalloc(sizeof(*cmd)))) {
log_error("Failed to allocate command context");
return NULL;
@@ -1663,7 +1611,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
cmd->handles_missing_pvs = 0;
cmd->handles_unknown_segments = 0;
cmd->hosttags = 0;
cmd->check_devs_used = 1;
dm_list_init(&cmd->arg_value_groups);
dm_list_init(&cmd->formats);
dm_list_init(&cmd->segtypes);
@@ -1787,7 +1734,8 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
if (!_init_dev_cache(cmd))
goto_out;
devices_file_init(cmd);
if (!_init_device_ids(cmd))
return_0;
memlock_init(cmd);
@@ -1914,7 +1862,6 @@ int refresh_toolcontext(struct cmd_context *cmd)
_destroy_segtypes(&cmd->segtypes);
_destroy_formats(cmd, &cmd->formats);
devices_file_exit(cmd);
if (!dev_cache_exit())
stack;
_destroy_dev_types(cmd);
@@ -1994,7 +1941,8 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_dev_cache(cmd))
return_0;
devices_file_init(cmd);
if (!_init_device_ids(cmd))
return_0;
if (!_init_formats(cmd))
return_0;
@@ -2045,7 +1993,6 @@ void destroy_toolcontext(struct cmd_context *cmd)
_destroy_filters(cmd);
if (cmd->mem)
dm_pool_destroy(cmd->mem);
devices_file_exit(cmd);
dev_cache_exit();
_destroy_dev_types(cmd);
_destroy_tags(cmd);

View File

@@ -29,9 +29,7 @@ struct config_info {
int debug_classes;
int verbose;
int silent;
int suppress;
int test;
int yes;
int syslog;
int activation;
int suffix;
@@ -41,8 +39,7 @@ struct config_info {
int udev_rules;
int udev_sync;
int udev_fallback;
int issue_discards;
uint32_t journal;
int cache_vgmetadata;
const char *msg_prefix;
const char *fmt_name;
const char *dmeventd_executable;
@@ -183,36 +180,18 @@ struct cmd_context {
unsigned enable_hints:1; /* hints are enabled for cmds in general */
unsigned use_hints:1; /* if hints are enabled this cmd can use them */
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
unsigned hints_pvs_online:1; /* hints="pvs_online" */
unsigned scan_lvs:1;
unsigned wipe_outdated_pvs:1;
unsigned enable_devices_list:1; /* command is using --devices option */
unsigned enable_devices_file:1; /* command is using devices file */
unsigned pending_devices_file:1; /* command may create and enable devices file */
unsigned create_edit_devices_file:1; /* command expects to create and/or edit devices file */
unsigned edit_devices_file:1; /* command expects to edit devices file */
unsigned filter_deviceid_skip:1; /* don't use filter-deviceid */
unsigned filter_regex_with_devices_file:1; /* use filter-regex even when devices file is enabled */
unsigned filter_nodata_only:1; /* only use filters that do not require data from the dev */
unsigned run_by_dmeventd:1; /* command is being run by dmeventd */
unsigned sysinit:1; /* --sysinit is used */
unsigned ignorelockingfailure:1; /* --ignorelockingfailure is used */
unsigned check_devs_used:1; /* check devs used by LVs */
unsigned print_device_id_not_found:1; /* print devices file entries not found */
unsigned ignore_device_name_mismatch:1; /* skip updating devices file names */
unsigned backup_disabled:1; /* skip repeated debug message */
unsigned event_activation:1; /* whether event_activation is set */
unsigned enable_device_ids:1;
/*
* Devices and filtering.
*/
struct dev_filter *filter;
struct dm_list hints;
struct dm_list use_devices; /* struct dev_use for each entry in devices file */
struct dm_list use_device_ids;
const char *md_component_checks;
const char *search_for_devnames; /* config file setting */
const char *devicesfile; /* from --devicesfile option */
struct dm_list deviceslist; /* from --devices option, struct dm_str_list */
const char *devices_file;
/*
* Configuration.
@@ -244,7 +223,6 @@ struct cmd_context {
char system_dir[PATH_MAX];
char dev_dir[PATH_MAX];
char proc_dir[PATH_MAX];
char devices_file_path[PATH_MAX];
/*
* Reporting.

View File

@@ -501,15 +501,12 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
checksum_fn_t checksum_fn, uint32_t checksum,
int checksum_only, int no_dup_node_check)
{
char namebuf[NAME_LEN + 1] __attribute__((aligned(8)));
int namelen = 0;
int bad_name = 0;
char *fb, *fe;
int r = 0;
int sz, use_plain_read = 1;
int use_mmap = 1;
off_t mmap_offset = 0;
char *buf = NULL;
struct config_source *cs = dm_config_get_custom(cft);
size_t rsize;
if (!_is_file_based_config_source(cs->type)) {
log_error(INTERNAL_ERROR "config_file_read_fd: expected file, special file "
@@ -518,28 +515,26 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
return 0;
}
/* Only use plain read with regular files */
/* Only use mmap with regular files */
if (!(dev->flags & DEV_REGULAR) || size2)
use_plain_read = 0;
use_mmap = 0;
if (!(buf = zalloc(size + size2))) {
log_error("Failed to allocate circular buffer.");
return 0;
}
if (use_plain_read) {
/* Note: also used for lvm.conf to read all settings */
for (rsize = 0; rsize < size; rsize += sz) {
do {
sz = read(dev_fd(dev), buf + rsize, size - rsize);
} while ((sz < 0) && ((errno == EINTR) || (errno == EAGAIN)));
if (sz < 0) {
log_sys_error("read", dev_name(dev));
goto out;
}
if (use_mmap) {
mmap_offset = offset % lvm_getpagesize();
/* memory map the file */
fb = mmap((caddr_t) 0, size + mmap_offset, PROT_READ,
MAP_PRIVATE, dev_fd(dev), offset - mmap_offset);
if (fb == (caddr_t) (-1)) {
log_sys_error("mmap", dev_name(dev));
goto out;
}
fb = fb + mmap_offset;
} else {
if (!(buf = malloc(size + size2))) {
log_error("Failed to allocate circular buffer.");
return 0;
}
if (!dev_read_bytes(dev, offset, size, buf))
goto out;
@@ -547,25 +542,8 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
if (!dev_read_bytes(dev, offset2, size2, buf + size))
goto out;
}
}
fb = buf;
if (!(dev->flags & DEV_REGULAR)) {
memcpy(namebuf, buf, NAME_LEN);
while (namebuf[namelen] && !isspace(namebuf[namelen]) && namebuf[namelen] != '{' && namelen < (NAME_LEN - 1))
namelen++;
namebuf[namelen] = '\0';
/*
* Check that the text metadata begins with a valid name.
*/
if (!validate_name(namebuf)) {
log_warn("WARNING: Metadata location on %s at offset %llu begins with invalid name.",
dev_name(dev), (unsigned long long)offset);
bad_name = 1;
}
fb = buf;
}
/*
@@ -577,13 +555,10 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
if (checksum_fn && checksum !=
(checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size),
(const uint8_t *)(fb + size), size2))) {
log_warn("WARNING: Checksum error on %s at offset %llu.", dev_name(dev), (unsigned long long)offset);
log_error("%s: Checksum error at offset %" PRIu64, dev_name(dev), (uint64_t) offset);
goto out;
}
if (bad_name)
goto out;
if (!checksum_only) {
fe = fb + size + size2;
if (no_dup_node_check) {
@@ -598,7 +573,15 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
r = 1;
out:
free(buf);
if (!use_mmap)
free(buf);
else {
/* unmap the file */
if (munmap(fb - mmap_offset, size + mmap_offset)) {
log_sys_error("munmap", dev_name(dev));
r = 0;
}
}
return r;
}
@@ -733,7 +716,7 @@ static struct dm_config_value *_get_def_array_values(struct cmd_context *cmd,
return array;
}
if (!(token = enc_value = strdup(def_enc_value))) {
if (!(p = token = enc_value = strdup(def_enc_value))) {
log_error("_get_def_array_values: strdup failed");
return NULL;
}
@@ -932,7 +915,7 @@ static int _check_value_differs_from_default(struct cft_check_handle *handle,
} else {
str = v_def ? v_def->v.str
: cfg_def_get_default_value(handle->cmd, def, CFG_TYPE_STRING, NULL);
diff = str ? strcmp(str, v->v.str) : 0;
diff = strcmp(str, v->v.str);
}
break;
case DM_CFG_EMPTY_ARRAY:
@@ -1164,10 +1147,8 @@ int config_def_check(struct cft_check_handle *handle)
* sections and settings with full path as a key.
* If section name is variable, use '#' as a substitute.
*/
*vp = 0;
*rp = 0;
if (!handle->cmd->cft_def_hash) {
if (!(handle->cmd->cft_def_hash = dm_hash_create(60))) {
if (!(handle->cmd->cft_def_hash = dm_hash_create(64))) {
log_error("Failed to create configuration definition hash.");
r = 0; goto out;
}
@@ -1733,7 +1714,6 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
const char *node_type_name = cn->v ? "option" : "section";
char path[CFG_PATH_MAX_LEN];
char commentline[MAX_COMMENT_LINE+1];
int is_deprecated = 0;
if (cn->id <= 0)
return 1;
@@ -1747,14 +1727,13 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
cfg_def = cfg_def_get_item_p(cn->id);
is_deprecated = _def_node_is_deprecated(cfg_def, out->tree_spec);
if (out->tree_spec->withsummary || out->tree_spec->withcomments) {
_cfg_def_make_path(path, sizeof(path), cfg_def->id, cfg_def, 1);
fprintf(out->fp, "\n");
fprintf(out->fp, "%s# Configuration %s %s.\n", line, node_type_name, path);
if (out->tree_spec->withcomments && is_deprecated && cfg_def->deprecation_comment)
if (out->tree_spec->withcomments &&
_def_node_is_deprecated(cfg_def, out->tree_spec))
fprintf(out->fp, "%s# %s", line, cfg_def->deprecation_comment);
if (cfg_def->comment) {
@@ -1765,14 +1744,14 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
continue;
commentline[0] = '\0';
}
fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
fprintf(out->fp, "%s# %s\n", line, commentline);
/* withsummary prints only the first comment line. */
if (!out->tree_spec->withcomments)
break;
}
}
if (is_deprecated)
if (_def_node_is_deprecated(cfg_def, out->tree_spec))
fprintf(out->fp, "%s# This configuration %s is deprecated.\n", line, node_type_name);
if (cfg_def->flags & CFG_ADVANCED)
@@ -1800,7 +1779,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
return_0;
fprintf(out->fp, "%s# Available since version %s.\n", line, version);
if (is_deprecated) {
if (_def_node_is_deprecated(cfg_def, out->tree_spec)) {
if (!_get_config_node_version(cfg_def->deprecated_since_version, version))
return_0;
fprintf(out->fp, "%s# Deprecated since version %s.\n", line, version);

View File

@@ -205,7 +205,7 @@ cfg_section(local_CFG_SECTION, "local", root_CFG_SECTION, 0, vsn(2, 2, 117), 0,
"# Please take care that each setting only appears once if uncommenting\n" \
"# example settings in this file and never copy this file between hosts.\n\n"
cfg(config_checks_CFG, "checks", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 2, 99), NULL, 0, NULL,
cfg(config_checks_CFG, "checks", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 99), NULL, 0, NULL,
"If enabled, any LVM configuration mismatch is reported.\n"
"This implies checking that the configuration key is understood by\n"
"LVM and that the value of the key is the proper type. If disabled,\n"
@@ -213,22 +213,22 @@ cfg(config_checks_CFG, "checks", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
"without any warning (a message about the configuration key not being\n"
"found is issued in verbose mode only).\n")
cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2,2,99), NULL, 0, NULL,
cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2,2,99), NULL, 0, NULL,
"Abort the LVM process if a configuration mismatch is found.\n")
cfg_runtime(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, vsn(2, 2, 99), 0, NULL,
cfg_runtime(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, CFG_DISALLOW_INTERACTIVE, CFG_TYPE_STRING, vsn(2, 2, 99), 0, NULL,
"Directory where LVM looks for configuration profiles.\n")
cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL, 0, NULL,
cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL, 0, NULL,
"Directory in which to create volume group device nodes.\n"
"Commands also accept this as a prefix on volume group names.\n")
cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL,
cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL, 0, NULL,
"Directories containing device nodes to use with LVM.\n")
cfg_array(devices_loopfiles_CFG, "loopfiles", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 2, 0), NULL, vsn(2, 3, 0), NULL, NULL)
cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV, vsn(2, 2, 85), NULL, 0, NULL,
cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV, vsn(2, 2, 85), NULL, 0, NULL,
"Obtain the list of available devices from udev.\n"
"This avoids opening or using any inapplicable non-block devices or\n"
"subdirectories found in the udev directory. Any device node or\n"
@@ -237,11 +237,23 @@ cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", de
"directories will be scanned fully. LVM needs to be compiled with\n"
"udev support for this setting to apply.\n")
cfg(devices_external_device_info_source_CFG, "external_device_info_source", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE, vsn(2, 2, 116), NULL, 0, NULL,
"Enable device information from udev.\n"
"If set to \"udev\", lvm will supplement its own native device information\n"
"with information from libudev. This can potentially improve the detection\n"
"of MD component devices and multipath component devices.\n")
cfg(devices_external_device_info_source_CFG, "external_device_info_source", devices_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE, vsn(2, 2, 116), NULL, 0, NULL,
"Select an external device information source.\n"
"Some information may already be available in the system and LVM can\n"
"use this information to determine the exact type or use of devices it\n"
"processes. Using an existing external device information source can\n"
"speed up device processing as LVM does not need to run its own native\n"
"routines to acquire this information. For example, this information\n"
"is used to drive LVM filtering like MD component detection, multipath\n"
"component detection, partition detection and others.\n"
"#\n"
"Accepted values:\n"
" none\n"
" No external device information source is used.\n"
" udev\n"
" Reuse existing udev database records. Applicable only if LVM is\n"
" compiled with udev support.\n"
"#\n")
cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_HINTS, vsn(2, 3, 2), NULL, 0, NULL,
"Use a local file to remember which devices have PVs on them.\n"
@@ -276,31 +288,8 @@ cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, C
"preferred_names = [ \"^/dev/mpath/\", \"^/dev/mapper/mpath\", \"^/dev/[hs]d\" ]\n"
"#\n")
cfg(devices_use_devicesfile_CFG, "use_devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_DEVICES_FILE, vsn(2, 3, 12), NULL, 0, NULL,
"Enable or disable the use of a devices file.\n"
"When enabled, lvm will only use devices that\n"
"are lised in the devices file. A devices file will\n"
"be used, regardless of this setting, when the --devicesfile\n"
"option is set to a specific file name.\n")
cfg(devices_devicesfile_CFG, "devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DEVICES_FILE, vsn(2, 3, 12), NULL, 0, NULL,
"The name of the system devices file, listing devices that LVM should use.\n"
"This should not be used to select a non-system devices file.\n"
"The --devicesfile option is intended for alternative devices files.\n")
cfg(devices_search_for_devnames_CFG, "search_for_devnames", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SEARCH_FOR_DEVNAMES, vsn(2, 3, 12), NULL, 0, NULL,
"Look outside of the devices file for missing devname entries.\n"
"A devname entry is used for a device that does not have a stable\n"
"device id, e.g. wwid, so the unstable device name is used as\n"
"the device id. After reboot, or if the device is reattached,\n"
"the device name may change, in which case lvm will not find\n"
"the expected PV on the device listed in the devices file.\n"
"This setting controls whether lvm will search other devices,\n"
"outside the devices file, to look for the missing PV on a\n"
"renamed device. If \"none\", lvm will not look at other devices,\n"
"and the PV may appear to be missing. If \"auto\", lvm will look\n"
"at other devices, but only those that are likely to have the PV.\n"
"If \"all\", lvm will look at all devices on the system.\n")
cfg(devices_devicesfile_CFG, "devicesfile", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DEVICES_FILE, vsn(2, 3, 10), NULL, 0, NULL,
"The file listing devices LVM should use.\n")
cfg_array(devices_filter_CFG, "filter", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sa|.*|", vsn(1, 0, 0), NULL, 0, NULL,
"Limit the block devices that are used by LVM commands.\n"
@@ -340,16 +329,16 @@ cfg_array(devices_global_filter_CFG, "global_filter", devices_CFG_SECTION, CFG_D
"global_filter are not opened by LVM.\n")
cfg_runtime(devices_cache_CFG, "cache", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), vsn(1, 2, 19), NULL,
NULL)
"This setting is no longer used.\n")
cfg_runtime(devices_cache_dir_CFG, "cache_dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 2, 19), vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.\n")
cfg(devices_cache_file_prefix_CFG, "cache_file_prefix", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_CACHE_FILE_PREFIX, vsn(1, 2, 19), NULL, vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.\n")
cfg(devices_write_cache_state_CFG, "write_cache_state", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.\n")
cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_ADVANCED, CFG_TYPE_INT | CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"List of additional acceptable block device types.\n"
@@ -360,12 +349,12 @@ cfg_array(devices_types_CFG, "types", devices_CFG_SECTION, CFG_DEFAULT_UNDEFINED
"types = [ \"fd\", 16 ]\n"
"#\n")
cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SYSFS_SCAN, vsn(1, 0, 8), NULL, 0, NULL,
cfg(devices_sysfs_scan_CFG, "sysfs_scan", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SYSFS_SCAN, vsn(1, 0, 8), NULL, 0, NULL,
"Restrict device scanning to block devices appearing in sysfs.\n"
"This is a quick way of filtering out block devices that are not\n"
"present on the system. sysfs must be part of the kernel and mounted.)\n")
cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SCAN_LVS, vsn(2, 2, 182), NULL, 0, NULL,
cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SCAN_LVS, vsn(2, 2, 182), NULL, 0, NULL,
"Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.\n"
"When 1, LVM will detect PVs layered on LVs, and caution must be\n"
"taken to avoid a host accessing a layered VG that may not belong\n"
@@ -378,14 +367,10 @@ cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED
"an LV. The LVs are ignored using a built in device filter that\n"
"identifies and excludes LVs.\n")
cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL,
cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL,
"Ignore devices that are components of DM multipath devices.\n")
cfg(devices_multipath_wwids_file_CFG, "multipath_wwids_file", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_WWIDS_FILE, vsn(2, 3, 13), NULL, 0, NULL,
"The path to the multipath wwids file used for multipath component detection.\n"
"Set this to an empty string to disable the use of the multipath wwids file.\n")
cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL, 0, NULL,
cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_COMPONENT_DETECTION, vsn(1, 0, 18), NULL, 0, NULL,
"Enable detection and exclusion of MD component devices.\n"
"An MD component device is a block device that MD uses as part\n"
"of a software RAID virtual device. When an LVM PV is created\n"
@@ -411,26 +396,26 @@ cfg(devices_md_component_checks_CFG, "md_component_checks", devices_CFG_SECTION,
" This requires an extra read at the end of devices.\n"
"#\n")
cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FW_RAID_COMPONENT_DETECTION, vsn(2, 2, 112), NULL, 0, NULL,
cfg(devices_fw_raid_component_detection_CFG, "fw_raid_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FW_RAID_COMPONENT_DETECTION, vsn(2, 2, 112), NULL, 0, NULL,
"Ignore devices that are components of firmware RAID devices.\n"
"LVM must use an external_device_info_source other than none for this\n"
"detection to execute.\n")
cfg(devices_md_chunk_alignment_CFG, "md_chunk_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MD_CHUNK_ALIGNMENT, vsn(2, 2, 48), NULL, 0, NULL,
cfg(devices_md_chunk_alignment_CFG, "md_chunk_alignment", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MD_CHUNK_ALIGNMENT, vsn(2, 2, 48), NULL, 0, NULL,
"Align the start of a PV data area with md device's stripe-width.\n"
"This applies if a PV is placed directly on an md device.\n"
"default_data_alignment will be overridden if it is not aligned\n"
"default_data_alignment will be overriden if it is not aligned\n"
"with the value detected for this setting.\n"
"This setting is overridden by data_alignment_detection,\n"
"This setting is overriden by data_alignment_detection,\n"
"data_alignment, and the --dataalignment option.\n")
cfg(devices_default_data_alignment_CFG, "default_data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, FIRST_PE_AT_ONE_MB_IN_MB, vsn(2, 2, 75), NULL, 0, NULL,
"Align the start of a PV data area with this number of MiB.\n"
"Set to 1 for 1MiB, 2 for 2MiB, etc. Set to 0 to disable.\n"
"This setting is overridden by data_alignment and the --dataalignment\n"
"This setting is overriden by data_alignment and the --dataalignment\n"
"option.\n")
cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_DETECTION, vsn(2, 2, 51), NULL, 0, NULL,
cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_DETECTION, vsn(2, 2, 51), NULL, 0, NULL,
"Align the start of a PV data area with sysfs io properties.\n"
"The start of a PV data area will be a multiple of minimum_io_size or\n"
"optimal_io_size exposed in sysfs. minimum_io_size is the smallest\n"
@@ -439,19 +424,19 @@ cfg(devices_data_alignment_detection_CFG, "data_alignment_detection", devices_CF
"preferred unit of receiving I/O, e.g. MD stripe width.\n"
"minimum_io_size is used if optimal_io_size is undefined (0).\n"
"If md_chunk_alignment is enabled, that detects the optimal_io_size.\n"
"default_data_alignment and md_chunk_alignment will be overridden\n"
"default_data_alignment and md_chunk_alignment will be overriden\n"
"if they are not aligned with the value detected for this setting.\n"
"This setting is overridden by data_alignment and the --dataalignment\n"
"This setting is overriden by data_alignment and the --dataalignment\n"
"option.\n")
cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 45), NULL, 0, NULL,
cfg(devices_data_alignment_CFG, "data_alignment", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 45), NULL, 0, NULL,
"Align the start of a PV data area with this number of KiB.\n"
"When non-zero, this setting overrides default_data_alignment.\n"
"Set to 0 to disable, in which case default_data_alignment\n"
"is used to align the first PE in units of MiB.\n"
"This setting is overridden by the --dataalignment option.\n")
"This setting is overriden by the --dataalignment option.\n")
cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detection", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION, vsn(2, 2, 50), NULL, 0, NULL,
cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DATA_ALIGNMENT_OFFSET_DETECTION, vsn(2, 2, 50), NULL, 0, NULL,
"Shift the start of an aligned PV data area based on sysfs information.\n"
"After a PV data area is aligned, it will be shifted by the\n"
"alignment_offset exposed in sysfs. This offset is often 0, but may\n"
@@ -459,14 +444,14 @@ cfg(devices_data_alignment_offset_detection_CFG, "data_alignment_offset_detectio
"partitioning will have an alignment_offset of 3584 bytes (sector 7\n"
"is the lowest aligned logical block, the 4KiB sectors start at\n"
"LBA -1, and consequently sector 63 is aligned on a 4KiB boundary).\n"
"This setting is overridden by the --dataalignmentoffset option.\n")
"This setting is overriden by the --dataalignmentoffset option.\n")
cfg(devices_ignore_suspended_devices_CFG, "ignore_suspended_devices", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_IGNORE_SUSPENDED_DEVICES, vsn(1, 2, 19), NULL, 0, NULL,
cfg(devices_ignore_suspended_devices_CFG, "ignore_suspended_devices", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_IGNORE_SUSPENDED_DEVICES, vsn(1, 2, 19), NULL, 0, NULL,
"Ignore DM devices that have I/O suspended while scanning devices.\n"
"Otherwise, LVM waits for a suspended device to become accessible.\n"
"This should only be needed in recovery situations.\n")
cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_IGNORE_LVM_MIRRORS, vsn(2, 2, 104), NULL, 0, NULL,
cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_IGNORE_LVM_MIRRORS, vsn(2, 2, 104), NULL, 0, NULL,
"Do not scan 'mirror' LVs to avoid possible deadlocks.\n"
"This avoids possible deadlocks when using the 'mirror' segment type.\n"
"This setting determines whether LVs using the 'mirror' segment type\n"
@@ -484,19 +469,19 @@ cfg(devices_ignore_lvm_mirrors_CFG, "ignore_lvm_mirrors", devices_CFG_SECTION, C
"apply to LVM RAID types like 'raid1' which handle failures in a\n"
"different way, making them a better choice for VG stacking.\n")
cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(2, 3, 0), NULL,
NULL)
cfg(devices_disable_after_error_count_CFG, "disable_after_error_count", devices_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(2, 2, 75), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID, vsn(2, 2, 73), NULL, 0, NULL,
cfg(devices_require_restorefile_with_uuid_CFG, "require_restorefile_with_uuid", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_REQUIRE_RESTOREFILE_WITH_UUID, vsn(2, 2, 73), NULL, 0, NULL,
"Allow use of pvcreate --uuid without requiring --restorefile.\n")
cfg(devices_pv_min_size_CFG, "pv_min_size", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PV_MIN_SIZE_KB, vsn(2, 2, 85), NULL, 0, NULL,
cfg(devices_pv_min_size_CFG, "pv_min_size", devices_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_PV_MIN_SIZE_KB, vsn(2, 2, 85), NULL, 0, NULL,
"Minimum size in KiB of block devices which can be used as PVs.\n"
"In a clustered environment all nodes must use the same value.\n"
"Any value smaller than 512KiB is ignored. The previous built-in\n"
"value was 512.\n")
cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ISSUE_DISCARDS, vsn(2, 2, 85), NULL, 0, NULL,
cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ISSUE_DISCARDS, vsn(2, 2, 85), NULL, 0, NULL,
"Issue discards to PVs that are no longer used by an LV.\n"
"Discards are sent to an LV's underlying physical volumes when the LV\n"
"is no longer using the physical volumes' space, e.g. lvremove,\n"
@@ -508,7 +493,7 @@ cfg(devices_issue_discards_CFG, "issue_discards", devices_CFG_SECTION, CFG_DEFAU
"generally do. If enabled, discards will only be issued if both the\n"
"storage and kernel provide support.\n")
cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_pvs", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS, vsn(2, 2, 153), NULL, 0, NULL,
cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_pvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS, vsn(2, 2, 153), NULL, 0, NULL,
"Allow VG modification while a PV appears on multiple devices.\n"
"When a PV appears on multiple devices, LVM attempts to choose the\n"
"best device to use for the PV. If the devices represent the same\n"
@@ -520,7 +505,7 @@ cfg(devices_allow_changes_with_duplicate_pvs_CFG, "allow_changes_with_duplicate_
"Enabling this setting allows the VG to be used as usual even with\n"
"uncertain devices.\n")
cfg(devices_allow_mixed_block_sizes_CFG, "allow_mixed_block_sizes", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 3, 6), NULL, 0, NULL,
cfg(devices_allow_mixed_block_sizes_CFG, "allow_mixed_block_sizes", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 6), NULL, 0, NULL,
"Allow PVs in the same VG with different logical block sizes.\n"
"When allowed, the user is responsible to ensure that an LV is\n"
"using PVs with matching block sizes when necessary.\n")
@@ -543,14 +528,14 @@ cfg_array(allocation_cling_tag_list_CFG, "cling_tag_list", allocation_CFG_SECTIO
"cling_tag_list = [ \"@site1\", \"@site2\" ]\n"
"#\n")
cfg(allocation_maximise_cling_CFG, "maximise_cling", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MAXIMISE_CLING, vsn(2, 2, 85), NULL, 0, NULL,
cfg(allocation_maximise_cling_CFG, "maximise_cling", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MAXIMISE_CLING, vsn(2, 2, 85), NULL, 0, NULL,
"Use a previous allocation algorithm.\n"
"Changes made in version 2.02.85 extended the reach of the 'cling'\n"
"policies to detect more situations where data can be grouped onto\n"
"the same disks. This setting can be used to disable the changes\n"
"and revert to the previous algorithm.\n")
cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_BLKID_WIPING, vsn(2, 2, 105), "@DEFAULT_USE_BLKID_WIPING@", 0, NULL,
cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_BLKID_WIPING, vsn(2, 2, 105), "@DEFAULT_USE_BLKID_WIPING@", 0, NULL,
"Use blkid to detect and erase existing signatures on new PVs and LVs.\n"
"The blkid library can detect more signatures than the native LVM\n"
"detection code, but may take longer. LVM needs to be compiled with\n"
@@ -559,7 +544,7 @@ cfg(allocation_use_blkid_wiping_CFG, "use_blkid_wiping", allocation_CFG_SECTION,
"swap signature, and LUKS signatures. To see the list of signatures\n"
"recognized by blkid, check the output of the 'blkid -k' command.\n")
cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_zeroing_new_lvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 2, 105), NULL, 0, NULL,
cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_zeroing_new_lvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 105), NULL, 0, NULL,
"Look for and erase any signatures while zeroing a new LV.\n"
"The --wipesignatures option overrides this setting.\n"
"Zeroing is controlled by the -Z/--zero option, and if not specified,\n"
@@ -575,7 +560,7 @@ cfg(allocation_wipe_signatures_when_zeroing_new_lvs_CFG, "wipe_signatures_when_z
"When this setting is disabled, signatures on new LVs are not detected\n"
"or erased unless the --wipesignatures option is used directly.\n")
cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_MIRROR_LOGS_REQUIRE_SEPARATE_PVS, vsn(2, 2, 85), NULL, 0, NULL,
cfg(allocation_mirror_logs_require_separate_pvs_CFG, "mirror_logs_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MIRROR_LOGS_REQUIRE_SEPARATE_PVS, vsn(2, 2, 85), NULL, 0, NULL,
"Mirror logs and images will always use different PVs.\n"
"The default setting changed in version 2.02.85.\n")
@@ -586,7 +571,7 @@ cfg(allocation_raid_stripe_all_devices_CFG, "raid_stripe_all_devices", allocatio
"stripes to use.\n"
"This was the default behaviour until release 2.02.162.\n")
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
cfg(allocation_cache_pool_metadata_require_separate_pvs_CFG, "cache_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_BOOL, DEFAULT_CACHE_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 106), NULL, 0, NULL,
"Cache pool metadata and data will always use different PVs.\n")
cfg(allocation_cache_pool_cachemode_CFG, "cache_pool_cachemode", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_CACHE_MODE, vsn(2, 2, 113), NULL, vsn(2, 2, 128),
@@ -643,13 +628,8 @@ cfg(allocation_cache_pool_max_chunks_CFG, "cache_pool_max_chunks", allocation_CF
"For cache target v1.9 the recommended maximumm is 1000000 chunks.\n"
"Using cache pool with more chunks may degrade cache performance.\n")
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
"Thin pool metadata and data will always use different PVs.\n")
cfg(allocation_thin_pool_crop_metadata_CFG, "thin_pool_crop_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_CROP_METADATA, vsn(2, 3, 12), NULL, 0, NULL,
"Older version of lvm2 cropped pool's metadata size to 15.81 GiB.\n"
"This is slightly less then the actual maximum 15.88 GiB.\n"
"For compatibility with older version and use of cropped size set to 1.\n")
cfg(allocation_thin_pool_metadata_require_separate_pvs_CFG, "thin_pool_metadata_require_separate_pvs", allocation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS, vsn(2, 2, 89), NULL, 0, NULL,
"Thin pool metdata and data will always use different PVs.\n")
cfg(allocation_thin_pool_zero_CFG, "thin_pool_zero", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_THIN_POOL_ZERO, vsn(2, 2, 99), NULL, 0, NULL,
"Thin pool data chunks are zeroed before they are first used.\n"
@@ -680,9 +660,6 @@ cfg(allocation_thin_pool_chunk_size_policy_CFG, "thin_pool_chunk_size_policy", a
" 512KiB.\n"
"#\n")
cfg(allocation_zero_metadata_CFG, "zero_metadata", allocation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ZERO_METADATA, vsn(2, 3, 10), NULL, 0, NULL,
"Zero whole metadata area before use with thin or cache pool.\n")
cfg_runtime(allocation_thin_pool_chunk_size_CFG, "thin_pool_chunk_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_UNDEFINED, CFG_TYPE_INT, vsn(2, 2, 99), 0, NULL,
"The minimal chunk size in KiB for thin pool volumes.\n"
"Larger chunk sizes may improve performance for plain thin volumes,\n"
@@ -796,12 +773,10 @@ cfg(allocation_vdo_write_policy_CFG, "vdo_write_policy", allocation_CFG_SECTION,
"sync - Writes are acknowledged only after data is stably written.\n"
" This policy is not supported if the underlying storage is not also synchronous.\n"
"async - Writes are acknowledged after data has been cached for writing to stable storage.\n"
" Data which has not been flushed is not guaranteed to persist in this mode.\n"
"async-unsafe - Writes are handled like 'async' but there is no guarantee of the atomicity async provides.\n"
" This mode should only be used for better performance when atomicity is not required.\n")
" Data which has not been flushed is not guaranteed to persist in this mode.\n")
cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_MAX_DISCARD, VDO_1ST_VSN, NULL, 0, NULL,
"Specified the maximum size of discard bio accepted, in 4096 byte blocks.\n"
"Specified te maximum size of discard bio accepted, in 4096 byte blocks.\n"
"I/O requests to a VDO volume are normally split into 4096-byte blocks,\n"
"and processed up to 2048 at a time. However, discard requests to a VDO volume\n"
"can be automatically split to a larger size, up to <max discard> 4096-byte blocks\n"
@@ -810,9 +785,6 @@ cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, C
"increased latency for the individual discard requests.\n"
"The default and minimum is 1. The maximum is UINT_MAX / 4096.\n")
cfg(allocation_vdo_pool_header_size_CFG, "vdo_pool_header_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_HEADER_SIZE_KB, vsn(2, 3, 12), NULL, 0, NULL,
"Specified the emptry header size in KiB at the front and end of vdo pool device.\n")
cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL,
"Enable or disable LVM log reporting.\n"
"If enabled, LVM will collect a log of operations, messages,\n"
@@ -854,10 +826,10 @@ cfg(log_command_log_selection_CFG, "command_log_selection", log_CFG_SECTION, CFG
"For more information about selection criteria in general, see\n"
"lvm(8) man page.\n")
cfg(log_verbose_CFG, "verbose", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VERBOSE, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_verbose_CFG, "verbose", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_VERBOSE, vsn(1, 0, 0), NULL, 0, NULL,
"Controls the messages sent to stdout or stderr.\n")
cfg(log_silent_CFG, "silent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SILENT, vsn(2, 2, 98), NULL, 0, NULL,
cfg(log_silent_CFG, "silent", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SILENT, vsn(2, 2, 98), NULL, 0, NULL,
"Suppress all non-essential messages from stdout.\n"
"This has the same effect as -qq. When enabled, the following commands\n"
"still produce output: dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck,\n"
@@ -867,22 +839,16 @@ cfg(log_silent_CFG, "silent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_B
"Any 'yes' or 'no' questions not overridden by other arguments are\n"
"suppressed and default to 'no'.\n")
cfg(log_syslog_CFG, "syslog", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_SYSLOG, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_syslog_CFG, "syslog", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_SYSLOG, vsn(1, 0, 0), NULL, 0, NULL,
"Send log messages through syslog.\n")
cfg(log_file_CFG, "file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"Write error and debug log messages to a file specified here.\n")
cfg_array(log_journal_CFG, "journal", log_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, NULL, vsn(2, 3, 12), NULL, 0, NULL,
"Record lvm information in the systemd journal.\n"
"command: record commands that are run.\n"
"output: record default output from commands.\n"
"debug: record debug messages from commands.\n")
cfg(log_overwrite_CFG, "overwrite", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_OVERWRITE, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_overwrite_CFG, "overwrite", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_OVERWRITE, vsn(1, 0, 0), NULL, 0, NULL,
"Overwrite the log file each time the program is run.\n")
cfg(log_level_CFG, "level", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_LOGLEVEL, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_level_CFG, "level", log_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_LOGLEVEL, vsn(1, 0, 0), NULL, 0, NULL,
"The level of log messages that are sent to the log file or syslog.\n"
"There are 6 syslog-like log levels currently in use: 2 to 7 inclusive.\n"
"7 is the most verbose (LOG_DEBUG).\n")
@@ -890,23 +856,23 @@ cfg(log_level_CFG, "level", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT
cfg(log_indent_CFG, "indent", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_INDENT, vsn(1, 0, 0), NULL, 0, NULL,
"Indent messages according to their severity.\n")
cfg(log_command_names_CFG, "command_names", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_CMD_NAME, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_command_names_CFG, "command_names", log_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_CMD_NAME, vsn(1, 0, 0), NULL, 0, NULL,
"Display the command name on each line of output.\n")
cfg(log_prefix_CFG, "prefix", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_MSG_PREFIX, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_prefix_CFG, "prefix", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_MSG_PREFIX, vsn(1, 0, 0), NULL, 0, NULL,
"A prefix to use before the log message text.\n"
"(After the command name, if selected).\n"
"Two spaces allows you to see/grep the severity of each message.\n"
"To make the messages look similar to the original LVM tools use:\n"
"indent = 0, command_names = 1, prefix = \" -- \"\n")
cfg(log_activation_CFG, "activation", log_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
cfg(log_activation_CFG, "activation", log_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
"Log messages during activation.\n"
"Don't use this in low memory situations (can deadlock).\n")
cfg(log_activate_file_CFG, "activate_file", log_CFG_SECTION, CFG_DEFAULT_UNDEFINED | CFG_UNSUPPORTED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL, NULL)
cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sio#Sactivation#Sallocation#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL,
cfg_array(log_debug_classes_CFG, "debug_classes", log_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#Smemory#Sdevices#Sio#Sactivation#Sallocation#Smetadata#Scache#Slocking#Slvmpolld#Sdbus", vsn(2, 2, 99), NULL, 0, NULL,
"Select log messages by class.\n"
"Some debugging messages are assigned to a class and only appear in\n"
"debug output if the class is listed here. Classes currently\n"
@@ -921,55 +887,55 @@ cfg_array(log_debug_output_fields_CFG, "debug_output_fields", log_CFG_SECTION, C
"The fields included in debug output written to stderr.\n"
"Use \"all\" to include everything (the default).\n")
cfg(backup_backup_CFG, "backup", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_BACKUP_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
cfg(backup_backup_CFG, "backup", backup_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_BACKUP_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
"Maintain a backup of the current metadata configuration.\n"
"Think very hard before turning this off!\n")
cfg_runtime(backup_backup_dir_CFG, "backup_dir", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL,
cfg_runtime(backup_backup_dir_CFG, "backup_dir", backup_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL,
"Location of the metadata backup files.\n"
"Remember to back up this directory regularly!\n")
cfg(backup_archive_CFG, "archive", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ARCHIVE_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
cfg(backup_archive_CFG, "archive", backup_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ARCHIVE_ENABLED, vsn(1, 0, 0), NULL, 0, NULL,
"Maintain an archive of old metadata configurations.\n"
"Think very hard before turning this off.\n")
cfg_runtime(backup_archive_dir_CFG, "archive_dir", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL,
cfg_runtime(backup_archive_dir_CFG, "archive_dir", backup_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(1, 0, 0), 0, NULL,
"Location of the metdata archive files.\n"
"Remember to back up this directory regularly!\n")
cfg(backup_retain_min_CFG, "retain_min", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_ARCHIVE_NUMBER, vsn(1, 0, 0), NULL, 0, NULL,
cfg(backup_retain_min_CFG, "retain_min", backup_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_ARCHIVE_NUMBER, vsn(1, 0, 0), NULL, 0, NULL,
"Minimum number of archives to keep.\n")
cfg(backup_retain_days_CFG, "retain_days", backup_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_ARCHIVE_DAYS, vsn(1, 0, 0), NULL, 0, NULL,
cfg(backup_retain_days_CFG, "retain_days", backup_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_ARCHIVE_DAYS, vsn(1, 0, 0), NULL, 0, NULL,
"Minimum number of days to keep archive files.\n")
cfg(shell_history_size_CFG, "history_size", shell_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_MAX_HISTORY, vsn(1, 0, 0), NULL, 0, NULL,
cfg(shell_history_size_CFG, "history_size", shell_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_MAX_HISTORY, vsn(1, 0, 0), NULL, 0, NULL,
"Number of lines of history to store in ~/.lvm_history.\n")
cfg(global_umask_CFG, "umask", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_FORMAT_INT_OCTAL, CFG_TYPE_INT, DEFAULT_UMASK, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_umask_CFG, "umask", global_CFG_SECTION, CFG_FORMAT_INT_OCTAL, CFG_TYPE_INT, DEFAULT_UMASK, vsn(1, 0, 0), NULL, 0, NULL,
"The file creation mask for any files and directories created.\n"
"Interpreted as octal if the first digit is zero.\n")
cfg(global_test_CFG, "test", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_test_CFG, "test", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(1, 0, 0), NULL, 0, NULL,
"No on-disk metadata changes will be made in test mode.\n"
"Equivalent to having the -t option on every command.\n")
cfg(global_units_CFG, "units", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_STRING, DEFAULT_UNITS, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_units_CFG, "units", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_STRING, DEFAULT_UNITS, vsn(1, 0, 0), NULL, 0, NULL,
"Default value for --units argument.\n")
cfg(global_si_unit_consistency_CFG, "si_unit_consistency", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SI_UNIT_CONSISTENCY, vsn(2, 2, 54), NULL, 0, NULL,
cfg(global_si_unit_consistency_CFG, "si_unit_consistency", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SI_UNIT_CONSISTENCY, vsn(2, 2, 54), NULL, 0, NULL,
"Distinguish between powers of 1024 and 1000 bytes.\n"
"The LVM commands distinguish between powers of 1024 bytes,\n"
"e.g. KiB, MiB, GiB, and powers of 1000 bytes, e.g. KB, MB, GB.\n"
"If scripts depend on the old behaviour, disable this setting\n"
"temporarily until they are updated.\n")
cfg(global_suffix_CFG, "suffix", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SUFFIX, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_suffix_CFG, "suffix", global_CFG_SECTION, CFG_PROFILABLE, CFG_TYPE_BOOL, DEFAULT_SUFFIX, vsn(1, 0, 0), NULL, 0, NULL,
"Display unit suffix for sizes.\n"
"This setting has no effect if the units are in human-readable form\n"
"(global/units = \"h\") in which case the suffix is always displayed.\n")
cfg(global_activation_CFG, "activation", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ACTIVATION, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_activation_CFG, "activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ACTIVATION, vsn(1, 0, 0), NULL, 0, NULL,
"Enable/disable communication with the kernel device-mapper.\n"
"Disable to use the tools to manipulate LVM metadata without\n"
"activating any logical volumes. If the device-mapper driver\n"
@@ -977,69 +943,70 @@ cfg(global_activation_CFG, "activation", global_CFG_SECTION, CFG_DEFAULT_COMMENT
"the error messages.\n")
cfg(global_fallback_to_lvm1_CFG, "fallback_to_lvm1", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(1, 0, 18), NULL, vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.\n")
cfg(global_format_CFG, "format", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FORMAT, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.\n")
cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.")
cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL, vsn(2, 3, 3), NULL, NULL)
cfg(global_proc_CFG, "proc", global_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_PROC_DIR, vsn(1, 0, 0), NULL, 0, NULL,
cfg(global_proc_CFG, "proc", global_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_PROC_DIR, vsn(1, 0, 0), NULL, 0, NULL,
"Location of proc filesystem.\n")
cfg(global_etc_CFG, "etc", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_ETC_DIR, vsn(2, 2, 117), "@CONFDIR@", 0, NULL,
cfg(global_etc_CFG, "etc", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ETC_DIR, vsn(2, 2, 117), "@CONFDIR@", 0, NULL,
"Location of /etc system configuration directory.\n")
cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
NULL)
cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, 0, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.")
cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL, 0, NULL,
cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL, 0, NULL,
"When disabled, fail if a lock request would block.\n")
cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
NULL)
cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
NULL)
cfg(global_fallback_to_local_locking_CFG, "fallback_to_local_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_LOCAL_LOCKING, vsn(2, 2, 42), NULL, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_locking_dir_CFG, "locking_dir", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCK_DIR, vsn(1, 0, 0), "@DEFAULT_LOCK_DIR@", 0, NULL,
cfg(global_locking_dir_CFG, "locking_dir", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_LOCK_DIR, vsn(1, 0, 0), "@DEFAULT_LOCK_DIR@", 0, NULL,
"Directory to use for LVM command file locks.\n"
"Local non-LV directory that holds file-based locks while commands are\n"
"in progress. A directory like /tmp that may get wiped on reboot is OK.\n")
cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_PRIORITISE_WRITE_LOCKS, vsn(2, 2, 52), NULL, 0, NULL,
cfg(global_prioritise_write_locks_CFG, "prioritise_write_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_PRIORITISE_WRITE_LOCKS, vsn(2, 2, 52), NULL, 0, NULL,
"Allow quicker VG write access during high volume read access.\n"
"When there are competing read-only and read-write access requests for\n"
"a volume group's metadata, instead of always granting the read-only\n"
"requests immediately, delay them to allow the read-write requests to\n"
"be serviced. Without this setting, write access may be stalled by a\n"
"high volume of read-only requests. This option only affects file locks.\n")
"high volume of read-only requests. This option only affects\n"
"locking_type 1 viz. local file-based locking.\n")
cfg(global_library_dir_CFG, "library_dir", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, 0, NULL,
"Search this directory first for shared libraries.\n")
cfg(global_locking_library_CFG, "locking_library", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_LOCKING_LIB, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.\n")
cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ABORT_ON_INTERNAL_ERRORS, vsn(2, 2, 57), NULL, 0, NULL,
cfg(global_abort_on_internal_errors_CFG, "abort_on_internal_errors", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ABORT_ON_INTERNAL_ERRORS, vsn(2, 2, 57), NULL, 0, NULL,
"Abort a command that encounters an internal error.\n"
"Treat any internal errors as fatal errors, aborting the process that\n"
"encountered the internal error. Please only enable for debugging.\n")
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 96), NULL, vsn(2, 2, 174), NULL,
NULL)
cfg(global_detect_internal_vg_cache_corruption_CFG, "detect_internal_vg_cache_corruption", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 96), NULL, vsn(2, 2, 174), NULL,
"No longer used.\n")
cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_METADATA_READ_ONLY, vsn(2, 2, 75), NULL, 0, NULL,
cfg(global_metadata_read_only_CFG, "metadata_read_only", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_METADATA_READ_ONLY, vsn(2, 2, 75), NULL, 0, NULL,
"No operations that change on-disk metadata are permitted.\n"
"Additionally, read-only commands that encounter metadata in need of\n"
"repair will still be allowed to proceed exactly as if the repair had\n"
"been performed (except for the unchanged vg_seqno). Inappropriate\n"
"use could mess up your system, so seek advice first!\n")
cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_SEGTYPE, vsn(2, 2, 87), "@DEFAULT_MIRROR_SEGTYPE@", 0, NULL,
cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_SEGTYPE, vsn(2, 2, 87), "@DEFAULT_MIRROR_SEGTYPE@", 0, NULL,
"The segment type used by the short mirroring option -m.\n"
"The --type mirror|raid1 option overrides this setting.\n"
"#\n"
@@ -1064,7 +1031,7 @@ cfg(global_mirror_segtype_default_CFG, "mirror_segtype_default", global_CFG_SECT
" fashion in a cluster.\n"
"#\n")
cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 3, 2), NULL, 0, NULL,
cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 3, 2), NULL, 0, NULL,
"Enable mirrored 'mirror' log type for testing.\n"
"#\n"
"This type is deprecated to create or convert to but can\n"
@@ -1074,7 +1041,7 @@ cfg(global_support_mirrored_mirror_log_CFG, "support_mirrored_mirror_log", globa
"Not supported for regular operation!\n"
"\n")
cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_RAID10_SEGTYPE, vsn(2, 2, 99), "@DEFAULT_RAID10_SEGTYPE@", 0, NULL,
cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_RAID10_SEGTYPE, vsn(2, 2, 99), "@DEFAULT_RAID10_SEGTYPE@", 0, NULL,
"The segment type used by the -i -m combination.\n"
"The --type raid10|mirror option overrides this setting.\n"
"The --stripes/-i and --mirrors/-m options can both be specified\n"
@@ -1092,7 +1059,7 @@ cfg(global_raid10_segtype_default_CFG, "raid10_segtype_default", global_CFG_SECT
" in terms of providing redundancy and performance.\n"
"#\n")
cfg(global_sparse_segtype_default_CFG, "sparse_segtype_default", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SPARSE_SEGTYPE, vsn(2, 2, 112), "@DEFAULT_SPARSE_SEGTYPE@", 0, NULL,
cfg(global_sparse_segtype_default_CFG, "sparse_segtype_default", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_SPARSE_SEGTYPE, vsn(2, 2, 112), "@DEFAULT_SPARSE_SEGTYPE@", 0, NULL,
"The segment type used by the -V -L combination.\n"
"The --type snapshot|thin option overrides this setting.\n"
"The combination of -V and -L options creates a sparse LV. There are\n"
@@ -1118,40 +1085,25 @@ cfg(global_lvdisplay_shows_full_device_path_CFG, "lvdisplay_shows_full_device_pa
"Previously this was always shown as /dev/vgname/lvname even when that\n"
"was never a valid path in the /dev filesystem.\n")
cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL,
cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 3, 1), 0, 0, NULL,
"Activate LVs based on system-generated device events.\n"
"When a PV appears on the system, a system-generated uevent triggers\n"
"the lvm2-pvscan service which runs the pvscan --cache -aay command.\n"
"If the new PV completes a VG, pvscan autoactivates LVs in the VG.\n"
"When event_activation is disabled, the lvm2-activation services are\n"
"generated and run at fixed points during system startup. These\n"
"services run vgchange -aay to autoactivate LVs in VGs that happen\n"
"to be present at that point in time.\n"
"See the --setautoactivation option or the auto_activation_volume_list\n"
"setting to configure autoactivation for specific VGs or LVs.\n")
"When a device appears on the system, a system-generated event runs\n"
"the pvscan command to activate LVs if the new PV completes the VG.\n"
"Use auto_activation_volume_list to select which LVs should be\n"
"activated from these events (the default is all.)\n"
"When event_activation is disabled, the system will generally run\n"
"a direct activation command to activate LVs in complete VGs.\n")
cfg_array(global_event_activation_options_CFG, "event_activation_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_EVENT_ACTIVATION_OPTIONS, vsn(2, 3, 14), NULL, 0, NULL,
"Set event activation options.\n"
"service_to_event: begin with fixed activation services,\n"
"then switch to event based activation.\n"
"event_only: only use event based activation.\n"
"service_only: only use fixed activation services.\n"
"(This is equivalent to event_activation=0.)\n"
"Autoactivation commands should set --eventactivation service|event\n"
"to indicate if they are performing service or event activation.\n"
"An autoactivation command may then be skipped according to the\n"
"value of this setting.\n")
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL,
NULL)
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL,
"This setting is no longer used.\n")
cfg(global_lvmetad_update_wait_time_CFG, "lvmetad_update_wait_time", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(2, 2, 151), NULL, vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.\n")
cfg(global_use_aio_CFG, "use_aio", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_AIO, vsn(2, 2, 183), NULL, 0, NULL,
"Use async I/O when reading and writing devices.\n")
cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL,
cfg(global_use_lvmlockd_CFG, "use_lvmlockd", global_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2, 2, 124), NULL, 0, NULL,
"Use lvmlockd for locking among hosts using LVM on shared storage.\n"
"Applicable only if LVM is compiled with lockd support in which\n"
"case there is also lvmlockd(8) man page available for more\n"
@@ -1170,15 +1122,6 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D
"and can cause lvcreate to fail. Applicable only if LVM is compiled\n"
"with lockd support\n")
cfg(global_lvmlockctl_kill_command_CFG, "lvmlockctl_kill_command", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "", vsn(2, 3, 12), NULL, 0, NULL,
"The command that lvmlockctl --kill should use to force LVs offline.\n"
"The lvmlockctl --kill command is run when a shared VG has lost\n"
"access to locks (e.g. when sanlock has lost access to storage.)\n"
"An empty string means that there will be no automatic attempt by\n"
"lvmlockctl --kill to forcibly shut down LVs in the VG, and the user\n"
"can manually intervene as described in lvmlockd(8).\n"
"The VG name will be appended to the command specified here.\n")
cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL,
"The full path to the thin_check command.\n"
"LVM uses this command to check that a thin metadata device is in a\n"
@@ -1264,20 +1207,11 @@ cfg(global_vdo_format_executable_CFG, "vdo_format_executable", global_CFG_SECTIO
cfg_array(global_vdo_format_options_CFG, "vdo_format_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_VDO_FORMAT_OPTIONS_CONFIG, VDO_1ST_VSN, NULL, 0, NULL,
"List of options passed added to standard vdoformat command.\n")
cfg_array(global_vdo_disabled_features_CFG, "vdo_disabled_features", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 3, 11), NULL, 0, NULL,
"Features to not use in the vdo driver.\n"
"This can be helpful for testing, or to avoid using a feature that is\n"
"causing problems. Features include: online_rename\n"
"#\n"
"Example\n"
"vdo_disabled_features = [ \"online_rename\" ]\n"
"#\n")
cfg(global_fsadm_executable_CFG, "fsadm_executable", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_FSADM_PATH, vsn(2, 2, 170), "@FSADM_PATH@", 0, NULL,
"The full path to the fsadm command.\n"
"LVM uses this command to help with lvresize -r operations.\n")
cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_SYSTEM_ID_SOURCE, vsn(2, 2, 117), NULL, 0, NULL,
cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_SYSTEM_ID_SOURCE, vsn(2, 2, 117), NULL, 0, NULL,
"The method LVM uses to set the local system ID.\n"
"Volume Groups can also be given a system ID (by vgcreate, vgchange,\n"
"or vgimport.) A VG on shared storage devices is accessible only to\n"
@@ -1293,12 +1227,10 @@ cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, CFG_DEF
" uname\n"
" Set the system ID from the hostname (uname) of the system.\n"
" System IDs beginning localhost are not permitted.\n"
" appmachineid\n"
" Use an LVM-specific derivation of the local machine-id as the\n"
" system ID. See 'man machine-id'.\n"
" machineid\n"
" Use the contents of the machine-id file to set the system ID\n"
" (appmachineid is recommended.)\n"
" Use the contents of the machine-id file to set the system ID.\n"
" Some systems create this file at installation time.\n"
" See 'man machine-id' and global/etc.\n"
" file\n"
" Use the contents of another file (system_id_file) to set the\n"
" system ID.\n"
@@ -1309,13 +1241,13 @@ cfg(global_system_id_file_CFG, "system_id_file", global_CFG_SECTION, CFG_DEFAULT
"This is used when system_id_source is set to 'file'.\n"
"Comments starting with the character # are ignored.\n")
cfg(activation_checks_CFG, "checks", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_ACTIVATION_CHECKS, vsn(2, 2, 86), NULL, 0, NULL,
cfg(activation_checks_CFG, "checks", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ACTIVATION_CHECKS, vsn(2, 2, 86), NULL, 0, NULL,
"Perform internal checks of libdevmapper operations.\n"
"Useful for debugging problems with activation. Some of the checks may\n"
"be expensive, so it's best to use this only when there seems to be a\n"
"problem.\n")
cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_LVMPOLLD, vsn(2, 2, 120), "@DEFAULT_USE_LVMPOLLD@", 0, NULL,
cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_LVMPOLLD, vsn(2, 2, 120), "@DEFAULT_USE_LVMPOLLD@", 0, NULL,
"Use lvmpolld to supervise long running LVM commands.\n"
"When enabled, control of long running LVM commands is transferred\n"
"from the original LVM command to the lvmpolld daemon. This allows\n"
@@ -1328,7 +1260,7 @@ cfg(global_use_lvmpolld_CFG, "use_lvmpolld", global_CFG_SECTION, CFG_DEFAULT_COM
"commands will supervise long running operations by forking themselves.\n"
"Applicable only if LVM is compiled with lvmpolld support.\n")
cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL,
cfg(global_notify_dbus_CFG, "notify_dbus", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_NOTIFY_DBUS, vsn(2, 2, 145), NULL, 0, NULL,
"Enable D-Bus notification from LVM commands.\n"
"When enabled, an LVM command that changes PVs, changes VG metadata,\n"
"or changes the activation state of an LV will send a notification.\n")
@@ -1341,9 +1273,9 @@ cfg(global_io_memory_size_CFG, "io_memory_size", global_CFG_SECTION, CFG_DEFAULT
"This value should usually not be decreased from the default; setting\n"
"it too low can result in lvm failing to read VGs.\n")
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL,
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL, 0, NULL,
"Use udev notifications to synchronize udev and LVM.\n"
"The --noudevsync option overrides this setting.\n"
"The --nodevsync option overrides this setting.\n"
"When disabled, LVM commands will not wait for notifications from\n"
"udev, but continue irrespective of any possible udev processing in\n"
"the background. Only use this if udev is not running or has rules\n"
@@ -1351,25 +1283,25 @@ cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, CFG_DEFAULT_C
"running, and LVM processes are waiting for udev, run the command\n"
"'dmsetup udevcomplete_all' to wake them up.\n")
cfg(activation_udev_rules_CFG, "udev_rules", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_UDEV_RULES, vsn(2, 2, 57), NULL, 0, NULL,
cfg(activation_udev_rules_CFG, "udev_rules", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_RULES, vsn(2, 2, 57), NULL, 0, NULL,
"Use udev rules to manage LV device nodes and symlinks.\n"
"When disabled, LVM will manage the device nodes and symlinks for\n"
"active LVs itself. Manual intervention may be required if this\n"
"setting is changed while LVs are active.\n")
cfg(activation_verify_udev_operations_CFG, "verify_udev_operations", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_VERIFY_UDEV_OPERATIONS, vsn(2, 2, 86), NULL, 0, NULL,
cfg(activation_verify_udev_operations_CFG, "verify_udev_operations", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_VERIFY_UDEV_OPERATIONS, vsn(2, 2, 86), NULL, 0, NULL,
"Use extra checks in LVM to verify udev operations.\n"
"This enables additional checks (and if necessary, repairs) on entries\n"
"in the device directory after udev has completed processing its\n"
"events. Useful for diagnosing problems with LVM/udev interactions.\n")
cfg(activation_retry_deactivation_CFG, "retry_deactivation", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_RETRY_DEACTIVATION, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_retry_deactivation_CFG, "retry_deactivation", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_RETRY_DEACTIVATION, vsn(2, 2, 89), NULL, 0, NULL,
"Retry failed LV deactivation.\n"
"If LV deactivation fails, LVM will retry for a few seconds before\n"
"failing. This may happen because a process run from a quick udev rule\n"
"temporarily opened the device.\n")
cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_STRIPE_FILLER, vsn(1, 0, 0), NULL, 0, NULL,
cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_STRIPE_FILLER, vsn(1, 0, 0), NULL, 0, NULL,
"Method to fill missing stripes when activating an incomplete LV.\n"
"Using 'error' will make inaccessible parts of the device return I/O\n"
"errors on access. Using 'zero' will return success (and zero) on I/O\n"
@@ -1378,21 +1310,21 @@ cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CF
"other than 'error' with mirrored or snapshotted volumes is likely to\n"
"result in data corruption.\n")
cfg(activation_use_linear_target_CFG, "use_linear_target", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_LINEAR_TARGET, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_use_linear_target_CFG, "use_linear_target", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_LINEAR_TARGET, vsn(2, 2, 89), NULL, 0, NULL,
"Use the linear target to optimize single stripe LVs.\n"
"When disabled, the striped target is used. The linear target is an\n"
"optimised version of the striped target that only handles a single\n"
"stripe.\n")
cfg(activation_reserved_stack_CFG, "reserved_stack", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RESERVED_STACK, vsn(1, 0, 0), NULL, 0, NULL,
cfg(activation_reserved_stack_CFG, "reserved_stack", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RESERVED_STACK, vsn(1, 0, 0), NULL, 0, NULL,
"Stack size in KiB to reserve for use while devices are suspended.\n"
"Insufficent reserve risks I/O deadlock during device suspension.\n")
cfg(activation_reserved_memory_CFG, "reserved_memory", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RESERVED_MEMORY, vsn(1, 0, 0), NULL, 0, NULL,
cfg(activation_reserved_memory_CFG, "reserved_memory", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RESERVED_MEMORY, vsn(1, 0, 0), NULL, 0, NULL,
"Memory size in KiB to reserve for use while devices are suspended.\n"
"Insufficent reserve risks I/O deadlock during device suspension.\n")
cfg(activation_process_priority_CFG, "process_priority", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_PROCESS_PRIORITY, vsn(1, 0, 0), NULL, 0, NULL,
cfg(activation_process_priority_CFG, "process_priority", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_PROCESS_PRIORITY, vsn(1, 0, 0), NULL, 0, NULL,
"Nice value used while devices are suspended.\n"
"Use a high priority so that LVs are suspended\n"
"for the shortest possible time.\n")
@@ -1422,22 +1354,22 @@ cfg_array(activation_volume_list_CFG, "volume_list", activation_CFG_SECTION, CFG
"#\n")
cfg_array(activation_auto_activation_volume_list_CFG, "auto_activation_volume_list", activation_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 97), NULL, 0, NULL,
"A list of VGs or LVs that should be autoactivated.\n"
"Autoactivation is an activation command run with -aay,\n"
"i.e. vgchange -aay, lvchange -aay, or pvscan --cache -aay.\n"
"When this list is defined, an autoactivation command will only\n"
"activate LVs included in the list. If this list is undefined,\n"
"it has no effect. If this list is defined but empty, then no\n"
"LVs will be autoactivated. LVs can be included in the list by\n"
"LV name, VG name (applies to all LVs in the VG), or tag name.\n"
"VGs and LVs can also have an autoactivation property set in\n"
"metadata, see --setautoactivation. LVs included in this list\n"
"will not be autoactivated if the VG or LV autoactivation\n"
"property is disabled (see vgs or lvs \"-o autoactivation\").\n"
"The volume_list setting and the \"activation skip\" property\n"
"also apply to autoactivation.\n"
"The -aay option is meant to be used by activation commands that\n"
"are run automatically by the system, e.g. from systemd services.\n"
"Only LVs selected by this list are auto-activated.\n"
"This list works like volume_list, but it is used only by\n"
"auto-activation commands. It does not apply to direct activation\n"
"commands. If this list is defined, an LV is only auto-activated\n"
"if it matches an entry in this list. If this list is undefined, it\n"
"imposes no limits on LV auto-activation (all are allowed.) If this\n"
"list is defined and empty, i.e. \"[]\", then no LVs are selected for\n"
"auto-activation. An LV that is selected by this list for\n"
"auto-activation, must also be selected by volume_list (if defined)\n"
"before it is activated. Auto-activation is an activation command that\n"
"includes the 'a' argument: --activate ay or -a ay. The 'a' (auto)\n"
"argument for auto-activation is meant to be used by activation\n"
"commands that are run automatically by the system, as opposed to LVM\n"
"commands run directly by a user. A user may also use the 'a' flag\n"
"directly to perform auto-activation. Also see pvscan(8) for more\n"
"information about auto-activation.\n"
"#\n"
"Accepted values:\n"
" vgname\n"
@@ -1482,11 +1414,11 @@ cfg_array(activation_read_only_volume_list_CFG, "read_only_volume_list", activat
"read_only_volume_list = [ \"vg1\", \"vg2/lvol1\", \"@tag1\", \"@*\" ]\n"
"#\n")
cfg(activation_mirror_region_size_CFG, "mirror_region_size", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(1, 0, 0), NULL, vsn(2, 2, 99),
cfg(activation_mirror_region_size_CFG, "mirror_region_size", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(1, 0, 0), NULL, vsn(2, 2, 99),
"This has been replaced by the activation/raid_region_size setting.\n",
"Size in KiB of each raid or mirror synchronization region.\n")
cfg(activation_raid_region_size_CFG, "raid_region_size", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(2, 2, 99), NULL, 0, NULL,
cfg(activation_raid_region_size_CFG, "raid_region_size", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_RAID_REGION_SIZE, vsn(2, 2, 99), NULL, 0, NULL,
"Size in KiB of each raid or mirror synchronization region.\n"
"The clean/dirty state of data is tracked for each region.\n"
"The value is rounded down to a power of two if necessary, and\n"
@@ -1501,7 +1433,7 @@ cfg(activation_error_when_full_CFG, "error_when_full", activation_CFG_SECTION, C
"thin pool data space is extended. New thin pools are assigned the\n"
"behavior defined here.\n")
cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_READ_AHEAD, vsn(1, 0, 23), NULL, 0, NULL,
cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_READ_AHEAD, vsn(1, 0, 23), NULL, 0, NULL,
"Setting to use when there is no readahead setting in metadata.\n"
"#\n"
"Accepted values:\n"
@@ -1511,7 +1443,7 @@ cfg(activation_readahead_CFG, "readahead", activation_CFG_SECTION, CFG_DEFAULT_C
" Use default value chosen by kernel.\n"
"#\n")
cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_RAID_FAULT_POLICY, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_RAID_FAULT_POLICY, vsn(2, 2, 89), NULL, 0, NULL,
"Defines how a device failure in a RAID LV is handled.\n"
"This includes LVs that have the following segment types:\n"
"raid1, raid4, raid5*, and raid6*.\n"
@@ -1532,7 +1464,7 @@ cfg(activation_raid_fault_policy_CFG, "raid_fault_policy", activation_CFG_SECTIO
" replace faulty devices.\n"
"#\n")
cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, vsn(2, 2, 57), 0, NULL,
cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, vsn(2, 2, 57), 0, NULL,
"Defines how a device failure in a 'mirror' LV is handled.\n"
"An LV with the 'mirror' segment type is composed of mirror images\n"
"(copies) and a mirror log. A disk log ensures that a mirror LV does\n"
@@ -1568,16 +1500,16 @@ cfg_runtime(activation_mirror_image_fault_policy_CFG, "mirror_image_fault_policy
" replacement.\n"
"#\n")
cfg(activation_mirror_log_fault_policy_CFG, "mirror_log_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_LOG_FAULT_POLICY, vsn(1, 2, 18), NULL, 0, NULL,
cfg(activation_mirror_log_fault_policy_CFG, "mirror_log_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_LOG_FAULT_POLICY, vsn(1, 2, 18), NULL, 0, NULL,
"Defines how a device failure in a 'mirror' log LV is handled.\n"
"The mirror_image_fault_policy description for mirrored LVs also\n"
"applies to mirrored log LVs.\n")
cfg(activation_mirror_device_fault_policy_CFG, "mirror_device_fault_policy", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MIRROR_DEVICE_FAULT_POLICY, vsn(1, 2, 10), NULL, vsn(2, 2, 57),
cfg(activation_mirror_device_fault_policy_CFG, "mirror_device_fault_policy", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_MIRROR_DEVICE_FAULT_POLICY, vsn(1, 2, 10), NULL, vsn(2, 2, 57),
"This has been replaced by the activation/mirror_image_fault_policy setting.\n",
"Define how a device failure affecting a mirror is handled.\n")
cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD, vsn(2, 2, 75), NULL, 0, NULL,
cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_THRESHOLD, vsn(2, 2, 75), NULL, 0, NULL,
"Auto-extend a snapshot when its usage exceeds this percent.\n"
"Setting this to 100 disables automatic extension.\n"
"The minimum value is 50 (a smaller value is treated as 50.)\n"
@@ -1591,7 +1523,7 @@ cfg(activation_snapshot_autoextend_threshold_CFG, "snapshot_autoextend_threshold
"snapshot_autoextend_threshold = 70\n"
"#\n")
cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT, vsn(2, 2, 75), NULL, 0, NULL,
cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_SNAPSHOT_AUTOEXTEND_PERCENT, vsn(2, 2, 75), NULL, 0, NULL,
"Auto-extending a snapshot adds this percent extra space.\n"
"The amount of additional space added to a snapshot is this\n"
"percent of its current size.\n"
@@ -1603,7 +1535,7 @@ cfg(activation_snapshot_autoextend_percent_CFG, "snapshot_autoextend_percent", a
"snapshot_autoextend_percent = 20\n"
"#\n")
cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_threshold", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_THRESHOLD, vsn(2, 2, 89), NULL, 0, NULL,
"Auto-extend a thin pool when its usage exceeds this percent.\n"
"Setting this to 100 disables automatic extension.\n"
"The minimum value is 50 (a smaller value is treated as 50.)\n"
@@ -1617,7 +1549,7 @@ cfg(activation_thin_pool_autoextend_threshold_CFG, "thin_pool_autoextend_thresho
"thin_pool_autoextend_threshold = 70\n"
"#\n")
cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT, vsn(2, 2, 89), NULL, 0, NULL,
cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_THIN_POOL_AUTOEXTEND_PERCENT, vsn(2, 2, 89), NULL, 0, NULL,
"Auto-extending a thin pool adds this percent extra space.\n"
"The amount of additional space added to a thin pool is this\n"
"percent of its current size.\n"
@@ -1629,7 +1561,7 @@ cfg(activation_thin_pool_autoextend_percent_CFG, "thin_pool_autoextend_percent",
"thin_pool_autoextend_percent = 20\n"
"#\n")
cfg(activation_vdo_pool_autoextend_threshold_CFG, "vdo_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_AUTOEXTEND_THRESHOLD, VDO_1ST_VSN, NULL, 0, NULL,
cfg(activation_vdo_pool_autoextend_threshold_CFG, "vdo_pool_autoextend_threshold", activation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA, CFG_TYPE_INT, DEFAULT_VDO_POOL_AUTOEXTEND_THRESHOLD, VDO_1ST_VSN, NULL, 0, NULL,
"Auto-extend a VDO pool when its usage exceeds this percent.\n"
"Setting this to 100 disables automatic extension.\n"
"The minimum value is 50 (a smaller value is treated as 50.)\n"
@@ -1669,17 +1601,17 @@ cfg_array(activation_mlock_filter_CFG, "mlock_filter", activation_CFG_SECTION, C
"mlock_filter = [ \"locale/locale-archive\", \"gconv/gconv-modules.cache\" ]\n"
"#\n")
cfg(activation_use_mlockall_CFG, "use_mlockall", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_USE_MLOCKALL, vsn(2, 2, 62), NULL, 0, NULL,
cfg(activation_use_mlockall_CFG, "use_mlockall", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_USE_MLOCKALL, vsn(2, 2, 62), NULL, 0, NULL,
"Use the old behavior of mlockall to pin all memory.\n"
"Prior to version 2.02.62, LVM used mlockall() to pin the whole\n"
"process's memory while activating devices.\n")
cfg(activation_monitoring_CFG, "monitoring", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, DEFAULT_DMEVENTD_MONITOR, vsn(2, 2, 63), NULL, 0, NULL,
cfg(activation_monitoring_CFG, "monitoring", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_DMEVENTD_MONITOR, vsn(2, 2, 63), NULL, 0, NULL,
"Monitor LVs that are activated.\n"
"The --ignoremonitoring option overrides this setting.\n"
"When enabled, LVM will ask dmeventd to monitor activated LVs.\n")
cfg(activation_polling_interval_CFG, "polling_interval", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_INTERVAL, vsn(2, 2, 63), NULL, 0, NULL,
cfg(activation_polling_interval_CFG, "polling_interval", activation_CFG_SECTION, 0, CFG_TYPE_INT, DEFAULT_INTERVAL, vsn(2, 2, 63), NULL, 0, NULL,
"Check pvmove or lvconvert progress at this interval (seconds).\n"
"When pvmove or lvconvert must wait for the kernel to finish\n"
"synchronising or merging data, they check and report progress at\n"
@@ -1696,7 +1628,7 @@ cfg(activation_auto_set_activation_skip_CFG, "auto_set_activation_skip", activat
"flag set. When this setting is enabled, the activation skip flag is\n"
"set on new thin snapshot LVs.\n")
cfg(activation_mode_CFG, "activation_mode", activation_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_ACTIVATION_MODE, vsn(2,2,108), NULL, 0, NULL,
cfg(activation_mode_CFG, "activation_mode", activation_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ACTIVATION_MODE, vsn(2,2,108), NULL, 0, NULL,
"How LVs with missing devices are activated.\n"
"The --activationmode option overrides this setting.\n"
"#\n"
@@ -1793,7 +1725,7 @@ cfg(metadata_pvmetadataignore_CFG, "pvmetadataignore", metadata_CFG_SECTION, CFG
cfg(metadata_stripesize_CFG, "stripesize", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_STRIPESIZE, vsn(1, 0, 0), NULL, 0, NULL, NULL)
cfg_array(metadata_dirs_CFG, "dirs", metadata_CFG_SECTION, CFG_ADVANCED | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL, vsn(2, 3, 0), NULL,
NULL)
"This setting is no longer used.\n")
cfg_section(metadata_disk_areas_CFG_SUBSECTION, "disk_areas", metadata_CFG_SECTION, CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL)
cfg_section(disk_area_CFG_SUBSECTION, "disk_area", metadata_disk_areas_CFG_SUBSECTION, CFG_NAME_VARIABLE | CFG_UNSUPPORTED | CFG_DEFAULT_COMMENTED, vsn(1, 0, 0), vsn(2, 3, 0), NULL, NULL)
@@ -2118,7 +2050,7 @@ cfg(report_two_word_unknown_device_CFG, "two_word_unknown_device", report_CFG_SE
"Use the two words 'unknown device' in place of '[unknown]'.\n"
"This is displayed when the device for a PV is not known.\n")
cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_MIRROR_LIB, vsn(1, 2, 3), NULL, 0, NULL,
cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_MIRROR_LIB, vsn(1, 2, 3), NULL, 0, NULL,
"The library dmeventd uses when monitoring a mirror device.\n"
"libdevmapper-event-lvm2mirror.so attempts to recover from\n"
"failures. It removes failed devices from a volume group and\n"
@@ -2127,13 +2059,13 @@ cfg(dmeventd_mirror_library_CFG, "mirror_library", dmeventd_CFG_SECTION, CFG_DEF
cfg(dmeventd_raid_library_CFG, "raid_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_RAID_LIB, vsn(2, 2, 87), NULL, 0, NULL, NULL)
cfg(dmeventd_snapshot_library_CFG, "snapshot_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_SNAPSHOT_LIB, vsn(1, 2, 26), NULL, 0, NULL,
cfg(dmeventd_snapshot_library_CFG, "snapshot_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_SNAPSHOT_LIB, vsn(1, 2, 26), NULL, 0, NULL,
"The library dmeventd uses when monitoring a snapshot device.\n"
"libdevmapper-event-lvm2snapshot.so monitors the filling of snapshots\n"
"and emits a warning through syslog when the usage exceeds 80%. The\n"
"warning is repeated when 85%, 90% and 95% of the snapshot is filled.\n")
cfg(dmeventd_thin_library_CFG, "thin_library", dmeventd_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_DMEVENTD_THIN_LIB, vsn(2, 2, 89), NULL, 0, NULL,
cfg(dmeventd_thin_library_CFG, "thin_library", dmeventd_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DMEVENTD_THIN_LIB, vsn(2, 2, 89), NULL, 0, NULL,
"The library dmeventd uses when monitoring a thin device.\n"
"libdevmapper-event-lvm2thin.so monitors the filling of a pool\n"
"and emits a warning through syslog when the usage exceeds 80%. The\n"
@@ -2219,4 +2151,4 @@ cfg(local_host_id_CFG, "host_id", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_
"This must be unique among all hosts, and must be between 1 and 2000.\n"
"Applicable only if LVM is compiled with lockd support\n")
cfg(CFG_COUNT, NULL, root_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)
cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL, 0, NULL, NULL)

View File

@@ -42,7 +42,7 @@
#define DEFAULT_DEV_DIR "/dev"
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_SYSTEM_ID_SOURCE "none"
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 0
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 1
#define DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE "none"
#define DEFAULT_SYSFS_SCAN 1
#define DEFAULT_MD_COMPONENT_DETECTION 1
@@ -118,8 +118,6 @@
#define DEFAULT_THIN_REPAIR_OPTION1 ""
#define DEFAULT_THIN_REPAIR_OPTIONS_CONFIG "#S" DEFAULT_THIN_REPAIR_OPTION1
#define DEFAULT_THIN_POOL_METADATA_REQUIRE_SEPARATE_PVS 0
#define DEFAULT_THIN_POOL_CROP_METADATA 0
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE_V1_KB (UINT64_C(255) * ((1 << 14) - 64) * 4) /* KB */ /* 0x3f8040 blocks */
#define DEFAULT_THIN_POOL_MAX_METADATA_SIZE (DM_THIN_MAX_METADATA_SIZE / 2) /* KB */
#define DEFAULT_THIN_POOL_MIN_METADATA_SIZE 2048 /* KB */
#define DEFAULT_THIN_POOL_OPTIMAL_METADATA_SIZE (128 * 1024) /* KB */
@@ -131,7 +129,6 @@
#define DEFAULT_THIN_POOL_DISCARDS "passdown"
#define DEFAULT_THIN_POOL_ZERO 1
#define DEFAULT_POOL_METADATA_SPARE 1 /* thin + cache */
#define DEFAULT_ZERO_METADATA 1 /* thin + cache */
#ifdef CACHE_CHECK_NEEDS_CHECK
# define DEFAULT_CACHE_CHECK_OPTION1 "-q"
@@ -181,7 +178,8 @@
* VDO pool will reverve some sectors in the front and the back of pool device to avoid
* seeing same device twice in the system.
*/
#define DEFAULT_VDO_POOL_HEADER_SIZE_KB (512)
#define DEFAULT_VDO_POOL_HEADER_SIZE (1024) // 512KiB
#define DEFAULT_FSADM_PATH FSADM_PATH
@@ -221,7 +219,7 @@
#endif
#define DEFAULT_COMMAND_LOG_REPORT 0
#define DEFAULT_SYSLOG 0
#define DEFAULT_SYSLOG 1
#define DEFAULT_VERBOSE 0
#define DEFAULT_SILENT 0
#define DEFAULT_LOGLEVEL 0
@@ -322,17 +320,6 @@
#define DEFAULT_MD_COMPONENT_CHECKS "auto"
#define DEFAULT_DEVICES_FILE "system.devices"
#define DEFAULT_SEARCH_FOR_DEVNAMES "auto"
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
#define DEFAULT_EVENT_ACTIVATION_OPTION1 "service_to_event"
#define DEFAULT_EVENT_ACTIVATION_OPTIONS "#S" DEFAULT_EVENT_ACTIVATION_OPTION1
#define PVS_ONLINE_DIR DEFAULT_RUN_DIR "/pvs_online"
#define VGS_ONLINE_DIR DEFAULT_RUN_DIR "/vgs_online"
#define PVS_LOOKUP_DIR DEFAULT_RUN_DIR "/pvs_lookup"
#define DEFAULT_DEVICES_FILE "/etc/lvm/lvm_devices.dat"
#endif /* _LVM_DEFAULTS_H */

View File

@@ -218,7 +218,7 @@ struct dm_list *str_to_str_list(struct dm_pool *mem, const char *str,
return NULL;
}
p1 = str;
p1 = p2 = str;
while (*p1) {
if (!(p2 = strstr(p1, delim)))
next = p2 = str + strlen(str);

View File

@@ -39,32 +39,32 @@ static uint64_t _min(uint64_t lhs, uint64_t rhs)
//----------------------------------------------------------------
void bcache_prefetch_bytes(struct bcache *cache, int di, uint64_t start, size_t len)
void bcache_prefetch_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
{
block_address bb, be;
byte_range_to_block_range(cache, start, len, &bb, &be);
while (bb < be) {
bcache_prefetch(cache, di, bb);
bcache_prefetch(cache, fd, bb);
bb++;
}
}
//----------------------------------------------------------------
bool bcache_read_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data)
bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data)
{
struct block *b;
block_address bb, be;
uint64_t block_size = bcache_block_sectors(cache) << SECTOR_SHIFT;
uint64_t block_offset = start % block_size;
bcache_prefetch_bytes(cache, di, start, len);
bcache_prefetch_bytes(cache, fd, start, len);
byte_range_to_block_range(cache, start, len, &bb, &be);
for (; bb != be; bb++) {
if (!bcache_get(cache, di, bb, 0, &b))
if (!bcache_get(cache, fd, bb, 0, &b))
return false;
size_t blen = _min(block_size - block_offset, len);
@@ -79,7 +79,7 @@ bool bcache_read_bytes(struct bcache *cache, int di, uint64_t start, size_t len,
return true;
}
bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_t len)
bool bcache_invalidate_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
{
block_address bb, be;
bool result = true;
@@ -87,7 +87,7 @@ bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_
byte_range_to_block_range(cache, start, len, &bb, &be);
for (; bb != be; bb++) {
if (!bcache_invalidate(cache, di, bb))
if (!bcache_invalidate(cache, fd, bb))
result = false;
}
@@ -101,8 +101,8 @@ bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_
struct updater;
typedef bool (*partial_update_fn)(struct updater *u, int di, block_address bb, uint64_t offset, size_t len);
typedef bool (*whole_update_fn)(struct updater *u, int di, block_address bb, block_address be);
typedef bool (*partial_update_fn)(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len);
typedef bool (*whole_update_fn)(struct updater *u, int fd, block_address bb, block_address be);
struct updater {
struct bcache *cache;
@@ -111,7 +111,7 @@ struct updater {
void *data;
};
static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len)
static bool _update_bytes(struct updater *u, int fd, uint64_t start, size_t len)
{
struct bcache *cache = u->cache;
block_address bb, be;
@@ -124,12 +124,12 @@ static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len)
// If the last block is partial, we will require a read, so let's
// prefetch it.
if ((start + len) % block_size)
bcache_prefetch(cache, di, (start + len) / block_size);
bcache_prefetch(cache, fd, (start + len) / block_size);
// First block may be partial
if (block_offset) {
size_t blen = _min(block_size - block_offset, len);
if (!u->partial_fn(u, di, bb, block_offset, blen))
if (!u->partial_fn(u, fd, bb, block_offset, blen))
return false;
len -= blen;
@@ -141,7 +141,7 @@ static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len)
// Now we write out a set of whole blocks
nr_whole = len / block_size;
if (!u->whole_fn(u, di, bb, bb + nr_whole))
if (!u->whole_fn(u, fd, bb, bb + nr_whole))
return false;
bb += nr_whole;
@@ -151,29 +151,27 @@ static bool _update_bytes(struct updater *u, int di, uint64_t start, size_t len)
return true;
// Finally we write a partial end block
return u->partial_fn(u, di, bb, 0, len);
return u->partial_fn(u, fd, bb, 0, len);
}
//----------------------------------------------------------------
static bool _write_partial(struct updater *u, int di, block_address bb,
static bool _write_partial(struct updater *u, int fd, block_address bb,
uint64_t offset, size_t len)
{
struct block *b;
if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b))
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
return false;
if (u->data) {
memcpy(((unsigned char *) b->data) + offset, u->data, len);
u->data = ((unsigned char *) u->data) + len;
}
memcpy(((unsigned char *) b->data) + offset, u->data, len);
u->data = ((unsigned char *) u->data) + len;
bcache_put(b);
return true;
}
static bool _write_whole(struct updater *u, int di, block_address bb, block_address be)
static bool _write_whole(struct updater *u, int fd, block_address bb, block_address be)
{
struct block *b;
uint64_t block_size = bcache_block_sectors(u->cache) << SECTOR_SHIFT;
@@ -181,7 +179,7 @@ static bool _write_whole(struct updater *u, int di, block_address bb, block_addr
for (; bb != be; bb++) {
// We don't need to read the block since we are overwriting
// it completely.
if (!bcache_get(u->cache, di, bb, GF_ZERO, &b))
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
return false;
memcpy(b->data, u->data, block_size);
u->data = ((unsigned char *) u->data) + block_size;
@@ -191,7 +189,7 @@ static bool _write_whole(struct updater *u, int di, block_address bb, block_addr
return true;
}
bool bcache_write_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data)
bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data)
{
struct updater u;
@@ -200,16 +198,16 @@ bool bcache_write_bytes(struct bcache *cache, int di, uint64_t start, size_t len
u.whole_fn = _write_whole;
u.data = data;
return _update_bytes(&u, di, start, len);
return _update_bytes(&u, fd, start, len);
}
//----------------------------------------------------------------
static bool _zero_partial(struct updater *u, int di, block_address bb, uint64_t offset, size_t len)
static bool _zero_partial(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len)
{
struct block *b;
if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b))
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
return false;
memset(((unsigned char *) b->data) + offset, 0, len);
@@ -218,12 +216,12 @@ static bool _zero_partial(struct updater *u, int di, block_address bb, uint64_t
return true;
}
static bool _zero_whole(struct updater *u, int di, block_address bb, block_address be)
static bool _zero_whole(struct updater *u, int fd, block_address bb, block_address be)
{
struct block *b;
for (; bb != be; bb++) {
if (!bcache_get(u->cache, di, bb, GF_ZERO, &b))
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
return false;
bcache_put(b);
}
@@ -231,7 +229,7 @@ static bool _zero_whole(struct updater *u, int di, block_address bb, block_addre
return true;
}
bool bcache_zero_bytes(struct bcache *cache, int di, uint64_t start, size_t len)
bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len)
{
struct updater u;
@@ -240,17 +238,17 @@ bool bcache_zero_bytes(struct bcache *cache, int di, uint64_t start, size_t len)
u.whole_fn = _zero_whole;
u.data = NULL;
return _update_bytes(&u, di, start, len);
return _update_bytes(&u, fd, start, len);
}
//----------------------------------------------------------------
static bool _set_partial(struct updater *u, int di, block_address bb, uint64_t offset, size_t len)
static bool _set_partial(struct updater *u, int fd, block_address bb, uint64_t offset, size_t len)
{
struct block *b;
uint8_t val = (u->data) ? *((uint8_t *) u->data) : 0;
uint8_t val = *((uint8_t *) u->data);
if (!bcache_get(u->cache, di, bb, GF_DIRTY, &b))
if (!bcache_get(u->cache, fd, bb, GF_DIRTY, &b))
return false;
memset(((unsigned char *) b->data) + offset, val, len);
@@ -259,14 +257,14 @@ static bool _set_partial(struct updater *u, int di, block_address bb, uint64_t o
return true;
}
static bool _set_whole(struct updater *u, int di, block_address bb, block_address be)
static bool _set_whole(struct updater *u, int fd, block_address bb, block_address be)
{
struct block *b;
uint8_t val = (u->data) ? *((uint8_t *) u->data) : 0;
uint8_t val = *((uint8_t *) u->data);
uint64_t len = bcache_block_sectors(u->cache) * 512;
for (; bb != be; bb++) {
if (!bcache_get(u->cache, di, bb, GF_ZERO, &b))
if (!bcache_get(u->cache, fd, bb, GF_ZERO, &b))
return false;
memset((unsigned char *) b->data, val, len);
bcache_put(b);
@@ -275,7 +273,7 @@ static bool _set_whole(struct updater *u, int di, block_address bb, block_addres
return true;
}
bool bcache_set_bytes(struct bcache *cache, int di, uint64_t start, size_t len, uint8_t val)
bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val)
{
struct updater u;
@@ -284,6 +282,6 @@ bool bcache_set_bytes(struct bcache *cache, int di, uint64_t start, size_t len,
u.whole_fn = _set_whole;
u.data = &val;
return _update_bytes(&u, di, start, len);
return _update_bytes(&u, fd, start, len);
}

View File

@@ -33,16 +33,11 @@
#define SECTOR_SHIFT 9L
#define FD_TABLE_INC 1024
static int _fd_table_size;
static int *_fd_table;
//----------------------------------------------------------------
static void log_sys_warn(const char *call)
{
log_warn("WARNING: %s failed: %s.", call, strerror(errno));
log_warn("%s failed: %s", call, strerror(errno));
}
// Assumes the list is not empty.
@@ -66,17 +61,23 @@ struct control_block {
struct cb_set {
struct dm_list free;
struct dm_list allocated;
struct control_block vec[];
struct control_block *vec;
} control_block_set;
static struct cb_set *_cb_set_create(unsigned nr)
{
unsigned i;
struct cb_set *cbs = malloc(sizeof(*cbs) + nr * sizeof(*cbs->vec));
int i;
struct cb_set *cbs = malloc(sizeof(*cbs));
if (!cbs)
return NULL;
cbs->vec = malloc(nr * sizeof(*cbs->vec));
if (!cbs->vec) {
free(cbs);
return NULL;
}
dm_list_init(&cbs->free);
dm_list_init(&cbs->allocated);
@@ -92,10 +93,11 @@ static void _cb_set_destroy(struct cb_set *cbs)
// never be in flight IO.
if (!dm_list_empty(&cbs->allocated)) {
// bail out
log_warn("WARNING: async io still in flight.");
log_error("async io still in flight");
return;
}
free(cbs->vec);
free(cbs);
}
@@ -153,11 +155,11 @@ static void _async_destroy(struct io_engine *ioe)
free(e);
}
static int _last_byte_di;
static int _last_byte_fd;
static uint64_t _last_byte_offset;
static int _last_byte_sector_size;
static bool _async_issue(struct io_engine *ioe, enum dir d, int di,
static bool _async_issue(struct io_engine *ioe, enum dir d, int fd,
sector_t sb, sector_t se, void *data, void *context)
{
int r;
@@ -181,7 +183,7 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int di,
/*
* If bcache block goes past where lvm wants to write, then clamp it.
*/
if ((d == DIR_WRITE) && _last_byte_offset && (di == _last_byte_di)) {
if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) {
if (offset > _last_byte_offset) {
log_error("Limit write at %llu len %llu beyond last byte %llu",
(unsigned long long)offset,
@@ -266,7 +268,7 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int di,
memset(&cb->cb, 0, sizeof(cb->cb));
cb->cb.aio_fildes = (int) _fd_table[di];
cb->cb.aio_fildes = (int) fd;
cb->cb.u.c.buf = data;
cb->cb.u.c.offset = offset;
cb->cb.u.c.nbytes = nbytes;
@@ -274,15 +276,13 @@ static bool _async_issue(struct io_engine *ioe, enum dir d, int di,
#if 0
if (d == DIR_READ) {
log_debug("io R off %llu bytes %llu di %d fd %d",
log_debug("io R off %llu bytes %llu",
(unsigned long long)cb->cb.u.c.offset,
(unsigned long long)cb->cb.u.c.nbytes,
di, _fd_table[di]);
(unsigned long long)cb->cb.u.c.nbytes);
} else {
log_debug("io W off %llu bytes %llu di %d fd %d",
log_debug("io W off %llu bytes %llu",
(unsigned long long)cb->cb.u.c.offset,
(unsigned long long)cb->cb.u.c.nbytes,
di, _fd_table[di]);
(unsigned long long)cb->cb.u.c.nbytes);
}
#endif
@@ -318,7 +318,9 @@ static bool _async_wait(struct io_engine *ioe, io_complete_fn fn)
struct async_engine *e = _to_async(ioe);
memset(&event, 0, sizeof(event));
r = io_getevents(e->aio_context, 1, MAX_EVENT, event, NULL);
do {
r = io_getevents(e->aio_context, 1, MAX_EVENT, event, NULL);
} while (r == -EINTR);
if (r < 0) {
log_sys_warn("io_getevents");
@@ -358,16 +360,10 @@ static unsigned _async_max_io(struct io_engine *e)
struct io_engine *create_async_io_engine(void)
{
static int _pagesize = 0;
int r;
struct async_engine *e;
struct async_engine *e = malloc(sizeof(*e));
if ((_pagesize <= 0) && (_pagesize = sysconf(_SC_PAGESIZE)) < 0) {
log_warn("_SC_PAGESIZE returns negative value.");
return NULL;
}
if (!(e = malloc(sizeof(*e))))
if (!e)
return NULL;
e->e.destroy = _async_destroy;
@@ -390,9 +386,8 @@ struct io_engine *create_async_io_engine(void)
return NULL;
}
e->page_mask = (unsigned) _pagesize - 1;
e->page_mask = sysconf(_SC_PAGESIZE) - 1;
/* coverity[leaked_storage] 'e' is not leaking */
return &e->e;
}
@@ -419,7 +414,7 @@ static void _sync_destroy(struct io_engine *ioe)
free(e);
}
static bool _sync_issue(struct io_engine *ioe, enum dir d, int di,
static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
sector_t sb, sector_t se, void *data, void *context)
{
int rv;
@@ -435,7 +430,7 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int di,
}
where = sb * 512;
off = lseek(_fd_table[di], where, SEEK_SET);
off = lseek(fd, where, SEEK_SET);
if (off == (off_t) -1) {
log_warn("Device seek error %d for offset %llu", errno, (unsigned long long)where);
free(io);
@@ -450,7 +445,7 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int di,
/*
* If bcache block goes past where lvm wants to write, then clamp it.
*/
if ((d == DIR_WRITE) && _last_byte_offset && (di == _last_byte_di)) {
if ((d == DIR_WRITE) && _last_byte_offset && (fd == _last_byte_fd)) {
uint64_t offset = where;
uint64_t nbytes = len;
sector_t limit_nbytes = 0;
@@ -531,9 +526,9 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int di,
while (pos < len) {
if (d == DIR_READ)
rv = read(_fd_table[di], (char *)data + pos, len - pos);
rv = read(fd, (char *)data + pos, len - pos);
else
rv = write(_fd_table[di], (char *)data + pos, len - pos);
rv = write(fd, (char *)data + pos, len - pos);
if (rv == -1 && errno == EINTR)
continue;
@@ -607,8 +602,7 @@ struct io_engine *create_sync_io_engine(void)
e->e.wait = _sync_wait;
e->e.max_io = _sync_max_io;
dm_list_init(&e->complete);
/* coverity[leaked_storage] 'e' is not leaking */
dm_list_init(&e->complete);
return &e->e;
}
@@ -694,7 +688,7 @@ struct bcache {
//----------------------------------------------------------------
struct key_parts {
uint32_t di;
uint32_t fd;
uint64_t b;
} __attribute__ ((packed));
@@ -703,12 +697,12 @@ union key {
uint8_t bytes[12];
};
static struct block *_block_lookup(struct bcache *cache, int di, uint64_t i)
static struct block *_block_lookup(struct bcache *cache, int fd, uint64_t i)
{
union key k;
union radix_value v;
k.parts.di = di;
k.parts.fd = fd;
k.parts.b = i;
if (radix_tree_lookup(cache->rtree, k.bytes, k.bytes + sizeof(k.bytes), &v))
@@ -722,7 +716,7 @@ static bool _block_insert(struct block *b)
union key k;
union radix_value v;
k.parts.di = b->di;
k.parts.fd = b->fd;
k.parts.b = b->index;
v.ptr = b;
@@ -733,10 +727,10 @@ static void _block_remove(struct block *b)
{
union key k;
k.parts.di = b->di;
k.parts.fd = b->fd;
k.parts.b = b->index;
(void) radix_tree_remove(b->cache->rtree, k.bytes, k.bytes + sizeof(k.bytes));
radix_tree_remove(b->cache->rtree, k.bytes, k.bytes + sizeof(k.bytes));
}
//----------------------------------------------------------------
@@ -875,7 +869,7 @@ static void _issue_low_level(struct block *b, enum dir d)
dm_list_move(&cache->io_pending, &b->list);
if (!cache->engine->issue(cache->engine, d, b->di, sb, se, b->data, b)) {
if (!cache->engine->issue(cache->engine, d, b->fd, sb, se, b->data, b)) {
/* FIXME: if io_submit() set an errno, return that instead of EIO? */
_complete_io(b, -EIO);
return;
@@ -951,26 +945,21 @@ static struct block *_find_unused_clean_block(struct bcache *cache)
return NULL;
}
static struct block *_new_block(struct bcache *cache, int di, block_address i, bool can_wait)
static struct block *_new_block(struct bcache *cache, int fd, block_address i, bool can_wait)
{
struct block *b;
b = _alloc_block(cache);
while (!b) {
while (!b && !dm_list_empty(&cache->clean)) {
b = _find_unused_clean_block(cache);
if (!b) {
if (can_wait) {
if (dm_list_empty(&cache->io_pending))
_writeback(cache, 16); // FIXME: magic number
_wait_all(cache);
if (dm_list_size(&cache->errored) >= cache->max_io) {
log_debug("bcache no new blocks for di %d index %u with >%d errors.",
di, (uint32_t) i, cache->max_io);
return NULL;
}
_wait_io(cache);
} else {
log_debug("bcache no new blocks for di %d index %u",
di, (uint32_t) i);
log_debug("bcache no new blocks for fd %d index %u",
fd, (uint32_t) i);
return NULL;
}
}
@@ -979,7 +968,7 @@ static struct block *_new_block(struct bcache *cache, int di, block_address i, b
if (b) {
dm_list_init(&b->list);
b->flags = 0;
b->di = di;
b->fd = fd;
b->index = i;
b->ref_count = 0;
b->error = 0;
@@ -1025,10 +1014,10 @@ static void _miss(struct bcache *cache, unsigned flags)
}
static struct block *_lookup_or_read_block(struct bcache *cache,
int di, block_address i,
int fd, block_address i,
unsigned flags)
{
struct block *b = _block_lookup(cache, di, i);
struct block *b = _block_lookup(cache, fd, i);
if (b) {
// FIXME: this is insufficient. We need to also catch a read
@@ -1053,7 +1042,7 @@ static struct block *_lookup_or_read_block(struct bcache *cache,
} else {
_miss(cache, flags);
b = _new_block(cache, di, i, true);
b = _new_block(cache, fd, i, true);
if (b) {
if (flags & GF_ZERO)
_zero_block(b);
@@ -1095,12 +1084,11 @@ static void _preemptive_writeback(struct bcache *cache)
struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks,
struct io_engine *engine)
{
static long _pagesize = 0;
struct bcache *cache;
unsigned max_io = engine->max_io(engine);
int i;
long pgsize = sysconf(_SC_PAGESIZE);
if ((_pagesize <= 0) && ((_pagesize = sysconf(_SC_PAGESIZE)) < 0)) {
if (pgsize < 0) {
log_warn("WARNING: _SC_PAGESIZE returns negative value.");
return NULL;
}
@@ -1115,7 +1103,7 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks,
return NULL;
}
if (block_sectors & ((_pagesize >> SECTOR_SHIFT) - 1)) {
if (block_sectors & ((pgsize >> SECTOR_SHIFT) - 1)) {
log_warn("bcache block size must be a multiple of page size");
return NULL;
}
@@ -1152,25 +1140,13 @@ struct bcache *bcache_create(sector_t block_sectors, unsigned nr_cache_blocks,
cache->write_misses = 0;
cache->prefetches = 0;
if (!_init_free_list(cache, nr_cache_blocks, _pagesize)) {
if (!_init_free_list(cache, nr_cache_blocks, pgsize)) {
cache->engine->destroy(cache->engine);
radix_tree_destroy(cache->rtree);
free(cache);
return NULL;
}
_fd_table_size = FD_TABLE_INC;
if (!(_fd_table = malloc(sizeof(int) * _fd_table_size))) {
cache->engine->destroy(cache->engine);
radix_tree_destroy(cache->rtree);
free(cache);
return NULL;
}
for (i = 0; i < _fd_table_size; i++)
_fd_table[i] = -1;
return cache;
}
@@ -1186,9 +1162,6 @@ void bcache_destroy(struct bcache *cache)
radix_tree_destroy(cache->rtree);
cache->engine->destroy(cache->engine);
free(cache);
free(_fd_table);
_fd_table = NULL;
_fd_table_size = 0;
}
sector_t bcache_block_sectors(struct bcache *cache)
@@ -1206,13 +1179,13 @@ unsigned bcache_max_prefetches(struct bcache *cache)
return cache->max_io;
}
void bcache_prefetch(struct bcache *cache, int di, block_address i)
void bcache_prefetch(struct bcache *cache, int fd, block_address i)
{
struct block *b = _block_lookup(cache, di, i);
struct block *b = _block_lookup(cache, fd, i);
if (!b) {
if (cache->nr_io_pending < cache->max_io) {
b = _new_block(cache, di, i, false);
b = _new_block(cache, fd, i, false);
if (b) {
cache->prefetches++;
_issue_read(b);
@@ -1230,15 +1203,12 @@ static void _recycle_block(struct bcache *cache, struct block *b)
_free_block(b);
}
bool bcache_get(struct bcache *cache, int di, block_address i,
bool bcache_get(struct bcache *cache, int fd, block_address i,
unsigned flags, struct block **result)
{
struct block *b;
if (di >= _fd_table_size)
goto bad;
b = _lookup_or_read_block(cache, di, i, flags);
b = _lookup_or_read_block(cache, fd, i, flags);
if (b) {
if (b->error) {
if (b->io_dir == DIR_READ) {
@@ -1257,10 +1227,10 @@ bool bcache_get(struct bcache *cache, int di, block_address i,
*result = b;
return true;
}
bad:
*result = NULL;
log_error("bcache failed to get block %u di %d", (uint32_t) i, di);
log_error("bcache failed to get block %u fd %d", (uint32_t) i, fd);
return false;
}
@@ -1324,7 +1294,7 @@ static bool _invalidate_block(struct bcache *cache, struct block *b)
if (b->ref_count) {
log_warn("bcache_invalidate: block (%d, %llu) still held",
b->di, (unsigned long long) b->index);
b->fd, (unsigned long long) b->index);
return false;
}
@@ -1341,9 +1311,9 @@ static bool _invalidate_block(struct bcache *cache, struct block *b)
return true;
}
bool bcache_invalidate(struct bcache *cache, int di, block_address i)
bool bcache_invalidate(struct bcache *cache, int fd, block_address i)
{
return _invalidate_block(cache, _block_lookup(cache, di, i));
return _invalidate_block(cache, _block_lookup(cache, fd, i));
}
//----------------------------------------------------------------
@@ -1359,27 +1329,27 @@ static bool _writeback_v(struct radix_tree_iterator *it,
struct block *b = v.ptr;
if (_test_flags(b, BF_DIRTY))
_issue_write(b);
_issue_write(b);
return true;
return true;
}
static bool _invalidate_v(struct radix_tree_iterator *it,
uint8_t *kb, uint8_t *ke, union radix_value v)
{
struct block *b = v.ptr;
struct invalidate_iterator *iit = container_of(it, struct invalidate_iterator, it);
struct invalidate_iterator *iit = container_of(it, struct invalidate_iterator, it);
if (b->error || _test_flags(b, BF_DIRTY)) {
log_warn("WARNING: bcache_invalidate: block (%d, %llu) still dirty.",
b->di, (unsigned long long) b->index);
iit->success = false;
return true;
log_warn("bcache_invalidate: block (%d, %llu) still dirty",
b->fd, (unsigned long long) b->index);
iit->success = false;
return true;
}
if (b->ref_count) {
log_warn("WARNING: bcache_invalidate: block (%d, %llu) still held.",
b->di, (unsigned long long) b->index);
log_warn("bcache_invalidate: block (%d, %llu) still held",
b->fd, (unsigned long long) b->index);
iit->success = false;
return true;
}
@@ -1392,24 +1362,24 @@ static bool _invalidate_v(struct radix_tree_iterator *it,
return true;
}
bool bcache_invalidate_di(struct bcache *cache, int di)
bool bcache_invalidate_fd(struct bcache *cache, int fd)
{
union key k;
union key k;
struct invalidate_iterator it;
k.parts.di = di;
k.parts.fd = fd;
it.it.visit = _writeback_v;
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it.it);
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), &it.it);
_wait_all(cache);
it.success = true;
it.it.visit = _invalidate_v;
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it.it);
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), &it.it);
if (it.success)
(void) radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di));
radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd));
return it.success;
}
@@ -1423,7 +1393,7 @@ static bool _abort_v(struct radix_tree_iterator *it,
if (b->ref_count) {
log_fatal("bcache_abort: block (%d, %llu) still held",
b->di, (unsigned long long) b->index);
b->fd, (unsigned long long) b->index);
return true;
}
@@ -1435,94 +1405,35 @@ static bool _abort_v(struct radix_tree_iterator *it,
return true;
}
void bcache_abort_di(struct bcache *cache, int di)
void bcache_abort_fd(struct bcache *cache, int fd)
{
union key k;
union key k;
struct radix_tree_iterator it;
k.parts.di = di;
k.parts.fd = fd;
it.visit = _abort_v;
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di), &it);
(void) radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.di));
radix_tree_iterate(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd), &it);
radix_tree_remove_prefix(cache->rtree, k.bytes, k.bytes + sizeof(k.parts.fd));
}
//----------------------------------------------------------------
void bcache_set_last_byte(struct bcache *cache, int di, uint64_t offset, int sector_size)
void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size)
{
_last_byte_di = di;
_last_byte_fd = fd;
_last_byte_offset = offset;
_last_byte_sector_size = sector_size;
if (!sector_size)
_last_byte_sector_size = 512;
}
void bcache_unset_last_byte(struct bcache *cache, int di)
void bcache_unset_last_byte(struct bcache *cache, int fd)
{
if (_last_byte_di == di) {
_last_byte_di = 0;
if (_last_byte_fd == fd) {
_last_byte_fd = 0;
_last_byte_offset = 0;
_last_byte_sector_size = 0;
}
}
int bcache_set_fd(int fd)
{
int *new_table = NULL;
int new_size = 0;
int i;
retry:
for (i = 0; i < _fd_table_size; i++) {
if (_fd_table[i] == -1) {
_fd_table[i] = fd;
return i;
}
}
/* already tried once, shouldn't happen */
if (new_size)
return -1;
new_size = _fd_table_size + FD_TABLE_INC;
new_table = realloc(_fd_table, sizeof(int) * new_size);
if (!new_table) {
log_error("Cannot extend bcache fd table");
return -1;
}
for (i = _fd_table_size; i < new_size; i++)
new_table[i] = -1;
_fd_table = new_table;
_fd_table_size = new_size;
goto retry;
}
/*
* Should we check for unflushed or inprogress io on an fd
* prior to doing clear_fd or change_fd? (To catch mistakes;
* the caller should be smart enough to not do that.)
*/
void bcache_clear_fd(int di)
{
if (di >= _fd_table_size)
return;
_fd_table[di] = -1;
}
int bcache_change_fd(int di, int fd)
{
if (di >= _fd_table_size)
return 0;
if (di < 0) {
log_error(INTERNAL_ERROR "Cannot change not opened DI with FD:%d", fd);
return 0;
}
_fd_table[di] = fd;
return 1;
}

View File

@@ -34,7 +34,7 @@ typedef void io_complete_fn(void *context, int io_error);
struct io_engine {
void (*destroy)(struct io_engine *e);
bool (*issue)(struct io_engine *e, enum dir d, int di,
bool (*issue)(struct io_engine *e, enum dir d, int fd,
sector_t sb, sector_t se, void *data, void *context);
bool (*wait)(struct io_engine *e, io_complete_fn fn);
unsigned (*max_io)(struct io_engine *e);
@@ -48,7 +48,7 @@ struct io_engine *create_sync_io_engine(void);
struct bcache;
struct block {
/* clients may only access these three fields */
int di;
int fd;
uint64_t index;
void *data;
@@ -106,12 +106,12 @@ unsigned bcache_max_prefetches(struct bcache *cache);
* they complete. But we're talking a very small difference, and it's worth it
* to keep callbacks out of this interface.
*/
void bcache_prefetch(struct bcache *cache, int di, block_address index);
void bcache_prefetch(struct bcache *cache, int fd, block_address index);
/*
* Returns true on success.
*/
bool bcache_get(struct bcache *cache, int di, block_address index,
bool bcache_get(struct bcache *cache, int fd, block_address index,
unsigned flags, struct block **result);
void bcache_put(struct block *b);
@@ -129,42 +129,38 @@ bool bcache_flush(struct bcache *cache);
*
* If the block is currently held false will be returned.
*/
bool bcache_invalidate(struct bcache *cache, int di, block_address index);
bool bcache_invalidate(struct bcache *cache, int fd, block_address index);
/*
* Invalidates all blocks on the given descriptor. Call this before closing
* the descriptor to make sure everything is written back.
*/
bool bcache_invalidate_di(struct bcache *cache, int di);
bool bcache_invalidate_fd(struct bcache *cache, int fd);
/*
* Call this function if flush, or invalidate fail and you do not
* wish to retry the writes. This will throw away any dirty data
* not written. If any blocks for di are held, then it will call
* not written. If any blocks for fd are held, then it will call
* abort().
*/
void bcache_abort_di(struct bcache *cache, int di);
void bcache_abort_fd(struct bcache *cache, int fd);
//----------------------------------------------------------------
// The next four functions are utilities written in terms of the above api.
// Prefetches the blocks neccessary to satisfy a byte range.
void bcache_prefetch_bytes(struct bcache *cache, int di, uint64_t start, size_t len);
void bcache_prefetch_bytes(struct bcache *cache, int fd, uint64_t start, size_t len);
// Reads, writes and zeroes bytes. Returns false if errors occur.
bool bcache_read_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data);
bool bcache_write_bytes(struct bcache *cache, int di, uint64_t start, size_t len, void *data);
bool bcache_zero_bytes(struct bcache *cache, int di, uint64_t start, size_t len);
bool bcache_set_bytes(struct bcache *cache, int di, uint64_t start, size_t len, uint8_t val);
bool bcache_invalidate_bytes(struct bcache *cache, int di, uint64_t start, size_t len);
bool bcache_read_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data);
bool bcache_write_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, void *data);
bool bcache_zero_bytes(struct bcache *cache, int fd, uint64_t start, size_t len);
bool bcache_set_bytes(struct bcache *cache, int fd, uint64_t start, size_t len, uint8_t val);
bool bcache_invalidate_bytes(struct bcache *cache, int fd, uint64_t start, size_t len);
void bcache_set_last_byte(struct bcache *cache, int di, uint64_t offset, int sector_size);
void bcache_unset_last_byte(struct bcache *cache, int di);
void bcache_set_last_byte(struct bcache *cache, int fd, uint64_t offset, int sector_size);
void bcache_unset_last_byte(struct bcache *cache, int fd);
//----------------------------------------------------------------
int bcache_set_fd(int fd); /* returns di */
void bcache_clear_fd(int di);
int bcache_change_fd(int di, int fd);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,7 @@ struct cmd_context;
struct dev_filter {
int (*passes_filter) (struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name);
void (*destroy) (struct dev_filter *f);
void (*wipe) (struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name);
void (*wipe) (struct dev_filter *f);
void *private;
unsigned use_count;
const char *name;
@@ -48,16 +48,15 @@ int dev_cache_exit(void);
*/
int dev_cache_check_for_open_devices(void);
void dev_cache_scan(struct cmd_context *cmd);
void dev_cache_scan(void);
int dev_cache_has_scanned(void);
int dev_cache_add_dir(const char *path);
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f);
const char *dev_cache_filtered_reason(const char *name);
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t device, struct dev_filter *f, int *filtered);
struct device *dev_hash_get(const char *name);
void dev_set_preferred_name(struct dm_str_list *sl, struct device *dev);
/*
@@ -68,20 +67,14 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int unused);
void dev_iter_destroy(struct dev_iter *iter);
struct device *dev_iter_get(struct cmd_context *cmd, struct dev_iter *iter);
void dev_reset_error_count(struct cmd_context *cmd);
void dev_cache_failed_path(struct device *dev, const char *path);
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt);
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value);
int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
int setup_devices_file(struct cmd_context *cmd);
int setup_devices(struct cmd_context *cmd);
int setup_device(struct cmd_context *cmd, const char *devname);
/* Normal device setup functions are split up for pvscan optimization. */
int setup_devices_for_pvscan_cache(struct cmd_context *cmd);
int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname);
int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno);
void setup_devices(struct cmd_context *cmd);
#endif

View File

@@ -81,7 +81,7 @@ typedef struct dasd_information2_t {
int dasd_is_cdl_formatted(struct device *dev)
{
int ret = 0;
dasd_information2_t dasd_info2 = { 0 };
dasd_information2_t dasd_info2;
if (!dev_open_readonly(dev))
return_0;

View File

@@ -104,9 +104,9 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
}
if (ioctl(fd, BLKGETSIZE64, size) < 0) {
log_warn("WARNING: %s: ioctl BLKGETSIZE64 %s", name, strerror(errno));
log_sys_error("ioctl BLKGETSIZE64", name);
if (do_close && !dev_close_immediate(dev))
stack;
log_sys_error("close", name);
return 0;
}
@@ -117,14 +117,14 @@ static int _dev_get_size_dev(struct device *dev, uint64_t *size)
log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size);
if (do_close && !dev_close_immediate(dev))
stack;
log_sys_error("close", name);
return 1;
}
static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
{
long read_ahead_long = 0;
long read_ahead_long;
if (dev->read_ahead != -1) {
*read_ahead = (uint32_t) dev->read_ahead;
@@ -132,13 +132,12 @@ static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead)
}
if (!dev_open_readonly_quiet(dev)) {
log_warn("WARNING: Failed to open %s to get readahead %s.",
dev_name(dev), strerror(errno));
return 0;
log_error("Failed to open to get readahead %s", dev_name(dev));
return_0;
}
if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) {
log_warn("WARNING: %s: ioctl BLKRAGET %s.", dev_name(dev), strerror(errno));
log_sys_error("ioctl BLKRAGET", dev_name(dev));
if (!dev_close_immediate(dev))
stack;
return 0;
@@ -171,7 +170,7 @@ static int _dev_discard_blocks(struct device *dev, uint64_t offset_bytes, uint64
test_mode() ? " (test mode - suppressed)" : "");
if (!test_mode() && ioctl(dev->fd, BLKDISCARD, &discard_range) < 0) {
log_warn("WARNING: %s: ioctl BLKDISCARD at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
log_error("%s: BLKDISCARD ioctl at offset %" PRIu64 " size %" PRIu64 " failed: %s.",
dev_name(dev), offset_bytes, size_bytes, strerror(errno));
if (!dev_close_immediate(dev))
stack;
@@ -380,10 +379,8 @@ int dev_open_flags(struct device *dev, int flags, int direct, int quiet)
return 0;
}
#if defined(O_NOATIME) || defined(O_DIRECT_SUPPORT)
opened:
#endif
#ifdef O_DIRECT_SUPPORT
opened:
if (direct)
dev->flags |= DEV_O_DIRECT_TESTED;
#endif
@@ -452,7 +449,7 @@ int dev_open_readonly_quiet(struct device *dev)
static void _close(struct device *dev)
{
if (close(dev->fd))
log_sys_debug("close", dev_name(dev));
log_sys_error("close", dev_name(dev));
dev->fd = -1;
log_debug_devs("Closed %s", dev_name(dev));

View File

@@ -18,7 +18,7 @@
#define LUKS_SIGNATURE "LUKS\xba\xbe"
#define LUKS_SIGNATURE_SIZE 6
int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full)
int dev_is_luks(struct device *dev, uint64_t *offset_found, int full)
{
char buf[LUKS_SIGNATURE_SIZE];
int ret = -1;

View File

@@ -16,8 +16,6 @@
#include "lib/misc/lib.h"
#include "lib/device/dev-type.h"
#include "lib/mm/xlate.h"
#include "lib/misc/crc.h"
#include "lib/commands/toolcontext.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h> /* for MD detection using udev db records */
#include "lib/device/dev-ext-udev-constants.h"
@@ -50,122 +48,79 @@ static int _dev_has_md_magic(struct device *dev, uint64_t sb_offset)
return 0;
}
#define IMSM_SIGNATURE "Intel Raid ISM Cfg Sig. "
#define IMSM_SIG_LEN (sizeof(IMSM_SIGNATURE) - 1)
/*
* Calculate the position of the superblock.
* It is always aligned to a 4K boundary and
* depending on minor_version, it can be:
* 0: At least 8K, but less than 12K, from end of device
* 1: At start of device
* 2: 4K from start of device.
*/
typedef enum {
MD_MINOR_VERSION_MIN,
MD_MINOR_V0 = MD_MINOR_VERSION_MIN,
MD_MINOR_V1,
MD_MINOR_V2,
MD_MINOR_VERSION_MAX = MD_MINOR_V2
} md_minor_version_t;
static int _dev_has_imsm_magic(struct device *dev, uint64_t devsize_sectors)
static uint64_t _v1_sb_offset(uint64_t size, md_minor_version_t minor_version)
{
char imsm_signature[IMSM_SIG_LEN];
uint64_t off;
unsigned int physical_block_size = 0;
unsigned int logical_block_size = 0;
uint64_t sb_offset;
if (!dev_get_direct_block_sizes(dev, &physical_block_size, &logical_block_size))
return_0;
if (logical_block_size == 4096)
off = (devsize_sectors * 512) - 8192;
else
off = (devsize_sectors * 512) - 1024;
if (!dev_read_bytes(dev, off, IMSM_SIG_LEN, imsm_signature))
return_0;
if (!memcmp(imsm_signature, IMSM_SIGNATURE, IMSM_SIG_LEN))
return 1;
return 0;
}
#define DDF_MAGIC 0xDE11DE11
struct ddf_header {
uint32_t magic;
uint32_t crc;
char guid[24];
char revision[8];
char padding[472];
};
static int _dev_has_ddf_magic(struct device *dev, uint64_t devsize_sectors, uint64_t *sb_offset)
{
struct ddf_header hdr;
uint32_t crc, our_crc;
uint64_t off;
uint64_t devsize_bytes = devsize_sectors * 512;
if (devsize_bytes < 0x30000)
switch(minor_version) {
case MD_MINOR_V0:
sb_offset = (size - 8 * 2) & ~(4 * 2 - 1ULL);
break;
case MD_MINOR_V1:
sb_offset = 0;
break;
case MD_MINOR_V2:
sb_offset = 4 * 2;
break;
default:
log_warn(INTERNAL_ERROR "WARNING: Unknown minor version %d.",
minor_version);
return 0;
/* 512 bytes before the end of device (from libblkid) */
off = ((devsize_bytes / 0x200) - 1) * 0x200;
if (!dev_read_bytes(dev, off, 512, &hdr))
return_0;
if ((hdr.magic == cpu_to_be32(DDF_MAGIC)) ||
(hdr.magic == cpu_to_le32(DDF_MAGIC))) {
crc = hdr.crc;
hdr.crc = 0xffffffff;
our_crc = calc_crc(0, (const uint8_t *)&hdr, 512);
if ((cpu_to_be32(our_crc) == crc) ||
(cpu_to_le32(our_crc) == crc)) {
*sb_offset = off;
return 1;
} else {
log_debug_devs("Found md ddf magic at %llu wrong crc %x disk %x %s",
(unsigned long long)off, our_crc, crc, dev_name(dev));
return 0;
}
}
sb_offset <<= SECTOR_SHIFT;
/* 128KB before the end of device (from libblkid) */
off = ((devsize_bytes / 0x200) - 257) * 0x200;
if (!dev_read_bytes(dev, off, 512, &hdr))
return_0;
if ((hdr.magic == cpu_to_be32(DDF_MAGIC)) ||
(hdr.magic == cpu_to_le32(DDF_MAGIC))) {
crc = hdr.crc;
hdr.crc = 0xffffffff;
our_crc = calc_crc(0, (const uint8_t *)&hdr, 512);
if ((cpu_to_be32(our_crc) == crc) ||
(cpu_to_le32(our_crc) == crc)) {
*sb_offset = off;
return 1;
} else {
log_debug_devs("Found md ddf magic at %llu wrong crc %x disk %x %s",
(unsigned long long)off, our_crc, crc, dev_name(dev));
return 0;
}
}
return 0;
return sb_offset;
}
/*
* _udev_dev_is_md_component() only works if
* external_device_info_source="udev"
*
* but
*
* udev_dev_is_md_component() in dev-type.c only works if
* obtain_device_list_from_udev=1
*
* and neither of those config setting matches very well
* with what we're doing here.
*/
#ifdef UDEV_SYNC_SUPPORT
static int _dev_is_md_component_udev(struct device *dev)
static int _udev_dev_is_md_component(struct device *dev)
{
const char *value;
struct dev_ext *ext;
/*
* external_device_info_source="udev" enables these udev checks.
* external_device_info_source="none" disables them.
*/
if (!(ext = dev_ext_get(dev)))
return_0;
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE)))
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE))) {
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
return !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID);
}
#else
static int _dev_is_md_component_udev(struct device *dev)
static int _udev_dev_is_md_component(struct device *dev)
{
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
#endif
@@ -173,16 +128,14 @@ static int _dev_is_md_component_udev(struct device *dev)
/*
* Returns -1 on error
*/
static int _dev_is_md_component_native(struct device *dev, uint64_t *offset_found, int full)
static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
{
uint64_t size, sb_offset = 0;
md_minor_version_t minor;
uint64_t size, sb_offset;
int ret;
/* i/o layer has not been set up */
if (!scan_bcache) {
log_error(INTERNAL_ERROR "dev_is_md_component_native requires io layer.");
return -1;
}
if (!scan_bcache)
return -EAGAIN;
if (!dev_get_size(dev, &size)) {
stack;
@@ -193,9 +146,9 @@ static int _dev_is_md_component_native(struct device *dev, uint64_t *offset_foun
return 0;
/*
* Some md versions locate the magic number at the end of the device.
* Those checks can't be satisfied with the initial scan data, and
* require an extra read i/o at the end of every device. Issuing
* Old md versions locate the magic number at the end of the device.
* Those checks can't be satisfied with the initial bcache data, and
* would require an extra read i/o at the end of every device. Issuing
* an extra read to every device in every command, just to check for
* the old md format is a bad tradeoff.
*
@@ -206,81 +159,42 @@ static int _dev_is_md_component_native(struct device *dev, uint64_t *offset_foun
* and set it for commands that could possibly write to an md dev
* (pvcreate/vgcreate/vgextend).
*/
/*
* md superblock version 1.1 at offset 0 from start
*/
if (_dev_has_md_magic(dev, 0)) {
log_debug_devs("Found md magic number at offset 0 of %s.", dev_name(dev));
ret = 1;
goto out;
}
/*
* md superblock version 1.2 at offset 4KB from start
*/
if (_dev_has_md_magic(dev, 4096)) {
log_debug_devs("Found md magic number at offset 4096 of %s.", dev_name(dev));
ret = 1;
goto out;
}
if (!full) {
sb_offset = 0;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset 0 of %s.", dev_name(dev));
ret = 1;
goto out;
}
sb_offset = 8 << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset %d of %s.", (int)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
ret = 0;
goto out;
}
/*
* Handle superblocks at the end of the device.
*/
/*
* md superblock version 0 at 64KB from end of device
* (after end is aligned to 64KB)
*/
/* Check if it is an md component device. */
/* Version 0.90.0 */
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset %llu of %s.", (unsigned long long)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
/*
* md superblock version 1.0 at 8KB from end of device
*/
sb_offset = ((size - 8 * 2) & ~(4 * 2 - 1ULL)) << SECTOR_SHIFT;
if (_dev_has_md_magic(dev, sb_offset)) {
log_debug_devs("Found md magic number at offset %llu of %s.", (unsigned long long)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
/*
* md imsm superblock 1K from end of device
*/
if (_dev_has_imsm_magic(dev, size)) {
log_debug_devs("Found md imsm magic number at offset %llu of %s.", (unsigned long long)sb_offset, dev_name(dev));
sb_offset = 1024;
ret = 1;
goto out;
}
/*
* md ddf superblock 512 bytes from end, or 128KB from end
*/
if (_dev_has_ddf_magic(dev, size, &sb_offset)) {
log_debug_devs("Found md ddf magic number at offset %llu of %s.", (unsigned long long)sb_offset, dev_name(dev));
ret = 1;
goto out;
}
minor = MD_MINOR_VERSION_MIN;
/* Version 1, try v1.0 -> v1.2 */
do {
sb_offset = _v1_sb_offset(size, minor);
if (_dev_has_md_magic(dev, sb_offset)) {
ret = 1;
goto out;
}
} while (++minor <= MD_MINOR_VERSION_MAX);
ret = 0;
out:
@@ -290,20 +204,41 @@ out:
return ret;
}
int dev_is_md_component(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full)
int dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
{
if (_dev_is_md_component_native(dev, offset_found, full) == 1)
goto found;
int ret;
if (external_device_info_source() == DEV_EXT_UDEV) {
if (_dev_is_md_component_udev(dev) == 1)
goto found;
/*
* If non-native device status source is selected, use it
* only if offset_found is not requested as this
* information is not in udev db.
*/
if ((dev->ext.src == DEV_EXT_NONE) || offset_found) {
ret = _native_dev_is_md_component(dev, offset_found, full);
if (!full) {
if (!ret || (ret == -EAGAIN)) {
if (udev_dev_is_md_component(dev))
ret = 1;
}
}
if (ret && (ret != -EAGAIN))
dev->flags |= DEV_IS_MD_COMPONENT;
return ret;
}
return 0;
found:
dev->flags |= DEV_IS_MD_COMPONENT;
return 1;
if (dev->ext.src == DEV_EXT_UDEV) {
ret = _udev_dev_is_md_component(dev);
if (ret && (ret != -EAGAIN))
dev->flags |= DEV_IS_MD_COMPONENT;
return ret;
}
log_error(INTERNAL_ERROR "Missing hook for MD device recognition "
"using external device info source %s", dev_ext_name(dev));
return -1;
}
static int _md_sysfs_attribute_snprintf(char *path, size_t size,
@@ -526,8 +461,7 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev)
#else
int dev_is_md_component(struct cmd_context *cmd __attribute__((unused)),
struct device *dev __attribute__((unused)),
int dev_is_md_component(struct device *dev __attribute__((unused)),
uint64_t *sb __attribute__((unused)))
{
return 0;

View File

@@ -1,484 +0,0 @@
/*
* Copyright (C) 2011 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/activate/activate.h"
#include "lib/commands/toolcontext.h"
#include "lib/device/device_id.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "lib/device/dev-ext-udev-constants.h"
#endif
#include <dirent.h>
#define MPATH_PREFIX "mpath-"
/*
* This hash table keeps track of whether a given dm device
* is a mpath device or not.
*
* If dm-3 is an mpath device, then the constant "2" is stored in
* the hash table with the key of the dm minor number ("3" for dm-3).
* If dm-3 is not an mpath device, then the constant "1" is stored in
* the hash table with the key of the dm minor number.
*/
static struct dm_pool *_hash_mem;
static struct dm_hash_table *_minor_hash_tab;
static struct dm_hash_table *_wwid_hash_tab;
#define MAX_WWID_LINE 512
/*
* do we need to check the multipath.conf blacklist?
*/
static void _read_wwid_file(const char *config_wwids_file)
{
FILE *fp;
char line[MAX_WWID_LINE];
char *wwid, *p;
int count = 0;
if (config_wwids_file[0] != '/') {
log_print("Ignoring unknown multipath_wwids_file.");
return;
}
if (!(fp = fopen(config_wwids_file, "r"))) {
log_debug("multipath wwids file not found");
return;
}
while (fgets(line, sizeof(line), fp)) {
if (line[0] == '#')
continue;
wwid = line;
if (line[0] == '/')
wwid++;
/* skip the initial '3' */
wwid++;
if ((p = strchr(wwid, '/')))
*p = '\0';
(void) dm_hash_insert_binary(_wwid_hash_tab, wwid, strlen(wwid), (void*)1);
count++;
}
if (fclose(fp))
stack;
log_debug("multipath wwids read %d from %s", count, config_wwids_file);
}
int dev_mpath_init(const char *config_wwids_file)
{
struct dm_pool *mem;
struct dm_hash_table *minor_tab;
struct dm_hash_table *wwid_tab;
if (!(mem = dm_pool_create("mpath", 256))) {
log_error("mpath pool creation failed.");
return 0;
}
if (!(minor_tab = dm_hash_create(110))) {
log_error("mpath hash table creation failed.");
dm_pool_destroy(mem);
return 0;
}
_hash_mem = mem;
_minor_hash_tab = minor_tab;
/* multipath_wwids_file="" disables the use of the file */
if (config_wwids_file && !strlen(config_wwids_file)) {
log_debug("multipath wwids file disabled.");
return 1;
}
if (!(wwid_tab = dm_hash_create(110))) {
log_error("mpath hash table creation failed.");
dm_hash_destroy(_minor_hash_tab);
dm_pool_destroy(_hash_mem);
_minor_hash_tab = NULL;
_hash_mem = NULL;
return 0;
}
_wwid_hash_tab = wwid_tab;
if (config_wwids_file)
_read_wwid_file(config_wwids_file);
return 1;
}
void dev_mpath_exit(void)
{
if (_minor_hash_tab)
dm_hash_destroy(_minor_hash_tab);
if (_wwid_hash_tab)
dm_hash_destroy(_wwid_hash_tab);
if (_hash_mem)
dm_pool_destroy(_hash_mem);
_minor_hash_tab = NULL;
_wwid_hash_tab = NULL;
_hash_mem = NULL;
}
/*
* given "/dev/foo" return "foo"
*/
static const char *_get_sysfs_name(struct device *dev)
{
const char *name;
if (!(name = strrchr(dev_name(dev), '/'))) {
log_error("Cannot find '/' in device name.");
return NULL;
}
name++;
if (!*name) {
log_error("Device name is not valid.");
return NULL;
}
return name;
}
/*
* given major:minor
* readlink translates /sys/dev/block/major:minor to /sys/.../foo
* from /sys/.../foo return "foo"
*/
static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno,
char *buf, size_t buf_size)
{
const char *name;
char path[PATH_MAX];
int size;
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d", sysfs_dir,
(int) MAJOR(devno), (int) MINOR(devno)) < 0) {
log_error("Sysfs path string is too long.");
return NULL;
}
if ((size = readlink(path, buf, buf_size - 1)) < 0) {
log_sys_error("readlink", path);
return NULL;
}
buf[size] = '\0';
if (!(name = strrchr(buf, '/'))) {
log_error("Cannot find device name in sysfs path.");
return NULL;
}
name++;
return name;
}
static int _get_sysfs_string(const char *path, char *buffer, int max_size)
{
FILE *fp;
int r = 0;
if (!(fp = fopen(path, "r"))) {
log_sys_error("fopen", path);
return 0;
}
if (!fgets(buffer, max_size, fp))
log_sys_error("fgets", path);
else
r = 1;
if (fclose(fp))
log_sys_error("fclose", path);
return r;
}
static int _get_sysfs_dm_mpath(struct dev_types *dt, const char *sysfs_dir, const char *holder_name)
{
char path[PATH_MAX];
char buffer[128];
if (dm_snprintf(path, sizeof(path), "%sblock/%s/dm/uuid", sysfs_dir, holder_name) < 0) {
log_error("Sysfs path string is too long.");
return 0;
}
buffer[0] = '\0';
if (!_get_sysfs_string(path, buffer, sizeof(buffer)))
return_0;
if (!strncmp(buffer, MPATH_PREFIX, 6))
return 1;
return 0;
}
#ifdef UDEV_SYNC_SUPPORT
static int _dev_is_mpath_component_udev(struct device *dev)
{
const char *value;
struct dev_ext *ext;
/*
* external_device_info_source="udev" enables these udev checks.
* external_device_info_source="none" disables them.
*/
if (!(ext = dev_ext_get(dev)))
return_0;
value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH))
return 1;
value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_MPATH_DEVICE_PATH);
if (value && !strcmp(value, "1"))
return 1;
return 0;
}
#else
static int _dev_is_mpath_component_udev(struct device *dev)
{
return 0;
}
#endif
static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev)
{
struct dev_types *dt = cmd->dev_types;
const char *part_name;
const char *name; /* e.g. "sda" for "/dev/sda" */
char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */
char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */
char dm_dev_path[PATH_MAX]; /* e.g. "/dev/dm-1" */
char *holder_name; /* e.g. "dm-1" */
const char *sysfs_dir = dm_sysfs_dir();
DIR *dr;
struct dirent *de;
int dev_major = MAJOR(dev->dev);
int dev_minor = MINOR(dev->dev);
int dm_dev_major;
int dm_dev_minor;
struct stat info;
dev_t primary_dev;
int is_mpath_component = 0;
/* multipathing is only known to exist for SCSI or NVME devices */
if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
return 0;
switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
case 2: /* The dev is partition. */
part_name = dev_name(dev); /* name of original dev for log_debug msg */
/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
return_0;
log_debug_devs("%s: Device is a partition, using primary "
"device %s for mpath component detection",
part_name, name);
break;
case 1: /* The dev is already a primary dev. Just continue with the dev. */
/* gets "foo" for "/dev/foo" */
if (!(name = _get_sysfs_name(dev)))
return_0;
break;
default: /* 0, error. */
log_warn("Failed to get primary device for %d:%d.", dev_major, dev_minor);
return 0;
}
if (dm_snprintf(holders_path, sizeof(holders_path), "%sblock/%s/holders", sysfs_dir, name) < 0) {
log_warn("Sysfs path to check mpath is too long.");
return 0;
}
/* also will filter out partitions */
if (stat(holders_path, &info))
return 0;
if (!S_ISDIR(info.st_mode)) {
log_warn("Path %s is not a directory.", holders_path);
return 0;
}
/*
* If any holder is a dm mpath device, then return 1;
*/
if (!(dr = opendir(holders_path))) {
log_debug("Device %s has no holders dir", dev_name(dev));
return 0;
}
while ((de = readdir(dr))) {
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
continue;
/*
* holder_name is e.g. "dm-1"
* dm_dev_path is then e.g. "/dev/dm-1"
*/
holder_name = de->d_name;
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
log_warn("dm device path to check mpath is too long.");
continue;
}
/*
* stat "/dev/dm-1" which is the holder of the dev we're checking
* dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
*/
if (stat(dm_dev_path, &info)) {
log_debug_devs("dev_is_mpath_component %s holder %s stat result %d",
dev_name(dev), dm_dev_path, errno);
continue;
}
dm_dev_major = (int)MAJOR(info.st_rdev);
dm_dev_minor = (int)MINOR(info.st_rdev);
if (dm_dev_major != dt->device_mapper_major) {
log_debug_devs("dev_is_mpath_component %s holder %s %d:%d does not have dm major",
dev_name(dev), dm_dev_path, dm_dev_major, dm_dev_minor);
continue;
}
/*
* A previous call may have checked if dm_dev_minor is mpath and saved
* the result in the hash table. If there's a saved result just use that.
*
* The minor number of "/dev/dm-1" is added to the hash table with
* const value 2 meaning that dm minor 1 (for /dev/dm-1) is a multipath dev
* and const value 1 meaning that dm minor 1 is not a multipath dev.
*/
if (_minor_hash_tab) {
long look = (long) dm_hash_lookup_binary(_minor_hash_tab, &dm_dev_minor, sizeof(dm_dev_minor));
if (look > 0) {
log_debug_devs("dev_is_mpath_component %s holder %s %u:%u already checked as %sbeing mpath.",
dev_name(dev), holder_name, dm_dev_major, dm_dev_minor, (look > 1) ? "" : "not ");
is_mpath_component = (look == 2);
goto out;
}
/* no saved result for dm_dev_minor, so check the uuid for it */
}
/*
* Returns 1 if /sys/block/<holder_name>/dm/uuid indicates that
* <holder_name> is a dm device with dm uuid prefix mpath-.
* When true, <holder_name> will be something like "dm-1".
*/
if (_get_sysfs_dm_mpath(dt, sysfs_dir, holder_name)) {
log_debug_devs("dev_is_mpath_component %s holder %s %u:%u ignore mpath component",
dev_name(dev), holder_name, dm_dev_major, dm_dev_minor);
/* For future checks, save that the dm minor refers to mpath ("2" == is mpath) */
if (_minor_hash_tab)
(void) dm_hash_insert_binary(_minor_hash_tab, &dm_dev_minor, sizeof(dm_dev_minor), (void*)2);
is_mpath_component = 1;
goto out;
}
/* For future checks, save that the dm minor does not refer to mpath ("1" == is not mpath) */
if (_minor_hash_tab)
(void) dm_hash_insert_binary(_minor_hash_tab, &dm_dev_minor, sizeof(dm_dev_minor), (void*)1);
}
out:
if (closedir(dr))
stack;
return is_mpath_component;
}
static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev)
{
char sysbuf[PATH_MAX] = { 0 };
char *wwid;
long look;
if (!_wwid_hash_tab)
return 0;
if (!read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf)))
return 0;
if (!sysbuf[0])
return 0;
/*
* sysfs prints wwid as <typestr>.<value>
* multipath wwid uses '3'<value>
* does "<typestr>." always correspond to "3"?
*/
if (!(wwid = strchr(sysbuf, '.')))
return 0;
/* skip the type and dot, just as '3' was skipped from wwids entry */
wwid++;
look = (long) dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid));
if (look) {
log_debug_devs("dev_is_mpath_component %s multipath wwid %s", dev_name(dev), wwid);
return 1;
}
return 0;
}
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev)
{
if (_dev_is_mpath_component_sysfs(cmd, dev) == 1)
goto found;
if (_dev_in_wwid_file(cmd, dev))
goto found;
if (external_device_info_source() == DEV_EXT_UDEV) {
if (_dev_is_mpath_component_udev(dev) == 1)
goto found;
}
return 0;
found:
return 1;
}

View File

@@ -35,7 +35,7 @@ static int _swap_detect_signature(const char *buf)
return 0;
}
int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full)
int dev_is_swap(struct device *dev, uint64_t *offset_found, int full)
{
char buf[10];
uint64_t size;

View File

@@ -21,8 +21,6 @@
#include "lib/metadata/metadata.h"
#include "lib/device/bcache.h"
#include "lib/label/label.h"
#include "lib/commands/toolcontext.h"
#include "device_mapper/misc/dm-ioctl.h"
#ifdef BLKID_WIPING_SUPPORT
#include <blkid.h>
@@ -35,19 +33,38 @@
#include <libgen.h>
#include <ctype.h>
#include <dirent.h>
/*
* An nvme device has major number 259 (BLKEXT), minor number <minor>,
* and reading /sys/dev/block/259:<minor>/device/dev shows a character
* device cmajor:cminor where cmajor matches the major number of the
* nvme character device entry in /proc/devices. Checking all of that
* is excessive and unnecessary compared to just comparing /dev/name*.
* dev is pmem if /sys/dev/block/<major>:<minor>/queue/dax is 1
*/
int dev_is_nvme(struct dev_types *dt, struct device *dev)
int dev_is_pmem(struct device *dev)
{
return (dev->flags & DEV_IS_NVME) ? 1 : 0;
FILE *fp;
char path[PATH_MAX];
int is_pmem = 0;
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/queue/dax",
dm_sysfs_dir(),
(int) MAJOR(dev->dev),
(int) MINOR(dev->dev)) < 0) {
log_warn("Sysfs path for %s dax is too long.", dev_name(dev));
return 0;
}
if (!(fp = fopen(path, "r")))
return 0;
if (fscanf(fp, "%d", &is_pmem) != 1)
log_warn("Failed to parse DAX %s.", path);
if (is_pmem)
log_debug("%s is pmem", dev_name(dev));
if (fclose(fp))
log_sys_debug("fclose", path);
return is_pmem ? 1 : 0;
}
int dev_is_lv(struct device *dev)
@@ -79,124 +96,6 @@ int dev_is_lv(struct device *dev)
return ret;
}
int dev_is_used_by_active_lv(struct cmd_context *cmd, struct device *dev, int *used_by_lv_count,
char **used_by_dm_name, char **used_by_vg_uuid, char **used_by_lv_uuid)
{
char holders_path[PATH_MAX];
char dm_dev_path[PATH_MAX];
char dm_uuid[DM_UUID_LEN];
struct stat info;
DIR *d;
struct dirent *dirent;
char *holder_name;
int dm_dev_major, dm_dev_minor;
size_t lvm_prefix_len = sizeof(UUID_PREFIX) - 1;
size_t lvm_uuid_len = sizeof(UUID_PREFIX) - 1 + 2 * ID_LEN;
size_t uuid_len;
int used_count = 0;
char *used_name = NULL;
char *used_vgid = NULL;
char *used_lvid = NULL;
/*
* An LV using this device will be listed as a "holder" in the device's
* sysfs "holders" dir.
*/
if (dm_snprintf(holders_path, sizeof(holders_path), "%sdev/block/%d:%d/holders/", dm_sysfs_dir(), (int) MAJOR(dev->dev), (int) MINOR(dev->dev)) < 0) {
log_error("%s: dm_snprintf failed for path to holders directory.", dev_name(dev));
return 0;
}
if (!(d = opendir(holders_path)))
return 0;
while ((dirent = readdir(d))) {
if (!strcmp(".", dirent->d_name) || !strcmp("..", dirent->d_name))
continue;
holder_name = dirent->d_name;
/*
* dirent->d_name is the dev name of the holder, e.g. "dm-1"
* from this name, create path "/dev/dm-1" to run stat on.
*/
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0)
continue;
/*
* stat "/dev/dm-1" which is the holder of the dev we're checking
* dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
*/
if (stat(dm_dev_path, &info))
continue;
dm_dev_major = (int)MAJOR(info.st_rdev);
dm_dev_minor = (int)MINOR(info.st_rdev);
if (dm_dev_major != cmd->dev_types->device_mapper_major)
continue;
/*
* if "dm-1" is a dm device, then check if it's an LVM LV
* by reading /sys/block/<holder_name>/dm/uuid and seeing
* if the uuid begins with LVM-
* UUID_PREFIX is "LVM-"
*/
dm_uuid[0] = '\0';
if (!get_dm_uuid_from_sysfs(dm_uuid, sizeof(dm_uuid), dm_dev_major, dm_dev_minor))
continue;
if (!strncmp(dm_uuid, UUID_PREFIX, 4))
used_count++;
if (used_by_dm_name && !used_name)
used_name = dm_pool_strdup(cmd->mem, holder_name);
if (!used_by_vg_uuid && !used_by_lv_uuid)
continue;
/*
* UUID for LV is either "LVM-<vg_uuid><lv_uuid>" or
* "LVM-<vg_uuid><lv_uuid>-<suffix>", where vg_uuid and lv_uuid
* has length of ID_LEN and suffix len is not restricted (only
* restricted by whole DM UUID max len).
*/
uuid_len = strlen(dm_uuid);
if (((uuid_len == lvm_uuid_len) ||
((uuid_len > lvm_uuid_len) && (dm_uuid[lvm_uuid_len] == '-'))) &&
!strncmp(dm_uuid, UUID_PREFIX, lvm_prefix_len)) {
if (used_by_vg_uuid && !used_vgid)
used_vgid = dm_pool_strndup(cmd->mem, dm_uuid + lvm_prefix_len, ID_LEN);
if (used_by_lv_uuid && !used_lvid)
used_lvid = dm_pool_strndup(cmd->mem, dm_uuid + lvm_prefix_len + ID_LEN, ID_LEN);
}
}
if (closedir(d))
log_sys_debug("closedir", holders_path);
if (used_by_lv_count)
*used_by_lv_count = used_count;
if (used_by_dm_name)
*used_by_dm_name = used_name;
if (used_by_vg_uuid)
*used_by_vg_uuid = used_vgid;
if (used_by_lv_uuid)
*used_by_lv_uuid = used_lvid;
if (used_count)
return 1;
return 0;
}
struct dev_types *create_dev_types(const char *proc_dir,
const struct dm_config_node *cn)
{
@@ -331,7 +230,7 @@ struct dev_types *create_dev_types(const char *proc_dir,
log_error("Expecting string in devices/types "
"in config file");
if (fclose(pd))
log_sys_debug("fclose", proc_devices);
log_sys_error("fclose", proc_devices);
goto bad;
}
dev_len = strlen(cv->v.str);
@@ -342,7 +241,7 @@ struct dev_types *create_dev_types(const char *proc_dir,
"in devices/types in config file",
name);
if (fclose(pd))
log_sys_debug("fclose", proc_devices);
log_sys_error("fclose", proc_devices);
goto bad;
}
if (!cv->v.i) {
@@ -350,7 +249,7 @@ struct dev_types *create_dev_types(const char *proc_dir,
"%s in devices/types in config file",
name);
if (fclose(pd))
log_sys_debug("fclose", proc_devices);
log_sys_error("fclose", proc_devices);
goto bad;
}
if (dev_len <= strlen(line + i) &&
@@ -403,9 +302,6 @@ int dev_subsystem_part_major(struct dev_types *dt, struct device *dev)
const char *dev_subsystem_name(struct dev_types *dt, struct device *dev)
{
if (dev->flags & DEV_IS_NVME)
return "NVME";
if (MAJOR(dev->dev) == dt->device_mapper_major)
return "DM";
@@ -452,6 +348,7 @@ int major_is_scsi_device(struct dev_types *dt, int major)
return (dt->dev_type_array[major].flags & PARTITION_SCSI_DEVICE) ? 1 : 0;
}
static int _loop_is_with_partscan(struct device *dev)
{
FILE *fp;
@@ -483,45 +380,6 @@ static int _loop_is_with_partscan(struct device *dev)
return partscan;
}
int dev_get_partition_number(struct device *dev, int *num)
{
char path[PATH_MAX];
char buf[8] = { 0 };
dev_t devt = dev->dev;
struct stat sb;
if (dev->part != -1) {
*num = dev->part;
return 1;
}
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/partition",
dm_sysfs_dir(), (int)MAJOR(devt), (int)MINOR(devt)) < 0) {
log_error("Failed to create sysfs path for %s", dev_name(dev));
return 0;
}
if (stat(path, &sb)) {
dev->part = 0;
*num = 0;
return 1;
}
if (!get_sysfs_value(path, buf, sizeof(buf), 0)) {
log_error("Failed to read sysfs path for %s", dev_name(dev));
return 0;
}
if (!buf[0]) {
log_error("Failed to read sysfs partition value for %s", dev_name(dev));
return 0;
}
dev->part = atoi(buf);
*num = dev->part;
return 1;
}
/* See linux/genhd.h and fs/partitions/msdos */
#define PART_MAGIC 0xAA55
#define PART_MAGIC_OFFSET UINT64_C(0x1FE)
@@ -540,28 +398,6 @@ struct partition {
uint32_t nr_sects;
} __attribute__((packed));
static int _has_sys_partition(struct device *dev)
{
char path[PATH_MAX];
struct stat info;
int major = (int) MAJOR(dev->dev);
int minor = (int) MINOR(dev->dev);
/* check if dev is a partition */
if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
dm_sysfs_dir(), major, minor) < 0) {
log_warn("WARNING: %s: partition path is too long.", dev_name(dev));
return 0;
}
if (stat(path, &info) == -1) {
if (errno != ENOENT)
log_sys_debug("stat", path);
return 0;
}
return 1;
}
static int _is_partitionable(struct dev_types *dt, struct device *dev)
{
int parts = major_max_partitions(dt, MAJOR(dev->dev));
@@ -578,13 +414,6 @@ static int _is_partitionable(struct dev_types *dt, struct device *dev)
_loop_is_with_partscan(dev))
return 1;
if (dev_is_nvme(dt, dev)) {
/* If this dev is already a partition then it's not partitionable. */
if (_has_sys_partition(dev))
return 0;
return 1;
}
if ((parts <= 1) || (MINOR(dev->dev) % parts))
return 0;
@@ -624,16 +453,12 @@ static int _has_partition_table(struct device *dev)
}
#ifdef UDEV_SYNC_SUPPORT
static int _dev_is_partitioned_udev(struct dev_types *dt, struct device *dev)
static int _udev_dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
struct dev_ext *ext;
struct udev_device *device;
const char *value;
/*
* external_device_info_source="udev" enables these udev checks.
* external_device_info_source="none" disables them.
*/
if (!(ext = dev_ext_get(dev)))
return_0;
@@ -664,20 +489,21 @@ static int _dev_is_partitioned_udev(struct dev_types *dt, struct device *dev)
return !strcmp(value, DEV_EXT_UDEV_DEVTYPE_DISK);
}
#else
static int _dev_is_partitioned_udev(struct dev_types *dt, struct device *dev)
static int _udev_dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
return 0;
}
#endif
static int _dev_is_partitioned_native(struct dev_types *dt, struct device *dev)
static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
int r;
if (!scan_bcache) {
log_error(INTERNAL_ERROR "dev_is_partitioned_native requires i/o.");
return -1;
}
if (!scan_bcache)
return -EAGAIN;
if (!_is_partitionable(dt, dev))
return 0;
/* Unpartitioned DASD devices are not supported. */
if ((MAJOR(dev->dev) == dt->dasd_major) && dasd_is_cdl_formatted(dev))
@@ -688,20 +514,16 @@ static int _dev_is_partitioned_native(struct dev_types *dt, struct device *dev)
return r;
}
int dev_is_partitioned(struct cmd_context *cmd, struct device *dev)
int dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
struct dev_types *dt = cmd->dev_types;
if (dev->ext.src == DEV_EXT_NONE)
return _native_dev_is_partitioned(dt, dev);
if (!_is_partitionable(dt, dev))
return 0;
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_partitioned(dt, dev);
if (_dev_is_partitioned_native(dt, dev) == 1)
return 1;
if (external_device_info_source() == DEV_EXT_UDEV) {
if (_dev_is_partitioned_udev(dt, dev) == 1)
return 1;
}
log_error(INTERNAL_ERROR "Missing hook for partition table recognition "
"using external device info source %s", dev_ext_name(dev));
return 0;
}
@@ -729,22 +551,16 @@ int dev_is_partitioned(struct cmd_context *cmd, struct device *dev)
*/
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
{
const char *sysfs_dir = dm_sysfs_dir();
int major = (int) MAJOR(dev->dev);
int minor = (int) MINOR(dev->dev);
char path[PATH_MAX];
char temp_path[PATH_MAX];
char buffer[64];
struct stat info;
FILE *fp = NULL;
int parts, residue, size, ret = 0;
/*
* /dev/nvme devs don't use the major:minor numbering like
* block dev types that have their own major number, so
* the calculation based on minor number doesn't work.
*/
if (dev_is_nvme(dt, dev))
goto sys_partition;
/*
* Try to get the primary dev out of the
* list of known device types first.
@@ -760,14 +576,23 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
goto out;
}
sys_partition:
/*
* If we can't get the primary dev out of the list of known device
* types, try to look at sysfs directly then. This is more complex
* way and it also requires certain sysfs layout to be present
* which might not be there in old kernels!
*/
if (!_has_sys_partition(dev)) {
/* check if dev is a partition */
if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d/partition",
sysfs_dir, major, minor) < 0) {
log_error("dm_snprintf partition failed");
goto out;
}
if (stat(path, &info) == -1) {
if (errno != ENOENT)
log_sys_error("stat", path);
*result = dev->dev;
ret = 1;
goto out; /* dev is not a partition! */
@@ -780,31 +605,25 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
* - basename ../../block/md0/md0 = md0
* Parent's 'dev' sysfs attribute = /sys/block/md0/dev
*/
if (dm_snprintf(path, sizeof(path), "%s/dev/block/%d:%d",
dm_sysfs_dir(), major, minor) < 0) {
log_warn("WARNING: %s: major:minor sysfs path is too long.", dev_name(dev));
return 0;
}
if ((size = readlink(path, temp_path, sizeof(temp_path) - 1)) < 0) {
log_warn("WARNING: Readlink of %s failed.", path);
if ((size = readlink(dirname(path), temp_path, sizeof(temp_path) - 1)) < 0) {
log_sys_error("readlink", path);
goto out;
}
temp_path[size] = '\0';
if (dm_snprintf(path, sizeof(path), "%s/block/%s/dev",
dm_sysfs_dir(), basename(dirname(temp_path))) < 0) {
log_warn("WARNING: sysfs path for %s is too long.",
basename(dirname(temp_path)));
sysfs_dir, basename(dirname(temp_path))) < 0) {
log_error("dm_snprintf dev failed");
goto out;
}
/* finally, parse 'dev' attribute and create corresponding dev_t */
if (!(fp = fopen(path, "r"))) {
if (errno == ENOENT)
log_debug("sysfs file %s does not exist.", path);
log_error("sysfs file %s does not exist.", path);
else
log_sys_debug("fopen", path);
log_sys_error("fopen", path);
goto out;
}
@@ -814,7 +633,7 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
}
if (sscanf(buffer, "%d:%d", &major, &minor) != 2) {
log_warn("WARNING: sysfs file %s not in expected MAJ:MIN format: %s",
log_error("sysfs file %s not in expected MAJ:MIN format: %s",
path, buffer);
goto out;
}
@@ -822,31 +641,45 @@ int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
ret = 2;
out:
if (fp && fclose(fp))
log_sys_debug("fclose", path);
log_sys_error("fclose", path);
return ret;
}
#ifdef BLKID_WIPING_SUPPORT
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size)
{
char *block_size_str = NULL;
blkid_probe probe = NULL;
const char *block_size_str = NULL;
uint64_t block_size_val;
int r = 0;
if ((block_size_str = blkid_get_tag_value(NULL, "BLOCK_SIZE", pathname))) {
*fs_block_size = (uint32_t)atoi(block_size_str);
free(block_size_str);
log_debug("Found blkid BLOCK_SIZE %u for fs on %s", *fs_block_size, pathname);
return 1;
} else {
log_debug("No blkid BLOCK_SIZE for fs on %s", pathname);
*fs_block_size = 0;
return 0;
*fs_block_size = 0;
if (!(probe = blkid_new_probe_from_filename(dev_name(dev)))) {
log_error("Failed to create a new blkid probe for device %s.", dev_name(dev));
goto out;
}
blkid_probe_enable_partitions(probe, 1);
(void) blkid_probe_lookup_value(probe, "BLOCK_SIZE", &block_size_str, NULL);
if (!block_size_str)
goto out;
block_size_val = strtoull(block_size_str, NULL, 10);
*fs_block_size = (uint32_t)block_size_val;
r = 1;
out:
if (probe)
blkid_free_probe(probe);
return r;
}
#else
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size)
{
log_debug("Disabled blkid BLOCK_SIZE for fs.");
*fs_block_size = 0;
return 0;
}
@@ -873,7 +706,7 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
const char *offset = NULL, *type = NULL, *magic = NULL,
*usage = NULL, *label = NULL, *uuid = NULL;
loff_t offset_value;
size_t len = 0;
size_t len;
if (!blkid_probe_lookup_value(probe, "TYPE", &type, NULL)) {
if (_type_in_flag_list(type, types_to_exclude))
@@ -884,7 +717,7 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
return 0;
}
log_warn("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name);
log_error("WARNING: " MSG_FAILED_SIG_OFFSET MSG_WIPING_SKIPPED, type, name);
return 2;
}
if (blkid_probe_lookup_value(probe, "SBMAGIC", &magic, &len)) {
@@ -1013,14 +846,14 @@ out:
#endif /* BLKID_WIPING_SUPPORT */
static int _wipe_signature(struct cmd_context *cmd, struct device *dev, const char *type, const char *name,
static int _wipe_signature(struct device *dev, const char *type, const char *name,
int wipe_len, int yes, force_t force, int *wiped,
int (*signature_detection_fn)(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full))
int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found, int full))
{
int wipe;
uint64_t offset_found = 0;
uint64_t offset_found;
wipe = signature_detection_fn(cmd, dev, &offset_found, 1);
wipe = signature_detection_fn(dev, &offset_found, 1);
if (wipe == -1) {
log_error("Fatal error while trying to detect %s on %s.",
type, name);
@@ -1048,7 +881,7 @@ static int _wipe_signature(struct cmd_context *cmd, struct device *dev, const ch
return 1;
}
static int _wipe_known_signatures_with_lvm(struct cmd_context *cmd, struct device *dev, const char *name,
static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name,
uint32_t types_to_exclude __attribute__((unused)),
uint32_t types_no_prompt __attribute__((unused)),
int yes, force_t force, int *wiped)
@@ -1059,9 +892,9 @@ static int _wipe_known_signatures_with_lvm(struct cmd_context *cmd, struct devic
wiped = &wiped_tmp;
*wiped = 0;
if (!_wipe_signature(cmd, dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md_component) ||
!_wipe_signature(cmd, dev, "swap signature", name, 10, yes, force, wiped, dev_is_swap) ||
!_wipe_signature(cmd, dev, "LUKS signature", name, 8, yes, force, wiped, dev_is_luks))
if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md_component) ||
!_wipe_signature(dev, "swap signature", name, 10, yes, force, wiped, dev_is_swap) ||
!_wipe_signature(dev, "LUKS signature", name, 8, yes, force, wiped, dev_is_luks))
return 0;
return 1;
@@ -1082,11 +915,11 @@ int wipe_known_signatures(struct cmd_context *cmd, struct device *dev,
yes, force, wiped);
#endif
if (blkid_wiping_enabled) {
log_warn("WARNING: allocation/use_blkid_wiping=1 configuration setting is set "
log_warn("allocation/use_blkid_wiping=1 configuration setting is set "
"while LVM is not compiled with blkid wiping support.");
log_warn("WARNING: Falling back to native LVM signature detection.");
log_warn("Falling back to native LVM signature detection.");
}
return _wipe_known_signatures_with_lvm(cmd, dev, name,
return _wipe_known_signatures_with_lvm(dev, name,
types_to_exclude,
types_no_prompt,
yes, force, wiped);
@@ -1100,23 +933,25 @@ static int _snprintf_attr(char *buf, size_t buf_size, const char *sysfs_dir,
if (dm_snprintf(buf, buf_size, "%s/dev/block/%d:%d/%s", sysfs_dir,
(int)MAJOR(dev), (int)MINOR(dev),
attribute) < 0) {
log_warn("WARNING: sysfs path for %s attribute is too long.", attribute);
log_warn("dm_snprintf %s failed.", attribute);
return 0;
}
return 1;
}
static int _dev_sysfs_block_attribute(struct dev_types *dt,
const char *attribute,
struct device *dev,
unsigned long *value)
static unsigned long _dev_topology_attribute(struct dev_types *dt,
const char *attribute,
struct device *dev,
unsigned long default_value)
{
const char *sysfs_dir = dm_sysfs_dir();
char path[PATH_MAX], buffer[64];
FILE *fp;
dev_t primary = 0;
int ret = 0;
struct stat info;
dev_t uninitialized_var(primary);
unsigned long result = default_value;
unsigned long value = 0UL;
if (!attribute || !*attribute)
goto_out;
@@ -1125,16 +960,16 @@ static int _dev_sysfs_block_attribute(struct dev_types *dt,
goto_out;
if (!_snprintf_attr(path, sizeof(path), sysfs_dir, attribute, dev->dev))
goto_out;
goto_out;
/*
* check if the desired sysfs attribute exists
* - if not: either the kernel doesn't have topology support
* or the device could be a partition
*/
if (!(fp = fopen(path, "r"))) {
if (stat(path, &info) == -1) {
if (errno != ENOENT) {
log_sys_debug("fopen", path);
log_sys_debug("stat", path);
goto out;
}
if (!dev_get_primary_dev(dt, dev, &primary))
@@ -1144,54 +979,44 @@ static int _dev_sysfs_block_attribute(struct dev_types *dt,
if (!_snprintf_attr(path, sizeof(path), sysfs_dir, attribute, primary))
goto_out;
if (!(fp = fopen(path, "r"))) {
if (stat(path, &info) == -1) {
if (errno != ENOENT)
log_sys_debug("fopen", path);
log_sys_debug("stat", path);
goto out;
}
}
if (!(fp = fopen(path, "r"))) {
log_sys_debug("fopen", path);
goto out;
}
if (!fgets(buffer, sizeof(buffer), fp)) {
log_sys_debug("fgets", path);
goto out_close;
}
if (sscanf(buffer, "%lu", value) != 1) {
log_warn("WARNING: sysfs file %s not in expected format: %s", path, buffer);
if (sscanf(buffer, "%lu", &value) != 1) {
log_warn("sysfs file %s not in expected format: %s", path, buffer);
goto out_close;
}
ret = 1;
log_very_verbose("Device %s: %s is %lu%s.",
dev_name(dev), attribute, value, default_value ? "" : " bytes");
result = value >> SECTOR_SHIFT;
if (!result && value) {
log_warn("WARNING: Device %s: %s is %lu and is unexpectedly less than sector.",
dev_name(dev), attribute, value);
result = 1;
}
out_close:
if (fclose(fp))
log_sys_debug("fclose", path);
out:
return ret;
}
static unsigned long _dev_topology_attribute(struct dev_types *dt,
const char *attribute,
struct device *dev,
unsigned long default_value)
{
unsigned long result = default_value;
unsigned long value = 0UL;
if (_dev_sysfs_block_attribute(dt, attribute, dev, &value)) {
log_very_verbose("Device %s: %s is %lu%s.",
dev_name(dev), attribute, value, default_value ? "" : " bytes");
result = value >> SECTOR_SHIFT;
if (!result && value) {
log_warn("WARNING: Device %s: %s is %lu and is unexpectedly less than sector.",
dev_name(dev), attribute, value);
result = 1;
}
}
return result;
}
@@ -1222,17 +1047,8 @@ unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev)
int dev_is_rotational(struct dev_types *dt, struct device *dev)
{
unsigned long value;
return _dev_sysfs_block_attribute(dt, "queue/rotational", dev, &value) ? (int) value : 1;
return (int) _dev_topology_attribute(dt, "queue/rotational", dev, 1UL);
}
/* dev is pmem if /sys/dev/block/<major>:<minor>/queue/dax is 1 */
int dev_is_pmem(struct dev_types *dt, struct device *dev)
{
unsigned long value;
return _dev_sysfs_block_attribute(dt, "queue/dax", dev, &value) ? (int) value : 0;
}
#else
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result)
@@ -1269,10 +1085,152 @@ int dev_is_rotational(struct dev_types *dt, struct device *dev)
{
return 1;
}
#endif
int dev_is_pmem(struct dev_types *dt, struct device *dev)
#ifdef UDEV_SYNC_SUPPORT
/*
* Udev daemon usually has 30s timeout to process each event by default.
* But still, that value can be changed in udev configuration and we
* don't have libudev API to read the actual timeout value used.
*/
/* FIXME: Is this long enough to wait for udev db to get initialized?
*
* Take also into consideration that this check is done for each
* device that is scanned so we don't want to wait for a long time
* if there's something wrong with udev, e.g. timeouts! With current
* libudev API, we can't recognize whether the event processing has
* not finished yet and it's still being processed or whether it has
* failed already due to timeout in udev - in both cases the
* udev_device_get_is_initialized returns 0.
*/
#define UDEV_DEV_IS_COMPONENT_ITERATION_COUNT 100
#define UDEV_DEV_IS_COMPONENT_USLEEP 100000
static struct udev_device *_udev_get_dev(struct device *dev)
{
struct udev *udev_context = udev_get_library_context();
struct udev_device *udev_device = NULL;
int initialized = 0;
unsigned i = 0;
if (!udev_context) {
log_warn("WARNING: No udev context available to check if device %s is multipath component.", dev_name(dev));
return NULL;
}
while (1) {
if (i >= UDEV_DEV_IS_COMPONENT_ITERATION_COUNT)
break;
if (udev_device)
udev_device_unref(udev_device);
if (!(udev_device = udev_device_new_from_devnum(udev_context, 'b', dev->dev))) {
log_warn("WARNING: Failed to get udev device handler for device %s.", dev_name(dev));
return NULL;
}
#ifdef HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED
if ((initialized = udev_device_get_is_initialized(udev_device)))
break;
#else
if ((initialized = (udev_device_get_property_value(udev_device, DEV_EXT_UDEV_DEVLINKS) != NULL)))
break;
#endif
log_debug("Device %s not initialized in udev database (%u/%u, %u microseconds).", dev_name(dev),
i + 1, UDEV_DEV_IS_COMPONENT_ITERATION_COUNT,
i * UDEV_DEV_IS_COMPONENT_USLEEP);
if (!udev_sleeping())
break;
usleep(UDEV_DEV_IS_COMPONENT_USLEEP);
i++;
}
if (!initialized) {
log_warn("WARNING: Device %s not initialized in udev database even after waiting %u microseconds.",
dev_name(dev), i * UDEV_DEV_IS_COMPONENT_USLEEP);
goto out;
}
out:
return udev_device;
}
int udev_dev_is_mpath_component(struct device *dev)
{
struct udev_device *udev_device;
const char *value;
int ret = 0;
if (!obtain_device_list_from_udev())
return 0;
if (!(udev_device = _udev_get_dev(dev)))
return 0;
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH)) {
log_debug("Device %s is multipath component based on blkid variable in udev db (%s=\"%s\").",
dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value);
ret = 1;
goto out;
}
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_MPATH_DEVICE_PATH);
if (value && !strcmp(value, "1")) {
log_debug("Device %s is multipath component based on multipath variable in udev db (%s=\"%s\").",
dev_name(dev), DEV_EXT_UDEV_MPATH_DEVICE_PATH, value);
ret = 1;
goto out;
}
out:
udev_device_unref(udev_device);
return ret;
}
int udev_dev_is_md_component(struct device *dev)
{
struct udev_device *udev_device;
const char *value;
int ret = 0;
if (!obtain_device_list_from_udev()) {
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
if (!(udev_device = _udev_get_dev(dev)))
return 0;
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID)) {
log_debug("Device %s is md raid component based on blkid variable in udev db (%s=\"%s\").",
dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value);
dev->flags |= DEV_IS_MD_COMPONENT;
ret = 1;
goto out;
}
out:
udev_device_unref(udev_device);
return ret;
}
#else
int udev_dev_is_mpath_component(struct device *dev)
{
return 0;
}
#endif
int udev_dev_is_md_component(struct device *dev)
{
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
#endif

View File

@@ -57,11 +57,12 @@ const char *dev_subsystem_name(struct dev_types *dt, struct device *dev);
int major_is_scsi_device(struct dev_types *dt, int major);
/* Signature/superblock recognition with position returned where found. */
int dev_is_md_component(struct cmd_context *cmd, struct device *dev, uint64_t *sb, int full);
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev);
int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *signature, int full);
int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *signature, int full);
int dev_is_md_component(struct device *dev, uint64_t *sb, int full);
int dev_is_swap(struct device *dev, uint64_t *signature, int full);
int dev_is_luks(struct device *dev, uint64_t *signature, int full);
int dasd_is_cdl_formatted(struct device *dev);
int udev_dev_is_mpath_component(struct device *dev);
int udev_dev_is_md_component(struct device *dev);
int dev_is_lvm1(struct device *dev, char *buf, int buflen);
int dev_is_pool(struct device *dev, char *buf, int buflen);
@@ -80,9 +81,8 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev);
/* Partitioning */
int major_max_partitions(struct dev_types *dt, int major);
int dev_is_partitioned(struct cmd_context *cmd, struct device *dev);
int dev_is_partitioned(struct dev_types *dt, struct device *dev);
int dev_get_primary_dev(struct dev_types *dt, struct device *dev, dev_t *result);
int dev_get_partition_number(struct device *dev, int *num);
/* Various device properties */
unsigned long dev_alignment_offset(struct dev_types *dt, struct device *dev);
@@ -93,15 +93,10 @@ unsigned long dev_discard_granularity(struct dev_types *dt, struct device *dev);
int dev_is_rotational(struct dev_types *dt, struct device *dev);
int dev_is_pmem(struct dev_types *dt, struct device *dev);
int dev_is_nvme(struct dev_types *dt, struct device *dev);
int dev_is_pmem(struct device *dev);
int dev_is_lv(struct device *dev);
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size);
int dev_is_used_by_active_lv(struct cmd_context *cmd, struct device *dev, int *used_by_lv_count,
char **used_by_dm_name, char **used_by_vg_uuid, char **used_by_lv_uuid);
int get_fs_block_size(struct device *dev, uint32_t *fs_block_size);
#endif

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