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

Compare commits

..

17 Commits

Author SHA1 Message Date
David Teigland
89b0d5b23c tests: add missing-pv missing-pv-unused 2019-05-24 13:12:51 -05:00
David Teigland
f44e7d1567 metadata.c: removed unused code
if 0 was placed around old vg_read code by
the previous commit.
2019-05-24 13:12:51 -05:00
David Teigland
db533560f8 improve reading and repairing vg metadata
The fact that vg repair is implemented as a part of vg read
has led to a messy and complicated implementation of vg_read,
and limited and uncontrolled repair capability.  This splits
read and repair apart.

Summary
-------

- take all kinds of various repairs out of vg_read
- vg_read no longer writes anything
- vg_read now simply reads and returns vg metadata
- vg_read ignores bad or old copies of metadata
- vg_read proceeds with a single good copy of metadata
- improve error checks and handling when reading
- keep track of bad (corrupt) copies of metadata in lvmcache
- keep track of old (seqno) copies of metadata in lvmcache
- keep track of outdated PVs in lvmcache
- vg_write will do basic repairs
- new command vgck --updatemetdata will do all repairs

Details
-------

- In scan, do not delete dev from lvmcache if reading/processing fails;
  the dev is still present, and removing it makes it look like the dev
  is not there.  Records are now kept about the problems with each PV
  so they be fixed/repaired in the appropriate places.

- In scan, record a bad mda on failure, and delete the mda from
  mda in use list so it will not be used by vg_read or vg_write,
  only by repair.

- In scan, succeed if any good mda on a device is found, instead of
  failing if any is bad.  The bad/old copies of metadata should not
  interfere with normal usage while good copies can be used.

- In scan, add a record of old mdas in lvmcache for later, do not repair
  them while reading, and do not let them prevent us from finding and
  using a good copy of metadata from elsewhere.  One result is that
  "inconsistent metadata" is no longer a read error, but instead a
  record in lvmcache that can be addressed separate from the read.

- Treat a dev with no good mdas like a dev with no mdas, which is an
  existing case we already handle.

- Don't use a fake vg "handle" for returning an error from vg_read,
  or the vg_read_error function for getting that error number;
  just return null if the vg cannot be read or used, and an error_flags
  arg with flags set for the specific kind of error (which can be used
  later for determining the kind of repair.)

- Saving an original copy of the vg metadata, for purposes of reverting
  a write, is now done explicitly in vg_read instead of being hidden in
  the vg_make_handle function.

- When a vg is not accessible due to "access restrictions" but is
  otherwise fine, return the vg through the new error_vg arg so that
  process_each_pv can skip the PVs in the VG while processing.
  (This is a temporary accomodation for the way process_each_pv
  tracks which devs have been looked at, and can be dropped later
  when process_each_pv implementation dev tracking is changed.)

- vg_read does not try to fix or recover a vg, but now just reads the
  metadata, checks access restrictions and returns it.
  (Checking access restrictions might be better done outside of vg_read,
   but this is a later improvement.)

- _vg_read now simply makes one attempt to read metadata from
  each mda, and uses the most recent copy to return to the caller
  in the form of a 'vg' struct.
  (bad mdas were excluded during the scan and are not retried)
  (old mdas were not excluded during scan and are retried here)

- vg_read uses _vg_read to get the latest copy of metadata from mdas,
  and then makes various checks against it to produce warnings,
  and to check if VG access is allowed (access restrictions include:
  writable, foreign, shared, clustered, missing pvs).

- Things that were previously silently/automatically written by vg_read
  that are now done by vg_write, based on the records made in lvmcache
  during the scan and read:
  . clearing the missing flag
  . updating old copies of metadata
  . clearing outdated pvs
  . updating pv header flags

- Bad/corrupt metadata are now repaired; they were not before.

Test changes
------------

- A read command no longer writes the VG to repair it, so add a write
  command to do a repair.
  (inconsistent-metadata, unlost-pv)

- When a missing PV is removed from a VG, and then the device is
  enabled again, vgck --updatemetadata is needed to clear the
  outdated PV before it can be used again, where it wasn't before.
  (lvconvert-repair-policy, lvconvert-repair-raid, lvconvert-repair,
   mirror-vgreduce-removemissing, pv-ext-flags, unlost-pv)

Reading bad/old metadata
------------------------

- "bad metadata": the mda_header or metadata text has invalid fields
  or can't be parsed by lvm.  This is a form of corruption that would
  not be caused by known failure scenarios.  A checksum error is
  typically included among the errors reported.

- "old metadata": a valid copy of the metadata that has a smaller seqno
  than other copies of the metadata.  This can happen if the device
  failed, or io failed, or lvm failed while commiting new metadata
  to all the metadata areas.  Old metadata on a PV that has been
  removed from the VG is the "outdated" case below.

When a VG has some PVs with bad/old metadata, lvm can simply ignore
the bad/old copies, and use a good copy.  This is why there are
multiple copies of the metadata -- so it's available even when some
of the copies cannot be used.  The bad/old copies do not have to be
repaired before the VG can be used (the repair can happen later.)

A PV with no good copies of the metadata simply falls back to being
treated like a PV with no mdas; a common and harmless configuration.

When bad/old metadata exists, lvm warns the user about it, and
suggests repairing it using a new metadata repair command.
Bad metadata in particular is something that users will want to
investigate and repair themselves, since it should not happen and
may indicate some other problem that needs to be fixed.

PVs with bad/old metadata are not the same as missing devices.
Missing devices will block various kinds of VG modification or
activation, but bad/old metadata will not.

Previously, lvm would attempt to repair bad/old metadata whenever
it was read.  This was unnecessary since lvm does not require every
copy of the metadata to be used.  It would also hide potential
problems that should be investigated by the user.  It was also
dangerous in cases where the VG was on shared storage.  The user
is now allowed to investigate potential problems and decide how
and when to repair them.

Repairing bad/old metadata
--------------------------

When label scan sees bad metadata in an mda, that mda is removed
from the lvmcache info->mdas list.  This means that vg_read will
skip it, and not attempt to read/process it again.  If it was
the only in-use mda on a PV, that PV is treated like a PV with
no mdas.  It also means that vg_write will also skip the bad mda,
and not attempt to write new metadata to it.  The only way to
repair bad metadata is with the metadata repair command.

When label scan sees old metadata in an mda, that mda is kept
in the lvmcache info->mdas list.  This means that vg_read will
read/process it again, and likely see the same mismatch with
the other copies of the metadata.  Like the label_scan, the
vg_read will simply ignore the old copy of the metadata and
use the latest copy.  If the command is modifying the vg
(e.g. lvcreate), then vg_write, which writes new metadata to
every mda on info->mdas, will write the new metadata to the
mda that had the old version.  If successful, this will resolve
the old metadata problem (without needing to run a metadata
repair command.)

Outdated PVs
------------

An outdated PV is a PV that has an old copy of VG metadata
that shows it is a member of the VG, but the latest copy of
the VG metadata does not include this PV.  This happens if
the PV is disconnected, vgreduce --removemissing is run to
remove the PV from the VG, then the PV is reconnected.
In this case, the outdated PV needs have its outdated metadata
removed and the PV used flag needs to be cleared.  This repair
will be done by the subsequent repair command.  It is also done
if vgremove is run on the VG.

MISSING PVs
-----------

When a device is missing, most commands will refuse to modify
the VG.  This is the simple case.  More complicated is when
a command is allowed to modify the VG while it is missing a
device.

When a VG is written while a device is missing for one of it's PVs,
the VG metadata is written to disk with the MISSING flag on the PV
with the missing device.  When the VG is next used, it is treated
as if the PV with the MISSING flag still has a missing device, even
if that device has reappeared.

If all LVs that were using a PV with the MISSING flag are removed
or repaired so that the MISSING PV is no longer used, then the
next time the VG metadata is written, the MISSING flag will be
dropped.

Alternative methods of clearing the MISSING flag are:

vgreduce --removemissing will remove PVs with missing devices,
or PVs with the MISSING flag where the device has reappeared.

vgextend --restoremissing will clear the MISSING flag on PVs
where the device has reappeared, allowing the VG to be used
normally.  This must be done with caution since the reappeared
device may have old data that is inconsistent with data on other PVs.

Bad mda repair
--------------

The new command:
vgck --updatemetadata VG

first uses vg_write to repair old metadata, and other basic
issues mentioned above (old metadata, outdated PVs, pv_header
flags, MISSING_PV flags).  It will also go further and repair
bad metadata:

. text metadata that has a bad checksum
. text metadata that is not parsable
. corrupt mda_header checksum and version fields

(To keep a clean diff, #if 0 is added around functions that
are replaced by new code.  These commented functions are
removed by the following commit.)
2019-05-24 13:10:31 -05:00
David Teigland
ad293cc3ae add a warning message when updating old metadata
in an mda that had previously not been updated
2019-05-24 12:01:27 -05:00
David Teigland
412c3b9f5c vgcfgbackup add error messages 2019-05-24 12:01:20 -05:00
David Teigland
a4af0a4f6c vgck --updatemetadata is a new command
uses vg_write to correct more common or less severe issues,
and also adds the ability to repair some metadata corruption
that couldn't be handled previously.
2019-05-24 12:01:15 -05:00
David Teigland
7cc002d915 move pv header repairs to vg_write
Correct PV header in-use or version fields
from vg_write instead of vg_read.
2019-05-24 12:01:08 -05:00
David Teigland
7990c490e9 process_each_pv handle outdated pvs
process_each_pv should account for outdated pvs
in the list of all devices it is processing.
2019-05-24 12:01:04 -05:00
David Teigland
b2aba2c3d3 move wipe_outdated_pvs to vg_write
and implement it based on a device, not based
on a pv struct (which is not available when the
device is not a part of the vg.)

currently only the vgremove command wipes outdated
pvs until more advanced recovery is added in a
subsequent commit
2019-05-24 12:01:00 -05:00
David Teigland
f1d89c1468 create separate lvmcache update functions for read and write
The vg read and vg write cases need to update lvmcache
differently, so create separate functions for them.

The read case now handles checking for outdated mdas
and moves them aside into a new list to be repaired in
a subsequent commit.
2019-05-24 12:00:55 -05:00
David Teigland
6358a0b8c6 fix vg_commit return value
The existing comment was desribing the correct behavior,
but the code didn't match.  The commit is successful if
one mda was committed.  Making it depend on the result of
the internal lvmcache update was wrong.
2019-05-24 12:00:51 -05:00
David Teigland
2335029a6c change args for text label read function
Have the caller pass the label_sector to the read
function so the read function can set the sector
field in the label struct, instead of having the
read function return a pointer to the label for
the caller to set the sector field.

Also have the read function return a flag indicating
to the caller that the scanned device was identified
as a duplicate pv.
2019-05-24 12:00:45 -05:00
David Teigland
ebd4f96f3a add mda arg to add_mda
Allow the caller of lvmcache_add_mda() to have the
new mda returned.
2019-05-24 12:00:41 -05:00
David Teigland
57787592e0 keep track of which mdas have old metadata in lvmcache
This will be used for more advanced repair in a
subsequent commit.
2019-05-24 12:00:36 -05:00
David Teigland
85cbc40704 ability to keep track of outdated pvs in lvmcache
Outdated PVs hold metadata for VG from which they
have been removed.  Add the ability to keep track
of these in lvmcache.
This will be used for more advanced repair in a
subsequent commit.
2019-05-24 12:00:32 -05:00
David Teigland
088b9a68b4 ability to keep track of bad mdas in lvmcache
mda's that cannot be processed by lvm because of
some corruption can be kept on a separate list.
These will be used for more advanced repair in a
subsequent commit.
2019-05-24 12:00:28 -05:00
David Teigland
022182dfb8 add flags to keep track of bad metadata
When reading metadata headers and text, use a new set
of flags to identify specific errors that are seen.
These will be used for more advanced repair in a
subsequent commit.
2019-05-24 12:00:24 -05:00
66 changed files with 1677 additions and 2771 deletions

View File

@@ -1 +1 @@
2.03.05(2)-git (2019-06-10)
2.03.02(2)-git (2018-10-31)

View File

@@ -1 +1 @@
1.02.163-git (2019-06-10)
1.02.155-git (2018-10-31)

View File

@@ -1,20 +1,5 @@
Version 2.03.05 -
================================
Fix command definition for pvchange -a.
Add vgck --updatemetadata command that will repair metadata problems.
Improve VG reading to work if one good copy of metadata is found.
Report/display/scan commands that read VGs will no longer write/repair.
Move metadata repairs from VG reading to VG writing.
Add config setting md_component_checks to control MD component checks.
Add end of device MD component checks when dev has no udev info.
Version 2.03.04 - 10th June 2019
================================
Remove unused_duplicate_devs from cmd causing segfault in dmeventd.
Version 2.03.03 - 07th June 2019
================================
Report no_discard_passdown for cache LVs with lvs -o+kernel_discards.
Version 2.03.02 -
===================================
Add pvck --dump option to extract metadata.
Fix signal delivery checking race in libdaemon (lvmetad).
Add missing Before=shutdown.target to LVM2 services to fix shutdown ordering.
@@ -49,14 +34,10 @@ Version 2.03.03 - 07th June 2019
Fix missing unlock on lvm2 dmeventd plugin error path initialization.
Improve Makefile dependency tracking.
Move VDO support towards V2 target (6.2) support.
Version 2.03.02 - 18th December 2018
====================================
Fix missing proper initialization of pv_list struct when adding pv.
Fix (de)activation of RaidLVs with visible SubLVs.
Prohibit mirrored 'mirror' log via lvcreate and lvconvert.
Fix (de)activation of RaidLVs with visible SubLVs
Prohibit mirrored 'mirror' log via lvcreate and lvconvert
Use sync io if async io_setup fails, or use_aio=0 is set in config.
Fix more issues reported by coverity scan.
Version 2.03.01 - 31st October 2018
===================================

View File

@@ -1,21 +1,10 @@
Version 1.02.163 -
=================================
Version 1.02.161 - 10th June 2019
=================================
Version 1.02.159 - 07th June 2019
=================================
Parsing of cache status understand no_discard_passdown.
Version 1.02.155 -
====================================
Ensure migration_threshold for cache is at least 8 chunks.
Version 1.02.155 - 18th December 2018
=====================================
Include correct internal header inside libdm list.c.
Enhance ioctl flattening and add parameters only when needed.
Add DM_DEVICE_ARM_POLL for API completness matching kernel.
Do not add parameters for RESUME with DM_DEVICE_CREATE dm task.
Fix dmstats report printing no output.
Version 1.02.153 - 31st October 2018
====================================

View File

@@ -88,22 +88,6 @@ devices {
#
external_device_info_source = "none"
# Configuration option devices/hints.
# Use a local file to remember which devices have PVs on them.
# Some commands will use this as an optimization to reduce device
# scanning, and will only scan the listed PVs. Removing the hint file
# will cause lvm to generate a new one. Disable hints if PVs will
# be copied onto devices using non-lvm commands, like dd.
#
# Accepted values:
# all
# Use all hints.
# none
# Use no hints.
#
# This configuration option has an automatic default value.
# hints = "all"
# Configuration option devices/preferred_names.
# Select which path name to display for a block device.
# If multiple path names exist for a block device, and LVM needs to
@@ -183,52 +167,17 @@ devices {
sysfs_scan = 1
# Configuration option devices/scan_lvs.
# Scan LVM LVs for layered PVs, allowing LVs to be used as PVs.
# When 1, LVM will detect PVs layered on LVs, and caution must be
# taken to avoid a host accessing a layered VG that may not belong
# to it, e.g. from a guest image. This generally requires excluding
# the LVs with device filters. Also, when this setting is enabled,
# every LVM command will scan every active LV on the system (unless
# filtered), which can cause performance problems on systems with
# many active LVs. When this setting is 0, LVM will not detect or
# use PVs that exist on LVs, and will not allow a PV to be created on
# an LV. The LVs are ignored using a built in device filter that
# identifies and excludes LVs.
scan_lvs = 0
# Scan LVM LVs for layered PVs.
scan_lvs = 1
# Configuration option devices/multipath_component_detection.
# Ignore devices that are components of DM multipath devices.
multipath_component_detection = 1
# Configuration option devices/md_component_detection.
# Enable detection and exclusion of MD component devices.
# An MD component device is a block device that MD uses as part
# of a software RAID virtual device. When an LVM PV is created
# on an MD device, LVM must only use the top level MD device as
# the PV, and should ignore the underlying component devices.
# In cases where the MD superblock is located at the end of the
# component devices, it is more difficult for LVM to consistently
# identify an MD component, see the md_component_checks setting.
# Ignore devices that are components of software RAID (md) devices.
md_component_detection = 1
# Configuration option devices/md_component_checks.
# The checks LVM should use to detect MD component devices.
# MD component devices are block devices used by MD software RAID.
#
# Accepted values:
# auto
# LVM will skip scanning the end of devices when it has other
# indications that the device is not an MD component.
# start
# LVM will only scan the start of devices for MD superblocks.
# This does not incur extra I/O by LVM.
# full
# LVM will scan the start and end of devices for MD superblocks.
# This requires an extra read at the end of devices.
#
# This configuration option has an automatic default value.
# md_component_checks = "auto"
# Configuration option devices/fw_raid_component_detection.
# Ignore devices that are components of firmware RAID devices.
# LVM must use an external_device_info_source other than none for this
@@ -771,8 +720,7 @@ log {
# Configuration option log/indent.
# Indent messages according to their severity.
# This configuration option has an automatic default value.
# indent = 0
indent = 1
# Configuration option log/command_names.
# Display the command name on each line of output.
@@ -798,20 +746,6 @@ log {
# available: memory, devices, io, activation, allocation,
# metadata, cache, locking, lvmpolld. Use "all" to see everything.
debug_classes = [ "memory", "devices", "io", "activation", "allocation", "metadata", "cache", "locking", "lvmpolld", "dbus" ]
# Configuration option log/debug_file_fields.
# The fields included in debug output written to log file.
# Use "all" to include everything (the default).
# This configuration option is advanced.
# This configuration option has an automatic default value.
# debug_file_fields = [ "time", "command", "fileline", "message" ]
# Configuration option log/debug_output_fields.
# The fields included in debug output written to stderr.
# Use "all" to include everything (the default).
# This configuration option is advanced.
# This configuration option has an automatic default value.
# debug_output_fields = [ "time", "command", "fileline", "message" ]
}
# Configuration section backup.
@@ -1240,16 +1174,6 @@ global {
# When enabled, an LVM command that changes PVs, changes VG metadata,
# or changes the activation state of an LV will send a notification.
notify_dbus = 1
# Configuration option global/io_memory_size.
# The amount of memory in KiB that LVM allocates to perform disk io.
# LVM performance may benefit from more io memory when there are many
# disks or VG metadata is large. Increasing this size may be necessary
# when a single copy of VG metadata is larger than the current setting.
# This value should usually not be decreased from the default; setting
# it too low can result in lvm failing to read VGs.
# This configuration option has an automatic default value.
# io_memory_size = 8192
}
# Configuration section activation.

105
configure vendored
View File

@@ -742,7 +742,6 @@ CLDNOWHOLEARCHIVE
CLDFLAGS
CACHE
BUILD_DMFILEMAPD
BUILD_LOCKDDLM_CONTROL
BUILD_LOCKDDLM
BUILD_LOCKDSANLOCK
BUILD_LVMLOCKD
@@ -772,8 +771,6 @@ BLKID_LIBS
BLKID_CFLAGS
NOTIFY_DBUS_LIBS
NOTIFY_DBUS_CFLAGS
LOCKD_DLM_CONTROL_LIBS
LOCKD_DLM_CONTROL_CFLAGS
LOCKD_DLM_LIBS
LOCKD_DLM_CFLAGS
LOCKD_SANLOCK_LIBS
@@ -935,7 +932,6 @@ enable_devmapper
enable_lvmpolld
enable_lvmlockd_sanlock
enable_lvmlockd_dlm
enable_lvmlockd_dlmcontrol
enable_use_lvmlockd
with_lvmlockd_pidfile
enable_use_lvmpolld
@@ -1004,8 +1000,6 @@ LOCKD_SANLOCK_CFLAGS
LOCKD_SANLOCK_LIBS
LOCKD_DLM_CFLAGS
LOCKD_DLM_LIBS
LOCKD_DLM_CONTROL_CFLAGS
LOCKD_DLM_CONTROL_LIBS
NOTIFY_DBUS_CFLAGS
NOTIFY_DBUS_LIBS
BLKID_CFLAGS
@@ -1649,8 +1643,6 @@ Optional Features:
--enable-lvmlockd-sanlock
enable the LVM lock daemon using sanlock
--enable-lvmlockd-dlm enable the LVM lock daemon using dlm
--enable-lvmlockd-dlmcontrol
enable lvmlockd remote refresh using libdlmcontrol
--disable-use-lvmlockd disable usage of LVM lock daemon
--disable-use-lvmpolld disable usage of LVM Poll Daemon
--enable-dmfilemapd enable the dmstats filemap daemon
@@ -1796,10 +1788,6 @@ Some influential environment variables:
C compiler flags for LOCKD_DLM, overriding pkg-config
LOCKD_DLM_LIBS
linker flags for LOCKD_DLM, overriding pkg-config
LOCKD_DLM_CONTROL_CFLAGS
C compiler flags for LOCKD_DLM_CONTROL, overriding pkg-config
LOCKD_DLM_CONTROL_LIBS
linker flags for LOCKD_DLM_CONTROL, overriding pkg-config
NOTIFY_DBUS_CFLAGS
C compiler flags for NOTIFY_DBUS, overriding pkg-config
NOTIFY_DBUS_LIBS
@@ -3089,7 +3077,6 @@ case "$host_os" in
BUILD_LVMPOLLD=no
LOCKDSANLOCK=no
LOCKDDLM=no
LOCKDDLM_CONTROL=no
ODIRECT=yes
DM_IOCTLS=yes
SELINUX=yes
@@ -10971,97 +10958,6 @@ $as_echo "#define LOCKDDLM_SUPPORT 1" >>confdefs.h
BUILD_LVMLOCKD=yes
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockddlmcontrol" >&5
$as_echo_n "checking whether to build lvmlockddlmcontrol... " >&6; }
# Check whether --enable-lvmlockd-dlmcontrol was given.
if test "${enable_lvmlockd_dlmcontrol+set}" = set; then :
enableval=$enable_lvmlockd_dlmcontrol; LOCKDDLM_CONTROL=$enableval
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LOCKDDLM_CONTROL" >&5
$as_echo "$LOCKDDLM_CONTROL" >&6; }
BUILD_LOCKDDLM_CONTROL=$LOCKDDLM_CONTROL
if test "$BUILD_LOCKDDLM_CONTROL" = yes; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LOCKD_DLM_CONTROL" >&5
$as_echo_n "checking for LOCKD_DLM_CONTROL... " >&6; }
if test -n "$LOCKD_DLM_CONTROL_CFLAGS"; then
pkg_cv_LOCKD_DLM_CONTROL_CFLAGS="$LOCKD_DLM_CONTROL_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdlmcontrol >= 3.2\""; } >&5
($PKG_CONFIG --exists --print-errors "libdlmcontrol >= 3.2") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LOCKD_DLM_CONTROL_CFLAGS=`$PKG_CONFIG --cflags "libdlmcontrol >= 3.2" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$LOCKD_DLM_CONTROL_LIBS"; then
pkg_cv_LOCKD_DLM_CONTROL_LIBS="$LOCKD_DLM_CONTROL_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdlmcontrol >= 3.2\""; } >&5
($PKG_CONFIG --exists --print-errors "libdlmcontrol >= 3.2") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_LOCKD_DLM_CONTROL_LIBS=`$PKG_CONFIG --libs "libdlmcontrol >= 3.2" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
LOCKD_DLM_CONTROL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libdlmcontrol >= 3.2" 2>&1`
else
LOCKD_DLM_CONTROL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libdlmcontrol >= 3.2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$LOCKD_DLM_CONTROL_PKG_ERRORS" >&5
$bailout
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$bailout
else
LOCKD_DLM_CONTROL_CFLAGS=$pkg_cv_LOCKD_DLM_CONTROL_CFLAGS
LOCKD_DLM_CONTROL_LIBS=$pkg_cv_LOCKD_DLM_CONTROL_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
HAVE_LOCKD_DLM_CONTROL=yes
fi
$as_echo "#define LOCKDDLM_CONTROL_SUPPORT 1" >>confdefs.h
BUILD_LVMLOCKD=yes
fi
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build lvmlockd" >&5
$as_echo_n "checking whether to build lvmlockd... " >&6; }
@@ -13888,7 +13784,6 @@ _ACEOF
################################################################################

View File

@@ -903,7 +903,6 @@ int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
#define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002
#define DM_CACHE_FEATURE_PASSTHROUGH 0x00000004
#define DM_CACHE_FEATURE_METADATA2 0x00000008 /* cache v1.10 */
#define DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN 0x00000010
struct dm_config_node;
/*

View File

@@ -296,8 +296,6 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
else if (!strncmp(p, "metadata2 ", 10))
s->feature_flags |= DM_CACHE_FEATURE_METADATA2;
else if (!strncmp(p, "no_discard_passdown ", 20))
s->feature_flags |= DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN;
else
log_error("Unknown feature in status: %s", params);

View File

@@ -295,6 +295,9 @@
/* Define to 1 if you have the `pselect' function. */
#undef HAVE_PSELECT
/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
/* Define to 1 if the system has the type `ptrdiff_t'. */
#undef HAVE_PTRDIFF_T
@@ -534,9 +537,6 @@
/* Locale-dependent data */
#undef LOCALEDIR
/* Define to 1 to include code that uses lvmlockd dlm control option. */
#undef LOCKDDLM_CONTROL_SUPPORT
/* Define to 1 to include code that uses lvmlockd dlm option. */
#undef LOCKDDLM_SUPPORT

202
lib/cache/lvmcache.c vendored
View File

@@ -74,7 +74,6 @@ static struct dm_hash_table *_vgname_hash = NULL;
static DM_LIST_INIT(_vginfos);
static DM_LIST_INIT(_found_duplicate_devs);
static DM_LIST_INIT(_unused_duplicate_devs);
static DM_LIST_INIT(_prev_unused_duplicate_devs);
static int _vgs_locked = 0;
static int _found_duplicate_pvs = 0; /* If we never see a duplicate PV we can skip checking for them later. */
static int _found_duplicate_vgnames = 0;
@@ -90,7 +89,6 @@ int lvmcache_init(struct cmd_context *cmd)
dm_list_init(&_vginfos);
dm_list_init(&_found_duplicate_devs);
dm_list_init(&_unused_duplicate_devs);
dm_list_init(&_prev_unused_duplicate_devs);
if (!(_vgname_hash = dm_hash_create(128)))
return 0;
@@ -117,6 +115,11 @@ void lvmcache_unlock_vgname(const char *vgname)
}
}
int lvmcache_vgs_locked(void)
{
return _vgs_locked;
}
/*
* When lvmcache sees a duplicate PV, this is set.
* process_each_pv() can avoid searching for duplicates
@@ -278,6 +281,60 @@ struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname, const ch
return vginfo;
}
const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd,
const char *vgname, const char *vgid,
unsigned revalidate_labels)
{
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
struct dm_list *devh, *tmp;
struct dm_list devs;
struct device_list *devl;
char vgid_found[ID_LEN + 1] __attribute__((aligned(8)));
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
stack;
return NULL;
}
/*
* If this function is called repeatedly, only the first one needs to revalidate.
*/
if (!revalidate_labels)
goto out;
/*
* This function is normally called before reading metadata so
* we check cached labels here. Unfortunately vginfo is volatile.
*/
dm_list_init(&devs);
dm_list_iterate_items(info, &vginfo->infos) {
if (!(devl = malloc(sizeof(*devl)))) {
log_error("device_list element allocation failed");
return NULL;
}
devl->dev = info->dev;
dm_list_add(&devs, &devl->list);
}
memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found));
dm_list_iterate_safe(devh, tmp, &devs) {
devl = dm_list_item(devh, struct device_list);
label_read(devl->dev);
dm_list_del(&devl->list);
free(devl);
}
/* If vginfo changed, caller needs to rescan */
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid_found)) ||
strncmp(vginfo->vgid, vgid_found, ID_LEN))
return NULL;
out:
return vginfo->fmt;
}
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid)
{
struct lvmcache_vginfo *vginfo;
@@ -552,11 +609,8 @@ next:
*/
if (!(info = lvmcache_info_from_pvid(alt->dev->pvid, NULL, 0))) {
/*
* This will happen if a duplicate dev has been dropped already,
* e.g. it was found to be an md component.
*/
log_debug("PVID %s on duplicate device %s not found in cache.",
/* This shouldn't happen */
log_warn("WARNING: PV %s on duplicate device %s not found in cache.",
alt->dev->pvid, dev_name(alt->dev));
goto next;
}
@@ -583,14 +637,14 @@ next:
if (!prev_unchosen1 && !prev_unchosen2) {
/*
* The prev list saves the unchosen preference across
* The cmd list saves the unchosen preference across
* lvmcache_destroy. Sometimes a single command will
* fill lvmcache, destroy it, and refill it, and we
* want the same duplicate preference to be preserved
* in each instance of lvmcache for a single command.
*/
prev_unchosen1 = dev_in_device_list(dev1, &_prev_unused_duplicate_devs);
prev_unchosen2 = dev_in_device_list(dev2, &_prev_unused_duplicate_devs);
prev_unchosen1 = dev_in_device_list(dev1, &cmd->unused_duplicate_devs);
prev_unchosen2 = dev_in_device_list(dev2, &cmd->unused_duplicate_devs);
}
dev1_major = MAJOR(dev1->dev);
@@ -947,26 +1001,49 @@ int lvmcache_label_scan(struct cmd_context *cmd)
return r;
}
int lvmcache_get_vgnameids(struct cmd_context *cmd,
struct dm_list *vgnameids,
const char *only_this_vgname,
int include_internal)
/*
* lvmcache_label_scan() detects duplicates in the basic label_scan(), then
* filters out some dups, and chooses preferred duplicates to use.
*/
void lvmcache_pvscan_duplicate_check(struct cmd_context *cmd)
{
struct device_list *devl;
/* Check if label_scan() detected any dups. */
if (!_found_duplicate_pvs)
return;
/*
* Once all the dups are identified, they are moved from the
* "found" list to the "unused" list to sort out.
*/
dm_list_splice(&_unused_duplicate_devs, &_found_duplicate_devs);
/*
* Remove items from the dups list that we know are the same
* underlying dev, e.g. md components, that we want to just ignore.
*/
_filter_duplicate_devs(cmd);
/*
* no more dups after ignoring some
*/
if (!_found_duplicate_pvs)
return;
/* Duplicates are found where we would have to pick one. */
dm_list_iterate_items(devl, &_unused_duplicate_devs)
log_warn("WARNING: found device with duplicate %s", dev_name(devl->dev));
}
int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
struct dm_list *vgnameids)
{
struct vgnameid_list *vgnl;
struct lvmcache_vginfo *vginfo;
if (only_this_vgname) {
if (!(vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl)))) {
log_error("vgnameid_list allocation failed.");
return 0;
}
vgnl->vg_name = dm_pool_strdup(cmd->mem, only_this_vgname);
vgnl->vgid = NULL;
dm_list_add(vgnameids, &vgnl->list);
return 1;
}
dm_list_iterate_items(vginfo, &_vginfos) {
if (!include_internal && is_orphan_vg(vginfo->vgname))
continue;
@@ -990,6 +1067,49 @@ int lvmcache_get_vgnameids(struct cmd_context *cmd,
return 1;
}
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid)
{
struct dm_list *pvids;
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info;
if (!(pvids = str_list_create(cmd->mem))) {
log_error("pvids list allocation failed");
return NULL;
}
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid)))
return pvids;
dm_list_iterate_items(info, &vginfo->infos) {
if (!str_list_add(cmd->mem, pvids,
dm_pool_strdup(cmd->mem, info->dev->pvid))) {
log_error("strlist allocation failed");
return NULL;
}
}
return pvids;
}
int lvmcache_get_vg_devs(struct cmd_context *cmd,
struct lvmcache_vginfo *vginfo,
struct dm_list *devs)
{
struct lvmcache_info *info;
struct device_list *devl;
dm_list_iterate_items(info, &vginfo->infos) {
if (!(devl = dm_pool_zalloc(cmd->mem, sizeof(*devl))))
return_0;
devl->dev = info->dev;
dm_list_add(devs, &devl->list);
}
return 1;
}
static struct device *_device_from_pvid(const struct id *pvid, uint64_t *label_sector)
{
struct lvmcache_info *info;
@@ -1958,8 +2078,8 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
dm_list_init(&_vginfos);
/*
* Move the current _unused_duplicate_devs to _prev_unused_duplicate_devs
* before destroying _unused_duplicate_devs.
* Copy the current _unused_duplicate_devs into a cmd list before
* destroying _unused_duplicate_devs.
*
* One command can init/populate/destroy lvmcache multiple times. Each
* time it will encounter duplicates and choose the preferrred devs.
@@ -1967,8 +2087,8 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
* the unpreferred devs here so that _choose_preferred_devs can use
* this to make the same choice each time.
*/
_destroy_duplicate_device_list(&_prev_unused_duplicate_devs);
dm_list_splice(&_prev_unused_duplicate_devs, &_unused_duplicate_devs);
dm_list_init(&cmd->unused_duplicate_devs);
lvmcache_get_unused_duplicate_devs(cmd, &cmd->unused_duplicate_devs);
_destroy_duplicate_device_list(&_unused_duplicate_devs);
_destroy_duplicate_device_list(&_found_duplicate_devs); /* should be empty anyway */
_found_duplicate_pvs = 0;
@@ -2270,6 +2390,26 @@ uint32_t lvmcache_ext_flags(struct lvmcache_info *info) {
return info->ext_flags;
}
int lvmcache_is_orphan(struct lvmcache_info *info) {
if (!info->vginfo)
return 1; /* FIXME? */
return is_orphan_vg(info->vginfo->vgname);
}
int lvmcache_vgid_is_cached(const char *vgid) {
struct lvmcache_vginfo *vginfo;
vginfo = lvmcache_vginfo_from_vgid(vgid);
if (!vginfo || !vginfo->vgname)
return 0;
if (is_orphan_vg(vginfo->vgname))
return 0;
return 1;
}
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info)
{
if (!info)
@@ -2519,7 +2659,7 @@ void lvmcache_del_outdated_devs(struct cmd_context *cmd,
struct lvmcache_info *info, *info2;
if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
log_error(INTERNAL_ERROR "lvmcache_del_outdated_devs no vginfo");
log_error(INTERNAL_ERROR "lvmcache_get_outdated_devs no vginfo");
return;
}

35
lib/cache/lvmcache.h vendored
View File

@@ -91,8 +91,12 @@ void lvmcache_lock_vgname(const char *vgname, int read_only);
void lvmcache_unlock_vgname(const char *vgname);
/* Queries */
const struct format_type *lvmcache_fmt_from_vgname(struct cmd_context *cmd, const char *vgname, const char *vgid, unsigned revalidate_labels);
int lvmcache_lookup_mda(struct lvmcache_vgsummary *vgsummary);
/* Decrement and test if there are still vg holders in vginfo. */
int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo);
struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
@@ -102,11 +106,14 @@ const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgnam
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);
int lvmcache_vgs_locked(void);
int lvmcache_get_vgnameids(struct cmd_context *cmd,
struct dm_list *vgnameids,
const char *only_this_vgname,
int include_internal);
int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
struct dm_list *vgnameids);
/* Returns list of struct dm_str_list containing pool-allocated copy of pvids */
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid);
void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
@@ -160,7 +167,9 @@ int lvmcache_foreach_pv(struct lvmcache_vginfo *vginfo,
uint64_t lvmcache_device_size(struct lvmcache_info *info);
void lvmcache_set_device_size(struct lvmcache_info *info, uint64_t size);
struct device *lvmcache_device(struct lvmcache_info *info);
int lvmcache_is_orphan(struct lvmcache_info *info);
unsigned lvmcache_mda_count(struct lvmcache_info *info);
int lvmcache_vgid_is_cached(const char *vgid);
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info);
struct metadata_area *lvmcache_get_mda(struct cmd_context *cmd,
@@ -171,6 +180,8 @@ struct metadata_area *lvmcache_get_mda(struct cmd_context *cmd,
int lvmcache_found_duplicate_pvs(void);
int lvmcache_found_duplicate_vgnames(void);
void lvmcache_pvscan_duplicate_check(struct cmd_context *cmd);
int lvmcache_get_unused_duplicate_devs(struct cmd_context *cmd, struct dm_list *head);
int vg_has_duplicate_pvs(struct volume_group *vg);
@@ -182,16 +193,32 @@ void lvmcache_get_max_name_lengths(struct cmd_context *cmd,
int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const char *vgid);
void lvmcache_lock_ordering(int enable);
int lvmcache_dev_is_unchosen_duplicate(struct device *dev);
void lvmcache_remove_unchosen_duplicate(struct device *dev);
int lvmcache_pvid_in_unchosen_duplicates(const char *pvid);
int lvmcache_get_vg_devs(struct cmd_context *cmd,
struct lvmcache_vginfo *vginfo,
struct dm_list *devs);
void lvmcache_set_independent_location(const char *vgname);
bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid);
/*
* These are clvmd-specific functions and are not related to lvmcache.
* FIXME: rename these with a clvm_ prefix in place of lvmcache_
*/
void lvmcache_save_vg(struct volume_group *vg, int precommitted);
struct volume_group *lvmcache_get_saved_vg(const char *vgid, int precommitted);
struct volume_group *lvmcache_get_saved_vg_latest(const char *vgid);
void lvmcache_drop_saved_vgid(const char *vgid);
uint64_t lvmcache_max_metadata_size(void);
void lvmcache_save_metadata_size(uint64_t val);

View File

@@ -1715,6 +1715,8 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
if (!init_lvmcache_orphans(cmd))
goto_out;
dm_list_init(&cmd->unused_duplicate_devs);
if (!_init_segtypes(cmd))
goto_out;

View File

@@ -172,7 +172,6 @@ struct cmd_context {
unsigned pvscan_cache_single:1;
unsigned can_use_one_scan:1;
unsigned is_clvmd:1;
unsigned md_component_detection:1;
unsigned use_full_md_check:1;
unsigned is_activating:1;
unsigned enable_hints:1; /* hints are enabled for cmds in general */
@@ -186,7 +185,6 @@ struct cmd_context {
*/
struct dev_filter *filter;
struct dm_list hints;
const char *md_component_checks;
/*
* Configuration.
@@ -237,6 +235,7 @@ struct cmd_context {
const char *report_list_item_separator;
const char *time_format;
unsigned rand_seed;
struct dm_list unused_duplicate_devs; /* save preferences between lvmcache instances */
};
/*

View File

@@ -368,30 +368,7 @@ cfg(devices_multipath_component_detection_CFG, "multipath_component_detection",
"Ignore devices that are components of DM multipath devices.\n")
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"
"on an MD device, LVM must only use the top level MD device as\n"
"the PV, and should ignore the underlying component devices.\n"
"In cases where the MD superblock is located at the end of the\n"
"component devices, it is more difficult for LVM to consistently\n"
"identify an MD component, see the md_component_checks setting.\n")
cfg(devices_md_component_checks_CFG, "md_component_checks", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_MD_COMPONENT_CHECKS, vsn(2, 3, 2), NULL, 0, NULL,
"The checks LVM should use to detect MD component devices.\n"
"MD component devices are block devices used by MD software RAID.\n"
"#\n"
"Accepted values:\n"
" auto\n"
" LVM will skip scanning the end of devices when it has other\n"
" indications that the device is not an MD component.\n"
" start\n"
" LVM will only scan the start of devices for MD superblocks.\n"
" This does not incur extra I/O by LVM.\n"
" full\n"
" LVM will scan the start and end of devices for MD superblocks.\n"
" This requires an extra read at the end of devices.\n"
"#\n")
"Ignore devices that are components of software RAID (md) devices.\n")
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"

View File

@@ -318,6 +318,4 @@
#define DEFAULT_IO_MEMORY_SIZE_KB 8192
#define DEFAULT_MD_COMPONENT_CHECKS "auto"
#endif /* _LVM_DEFAULTS_H */

View File

@@ -110,17 +110,14 @@ static int _udev_dev_is_md_component(struct device *dev)
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))) {
dev->flags |= DEV_UDEV_INFO_MISSING;
if (!(value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE)))
return 0;
}
return !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID);
}
#else
static int _udev_dev_is_md_component(struct device *dev)
{
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}
#endif

View File

@@ -1170,10 +1170,8 @@ int udev_dev_is_md_component(struct device *dev)
const char *value;
int ret = 0;
if (!obtain_device_list_from_udev()) {
dev->flags |= DEV_UDEV_INFO_MISSING;
if (!obtain_device_list_from_udev())
return 0;
}
if (!(udev_device = _udev_get_dev(dev)))
return 0;
@@ -1200,7 +1198,6 @@ int udev_dev_is_mpath_component(struct device *dev)
int udev_dev_is_md_component(struct device *dev)
{
dev->flags |= DEV_UDEV_INFO_MISSING;
return 0;
}

View File

@@ -37,7 +37,6 @@
#define DEV_BCACHE_WRITE 0x00008000 /* bcache_fd is open with RDWR */
#define DEV_SCAN_FOUND_LABEL 0x00010000 /* label scan read dev and found label */
#define DEV_IS_MD_COMPONENT 0x00020000 /* device is an md component */
#define DEV_UDEV_INFO_MISSING 0x00040000 /* we have no udev info for this device */
/*
* Support for external device info.

View File

@@ -121,6 +121,158 @@ static struct device *_mda_get_device_raw(struct metadata_area *mda)
return mdac->area.dev;
}
/*
* For circular region between region_start and region_start + region_size,
* back up one SECTOR_SIZE from 'region_ptr' and return the value.
* This allows reverse traversal through text metadata area to find old
* metadata.
*
* Parameters:
* region_start: start of the region (bytes)
* region_size: size of the region (bytes)
* region_ptr: pointer within the region (bytes)
* NOTE: region_start <= region_ptr <= region_start + region_size
*/
static uint64_t _get_prev_sector_circular(uint64_t region_start,
uint64_t region_size,
uint64_t region_ptr)
{
if (region_ptr >= region_start + SECTOR_SIZE)
return region_ptr - SECTOR_SIZE;
return (region_start + region_size - SECTOR_SIZE);
}
/*
* Analyze a metadata area for old metadata records in the circular buffer.
* This function just looks through and makes a first pass at the data in
* the sectors for particular things.
* FIXME: do something with each metadata area (try to extract vg, write
* raw data to file, etc)
*/
static int _pv_analyze_mda_raw (const struct format_type * fmt,
struct metadata_area *mda)
{
struct mda_header *mdah;
struct raw_locn *rlocn;
uint64_t area_start;
uint64_t area_size;
uint64_t prev_sector, prev_sector2;
uint64_t latest_mrec_offset;
uint64_t offset;
uint64_t offset2;
size_t size;
size_t size2;
char *buf=NULL;
struct device_area *area;
struct mda_context *mdac;
uint32_t bad_fields = 0;
int r=0;
mdac = (struct mda_context *) mda->metadata_locn;
log_print("Found text metadata area: offset=" FMTu64 ", size="
FMTu64, mdac->area.start, mdac->area.size);
area = &mdac->area;
if (!(mdah = raw_read_mda_header(fmt, area, mda_is_primary(mda), 0, &bad_fields)))
goto_out;
rlocn = mdah->raw_locns;
/*
* The device area includes the metadata header as well as the
* records, so remove the metadata header from the start and size
*/
area_start = area->start + MDA_HEADER_SIZE;
area_size = area->size - MDA_HEADER_SIZE;
latest_mrec_offset = rlocn->offset + area->start;
/*
* Start searching at rlocn (point of live metadata) and go
* backwards.
*/
prev_sector = _get_prev_sector_circular(area_start, area_size,
latest_mrec_offset);
offset = prev_sector;
size = SECTOR_SIZE;
offset2 = size2 = 0;
while (prev_sector != latest_mrec_offset) {
prev_sector2 = prev_sector;
prev_sector = _get_prev_sector_circular(area_start, area_size,
prev_sector);
if (prev_sector > prev_sector2)
goto_out;
/*
* FIXME: for some reason, the whole metadata region from
* area->start to area->start+area->size is not used.
* Only ~32KB seems to contain valid metadata records
* (LVM2 format - format_text). As a result, I end up with
* "dm_config_maybe_section" returning true when there's no valid
* metadata in a sector (sectors with all nulls).
*/
if (!(buf = malloc(size + size2)))
goto_out;
if (!dev_read_bytes(area->dev, offset, size, buf)) {
log_error("Failed to read dev %s offset %llu size %llu",
dev_name(area->dev),
(unsigned long long)offset,
(unsigned long long)size);
goto out;
}
if (size2) {
if (!dev_read_bytes(area->dev, offset2, size2, buf + size)) {
log_error("Failed to read dev %s offset %llu size %llu",
dev_name(area->dev),
(unsigned long long)offset2,
(unsigned long long)size2);
goto out;
}
}
/*
* FIXME: We could add more sophisticated metadata detection
*/
if (dm_config_maybe_section(buf, size + size2)) {
/* FIXME: Validate region, pull out timestamp?, etc */
/* FIXME: Do something with this region */
log_verbose ("Found LVM2 metadata record at "
"offset=" FMTu64 ", size=" FMTsize_t ", "
"offset2=" FMTu64 " size2=" FMTsize_t,
offset, size, offset2, size2);
offset = prev_sector;
size = SECTOR_SIZE;
offset2 = size2 = 0;
} else {
/*
* Not a complete metadata record, assume we have
* metadata and just increase the size and offset.
* Start the second region if the previous sector is
* wrapping around towards the end of the disk.
*/
if (prev_sector > offset) {
offset2 = prev_sector;
size2 += SECTOR_SIZE;
} else {
offset = prev_sector;
size += SECTOR_SIZE;
}
}
free(buf);
buf = NULL;
}
r = 1;
out:
free(buf);
return r;
}
static int _text_lv_setup(struct format_instance *fid __attribute__((unused)),
struct logical_volume *lv)
{
@@ -1836,6 +1988,7 @@ static struct metadata_area_ops _metadata_text_raw_ops = {
.mda_free_sectors = _mda_free_sectors_raw,
.mda_total_sectors = _mda_total_sectors_raw,
.mda_in_vg = _mda_in_vg_raw,
.pv_analyze_mda = _pv_analyze_mda_raw,
.mda_locns_match = _mda_locns_match_raw,
.mda_get_device = _mda_get_device_raw,
};
@@ -2476,6 +2629,224 @@ bad:
return NULL;
}
static char *_read_metadata_text(struct cmd_context *cmd, struct device *dev,
uint64_t area_start, uint64_t area_size,
uint32_t *len, uint64_t *disk_offset)
{
struct mda_header *mh;
struct raw_locn *rlocn_slot0;
uint64_t text_offset, text_size;
char *area_buf;
char *text_buf;
/*
* Read the entire metadata area, including mda_header and entire
* circular buffer.
*/
if (!(area_buf = malloc(area_size)))
return_NULL;
if (!dev_read_bytes(dev, area_start, area_size, area_buf)) {
log_error("Failed to read device %s at %llu size %llu",
dev_name(dev),
(unsigned long long)area_start,
(unsigned long long)area_size);
return NULL;
}
mh = (struct mda_header *)area_buf;
_xlate_mdah(mh);
rlocn_slot0 = &mh->raw_locns[0];
text_offset = rlocn_slot0->offset;
text_size = rlocn_slot0->size;
/*
* Copy and return the current metadata text out of the metadata area.
*/
if (!(text_buf = malloc(text_size)))
return_NULL;
memcpy(text_buf, area_buf + text_offset, text_size);
if (len)
*len = (uint32_t)text_size;
if (disk_offset)
*disk_offset = area_start + text_offset;
free(area_buf);
return text_buf;
}
int dump_metadata_text(struct cmd_context *cmd,
const char *vgname,
const char *vgid,
struct device *dev,
struct metadata_area *mda,
const char *tofile)
{
char *textbuf;
struct format_instance *fid;
struct format_instance_ctx fic;
struct mda_context *mdac;
struct volume_group *vg;
unsigned use_previous_vg = 0;
uint32_t textlen = 0;
uint32_t textcrc;
uint64_t text_disk_offset;
int ret = 0;
/*
* Set up overhead/abstractions for reading a given vgname
* (fmt/fid/fic/vgid).
*/
fic.type = FMT_INSTANCE_MDAS | FMT_INSTANCE_AUX_MDAS;
fic.context.vg_ref.vg_name = vgname;
fic.context.vg_ref.vg_id = vgid;
if (!(fid = _text_create_text_instance(cmd->fmt, &fic))) {
log_error("Failed to create format instance");
return 0;
}
mdac = mda->metadata_locn;
/*
* Read the VG metadata from the device as a raw chunk of original text.
*/
textbuf = _read_metadata_text(cmd, dev,
mdac->area.start, mdac->area.size,
&textlen, &text_disk_offset);
if (!textbuf || !textlen) {
log_error("No metadata text found on %s", dev_name(dev));
_text_destroy_instance(fid);
return 0;
}
textcrc = calc_crc(INITIAL_CRC, (uint8_t *)textbuf, textlen);
/*
* Read the same VG metadata, but imported/parsed into a vg struct
* format so we know it's valid/parsable, and can look at values in it.
*/
if (!(vg = _vg_read_raw(fid, vgname, mda, NULL, &use_previous_vg))) {
log_warn("WARNING: parse error for metadata on %s.", dev_name(dev));
_text_destroy_instance(fid);
}
log_print("Metadata for %s from %s at %llu size %u with seqno %u checksum 0x%x.",
vgname, dev_name(dev),
(unsigned long long)text_disk_offset, textlen,
vg ? vg->seqno : 0, textcrc);
if (!tofile) {
log_print("---");
printf("%s\n", textbuf);
log_print("---");
} else {
FILE *fp;
if (!(fp = fopen(tofile, "wx"))) {
log_error("Failed to create file %s", tofile);
goto out;
}
fprintf(fp, "%s", textbuf);
if (fflush(fp))
stack;
if (fclose(fp))
stack;
}
if (vg)
release_vg(vg);
free(textbuf);
ret = 1;
out:
return ret;
}
static char *_read_metadata_area(struct cmd_context *cmd, struct device *dev,
uint64_t area_start, uint64_t area_size)
{
char *area_buf;
/*
* Read the entire metadata area, including mda_header and entire
* circular buffer.
*/
if (!(area_buf = malloc(area_size)))
return_NULL;
if (!dev_read_bytes(dev, area_start, area_size, area_buf)) {
log_error("Failed to read device %s at %llu size %llu",
dev_name(dev),
(unsigned long long)area_start,
(unsigned long long)area_size);
return NULL;
}
return area_buf;
}
int dump_metadata_area(struct cmd_context *cmd,
const char *vgname,
const char *vgid,
struct device *dev,
struct metadata_area *mda,
const char *tofile)
{
char *areabuf;
char *textbuf;
struct mda_context *mdac;
int ret = 0;
mdac = mda->metadata_locn;
areabuf = _read_metadata_area(cmd, dev,
mdac->area.start, mdac->area.size);
if (!areabuf) {
log_error("No metadata area found on %s", dev_name(dev));
return 0;
}
log_print("Metadata buffer for %s from %s in area at %llu size %llu offset 512.",
vgname, dev_name(dev),
(unsigned long long)mdac->area.start,
(unsigned long long)mdac->area.size);
/* text starts after mda_header which uses 512 bytes */
textbuf = areabuf + 512;
if (!tofile) {
/* N.B. this will often include unprintable data */
log_print("---");
fwrite(textbuf, mdac->area.size - 512, 1, stdout);
log_print("---");
} else {
FILE *fp;
if (!(fp = fopen(tofile, "wx"))) {
log_error("Failed to create file %s", tofile);
goto out;
}
fwrite(textbuf, mdac->area.size - 512, 1, fp);
if (fflush(fp))
stack;
if (fclose(fp))
stack;
}
ret = 1;
out:
free(areabuf);
return ret;
}
int text_wipe_outdated_pv_mda(struct cmd_context *cmd, struct device *dev,
struct metadata_area *mda)
{

View File

@@ -77,6 +77,20 @@ struct data_area_list {
struct disk_locn disk_locn;
};
int dump_metadata_text(struct cmd_context *cmd,
const char *vgname,
const char *vgid,
struct device *dev,
struct metadata_area *mda,
const char *tofile);
int dump_metadata_area(struct cmd_context *cmd,
const char *vgname,
const char *vgid,
struct device *dev,
struct metadata_area *mda,
const char *tofile);
int text_wipe_outdated_pv_mda(struct cmd_context *cmd, struct device *dev,
struct metadata_area *mda);

View File

@@ -1042,33 +1042,6 @@ int label_scan(struct cmd_context *cmd)
}
}
/*
* Stronger exclusion of md components that might have been
* misidentified as PVs due to having an end-of-device md superblock.
* If we're not using hints, and are not already doing a full md check
* on devs being scanned, then if udev info is missing for a PV, scan
* the end of the PV to verify it's not an md component. The full
* dev_is_md_component call will do new reads at the end of the dev.
*/
if (cmd->md_component_detection && !cmd->use_full_md_check && !using_hints &&
!strcmp(cmd->md_component_checks, "auto")) {
int once = 0;
dm_list_iterate_items(devl, &scan_devs) {
if (!(devl->dev->flags & DEV_SCAN_FOUND_LABEL))
continue;
if (!(devl->dev->flags & DEV_UDEV_INFO_MISSING))
continue;
if (!once++)
log_debug_devs("Scanning end of PVs with no udev info for MD components");
if (dev_is_md_component(devl->dev, NULL, 1)) {
log_debug_devs("Drop PV from MD component %s", dev_name(devl->dev));
devl->dev->flags &= ~DEV_SCAN_FOUND_LABEL;
lvmcache_del_dev(devl->dev);
}
}
}
dm_list_iterate_items_safe(devl, devl2, &all_devs) {
dm_list_del(&devl->list);
free(devl);
@@ -1245,6 +1218,66 @@ int label_read(struct device *dev)
return 1;
}
/*
* Read a label from a specfic, non-zero sector. This is used in only
* one place: pvck/pv_analyze.
*/
int label_read_sector(struct device *dev, uint64_t read_sector)
{
struct block *bb = NULL;
uint64_t block_num;
uint64_t block_sector;
uint64_t start_sector;
int is_lvm_device = 0;
int result;
int ret;
block_num = read_sector / BCACHE_BLOCK_SIZE_IN_SECTORS;
block_sector = block_num * BCACHE_BLOCK_SIZE_IN_SECTORS;
start_sector = read_sector % BCACHE_BLOCK_SIZE_IN_SECTORS;
if (!label_scan_open(dev)) {
log_error("Error opening device %s for prefetch %llu sector.",
dev_name(dev), (unsigned long long)block_num);
return false;
}
bcache_prefetch(scan_bcache, dev->bcache_fd, block_num);
if (!bcache_get(scan_bcache, dev->bcache_fd, block_num, 0, &bb)) {
log_error("Scan failed to read %s at %llu",
dev_name(dev), (unsigned long long)block_num);
ret = 0;
goto out;
}
/*
* TODO: check if scan_sector is larger than the bcache block size.
* If it is, we need to fetch a later block from bcache.
*/
result = _process_block(NULL, NULL, dev, bb, block_sector, start_sector, &is_lvm_device);
if (!result && is_lvm_device) {
log_error("Scan failed to process %s", dev_name(dev));
ret = 0;
goto out;
}
if (!result || !is_lvm_device) {
log_error("Could not find LVM label on %s", dev_name(dev));
ret = 0;
goto out;
}
ret = 1;
out:
if (bb)
bcache_put(bb);
return ret;
}
int label_scan_setup_bcache(void)
{
if (!scan_bcache) {

View File

@@ -156,20 +156,12 @@ int init_locking(struct cmd_context *cmd,
return 1;
}
void fin_locking(struct cmd_context *cmd)
void fin_locking(void)
{
/* file locking disabled */
if (!_locking.flags)
return;
/*
* These may be automatically released when the
* command ends, without an explicit unlock call,
* in which case these flags would not be cleared.
*/
cmd->lockf_global_ex = 0;
cmd->lockd_global_ex = 0;
_locking.fin_locking();
}
@@ -384,10 +376,6 @@ int lockf_global(struct cmd_context *cmd, const char *mode)
int lockf_global_convert(struct cmd_context *cmd, const char *mode)
{
/* some uncommon cases like pvchange -a can call this multiple times */
if (cmd->lockf_global_ex && !strcmp(mode, "ex"))
return 1;
return _lockf_global(cmd, mode, 1);
}

View File

@@ -22,7 +22,7 @@
struct logical_volume;
int init_locking(struct cmd_context *cmd, int file_locking_sysinit, int file_locking_readonly, int file_locking_ignorefail);
void fin_locking(struct cmd_context *cmd);
void fin_locking(void);
void reset_locking(void);
int vg_write_lock_held(void);

View File

@@ -245,11 +245,6 @@ char *lvseg_kernel_discards_dup_with_info_and_seg_status(struct dm_pool *mem, co
return 0;
}
s = get_pool_discards_name(d);
} else if (lvdm->seg_status.type == SEG_STATUS_CACHE) {
if (lvdm->seg_status.cache->feature_flags &
DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN) {
s = "nopassdown";
}
}
if (!(ret = dm_pool_strdup(mem, s))) {

View File

@@ -696,6 +696,9 @@ int unlink_lv_from_vg(struct logical_volume *lv);
void lv_set_visible(struct logical_volume *lv);
void lv_set_hidden(struct logical_volume *lv);
int get_vgnameids(struct cmd_context *cmd, struct dm_list *vgnameids,
const char *only_this_vgname, int include_internal);
int pv_write(struct cmd_context *cmd, struct physical_volume *pv, int allow_non_orphan);
int move_pv(struct volume_group *vg_from, struct volume_group *vg_to,
const char *pv_name);

View File

@@ -985,6 +985,29 @@ int vg_has_unknown_segments(const struct volume_group *vg)
return 0;
}
struct volume_group *vg_lock_and_create(struct cmd_context *cmd, const char *vg_name, int *exists)
{
uint32_t rc;
struct volume_group *vg;
if (!validate_name(vg_name)) {
log_error("Invalid vg name %s", vg_name);
return NULL;
}
rc = vg_lock_newname(cmd, vg_name);
if (rc == FAILED_EXIST)
*exists = 1;
if (rc != SUCCESS)
return NULL;
vg = vg_create(cmd, vg_name);
if (!vg)
unlock_vg(cmd, NULL, vg_name);
return vg;
}
/*
* Create a VG with default parameters.
*/
@@ -3242,7 +3265,7 @@ static int _vg_read_orphan_pv(struct lvmcache_info *info, void *baton)
/* Make orphan PVs look like a VG. */
struct volume_group *vg_read_orphans(struct cmd_context *cmd, const char *orphan_vgname)
{
const struct format_type *fmt = cmd->fmt;
const struct format_type *fmt;
struct lvmcache_vginfo *vginfo;
struct volume_group *vg = NULL;
struct _vg_read_orphan_baton baton;
@@ -3254,6 +3277,9 @@ struct volume_group *vg_read_orphans(struct cmd_context *cmd, const char *orphan
if (!(vginfo = lvmcache_vginfo_from_vgname(orphan_vgname, NULL)))
return_NULL;
if (!(fmt = lvmcache_fmt_from_vgname(cmd, orphan_vgname, NULL, 0)))
return_NULL;
vg = fmt->orphan_vg;
dm_list_iterate_items_safe(pvl, tpvl, &vg->pvs)
@@ -3566,6 +3592,28 @@ void set_pv_devices(struct format_instance *fid, struct volume_group *vg)
_set_pv_device(fid, vg, pvl->pv);
}
int get_vgnameids(struct cmd_context *cmd, struct dm_list *vgnameids,
const char *only_this_vgname, int include_internal)
{
struct vgnameid_list *vgnl;
if (only_this_vgname) {
if (!(vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl)))) {
log_error("vgnameid_list allocation failed.");
return 0;
}
vgnl->vg_name = dm_pool_strdup(cmd->mem, only_this_vgname);
vgnl->vgid = NULL;
dm_list_add(vgnameids, &vgnl->list);
return 1;
}
lvmcache_get_vgnameids(cmd, include_internal, vgnameids);
return 1;
}
int pv_write(struct cmd_context *cmd,
struct physical_volume *pv, int allow_non_orphan)
{
@@ -3635,6 +3683,41 @@ int is_real_vg(const char *vg_name)
return (vg_name && *vg_name != '#');
}
static int _analyze_mda(struct metadata_area *mda, void *baton)
{
const struct format_type *fmt = baton;
mda->ops->pv_analyze_mda(fmt, mda);
return 1;
}
/*
* Returns:
* 0 - fail
* 1 - success
*/
int pv_analyze(struct cmd_context *cmd, struct device *dev,
uint64_t label_sector)
{
struct label *label;
struct lvmcache_info *info;
if (!(label = lvmcache_get_dev_label(dev))) {
log_error("Could not find LVM label on %s", dev_name(dev));
return 0;
}
log_print("Found label on %s, sector %"PRIu64", type=%.8s",
dev_name(dev), label->sector, label->type);
/*
* Next, loop through metadata areas
*/
info = label->info;
lvmcache_foreach_mda(info, _analyze_mda, (void *)lvmcache_fmt(info));
return 1;
}
/* FIXME: remove / combine this with locking? */
int vg_check_write_mode(struct volume_group *vg)
{
@@ -3925,6 +4008,40 @@ uint32_t vg_read_error(struct volume_group *vg_handle)
return SUCCESS;
}
/*
* Lock a vgname and/or check for existence.
* Takes a WRITE lock on the vgname before scanning.
* If scanning fails or vgname found, release the lock.
* NOTE: If you find the return codes confusing, you might think of this
* function as similar to an open() call with O_CREAT and O_EXCL flags
* (open returns fail with -EEXIST if file already exists).
*
* Returns:
* FAILED_LOCKING - Cannot lock name
* FAILED_EXIST - VG name already exists - cannot reserve
* SUCCESS - VG name does not exist in system and WRITE lock held
*/
uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname)
{
if (!lock_vol(cmd, vgname, LCK_VG_WRITE, NULL))
return FAILED_LOCKING;
/* Find the vgname in the cache */
/* If it's not there we must do full scan to be completely sure */
if (!lvmcache_fmt_from_vgname(cmd, vgname, NULL, 1)) {
lvmcache_label_scan(cmd);
if (!lvmcache_fmt_from_vgname(cmd, vgname, NULL, 1)) {
lvmcache_label_scan(cmd);
if (!lvmcache_fmt_from_vgname(cmd, vgname, NULL, 0))
return SUCCESS; /* vgname not found after scanning */
}
}
/* Found vgname so cannot reserve. */
unlock_vg(cmd, NULL, vgname);
return FAILED_EXIST;
}
struct format_instance *alloc_fid(const struct format_type *fmt,
const struct format_instance_ctx *fic)
{

View File

@@ -31,6 +31,7 @@ static int _fwraid_filtering = 0;
static int _pvmove = 0;
static int _obtain_device_list_from_udev = DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV;
static enum dev_ext_e _external_device_info_source = DEV_EXT_NONE;
static int _trust_cache = 0; /* Don't scan when incomplete VGs encountered */
static int _debug_level = 0;
static int _debug_classes_logged = 0;
static int _security_level = SECURITY_LEVEL;
@@ -106,6 +107,11 @@ void init_external_device_info_source(enum dev_ext_e src)
_external_device_info_source = src;
}
void init_trust_cache(int trustcache)
{
_trust_cache = trustcache;
}
void init_security_level(int level)
{
_security_level = level;
@@ -279,6 +285,11 @@ enum dev_ext_e external_device_info_source(void)
return _external_device_info_source;
}
int trust_cache(void)
{
return _trust_cache;
}
int background_polling(void)
{
return _background_polling;

View File

@@ -32,6 +32,7 @@ void init_fwraid_filtering(int level);
void init_pvmove(int level);
void init_external_device_info_source(enum dev_ext_e src);
void init_obtain_device_list_from_udev(int device_list_from_udev);
void init_trust_cache(int trustcache);
void init_debug(int level);
void init_debug_classes_logged(int classes);
void init_cmd_name(int status);
@@ -64,6 +65,7 @@ int fwraid_filtering(void);
int pvmove_mode(void);
int obtain_device_list_from_udev(void);
enum dev_ext_e external_device_info_source(void);
int trust_cache(void);
int verbose_level(void);
int silent_mode(void);
int debug_level(void);

View File

@@ -1893,7 +1893,6 @@ int dm_tree_node_add_raid_target_with_params_v2(struct dm_tree_node *node,
#define DM_CACHE_FEATURE_WRITETHROUGH 0x00000002
#define DM_CACHE_FEATURE_PASSTHROUGH 0x00000004
#define DM_CACHE_FEATURE_METADATA2 0x00000008 /* cache v1.10 */
#define DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN 0x00000010
struct dm_config_node;
/*

View File

@@ -296,8 +296,6 @@ int dm_get_status_cache(struct dm_pool *mem, const char *params,
s->feature_flags |= DM_CACHE_FEATURE_PASSTHROUGH;
else if (!strncmp(p, "metadata2 ", 10))
s->feature_flags |= DM_CACHE_FEATURE_METADATA2;
else if (!strncmp(p, "no_discard_passdown ", 20))
s->feature_flags |= DM_CACHE_FEATURE_NO_DISCARD_PASSDOWN;
else
log_error("Unknown feature in status: %s", params);

View File

@@ -16,26 +16,74 @@ lvchange - Change the attributes of logical volume(s)
\fB--activationmode\fP \fBpartial\fP|\fBdegraded\fP|\fBcomplete\fP
.ad b
.br
.ad l
\fB--addtag\fP \fITag\fP
.ad b
.br
.ad l
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
.ad b
.br
.ad l
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB--cachemode\fP \fBwritethrough\fP|\fBwriteback\fP|\fBpassthrough\fP
.ad b
.br
.ad l
\fB--cachepolicy\fP \fIString\fP
.ad b
.br
.ad l
\fB--cachesettings\fP \fIString\fP
.ad b
.br
.ad l
\fB--commandprofile\fP \fIString\fP
.ad b
.br
.ad l
\fB--compression\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB--config\fP \fIString\fP
.ad b
.br
.ad l
\fB-C\fP|\fB--contiguous\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB-d\fP|\fB--debug\fP
.ad b
.br
.ad l
\fB--deduplication\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB--deltag\fP \fITag\fP
.ad b
.br
.ad l
\fB--detachprofile\fP
.ad b
.br
.ad l
\fB--discards\fP \fBpassdown\fP|\fBnopassdown\fP|\fBignore\fP
.ad b
.br
.ad l
\fB--driverloaded\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB--errorwhenfull\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB-f\fP|\fB--force\fP
.ad b
@@ -68,10 +116,22 @@ lvchange - Change the attributes of logical volume(s)
\fB-j\fP|\fB--major\fP \fINumber\fP
.ad b
.br
.ad l
\fB--[raid]maxrecoveryrate\fP \fISize\fP[k|UNIT]
.ad b
.br
.ad l
\fB--metadataprofile\fP \fIString\fP
.ad b
.br
.ad l
\fB--minor\fP \fINumber\fP
.ad b
.br
.ad l
\fB--[raid]minrecoveryrate\fP \fISize\fP[k|UNIT]
.ad b
.br
.ad l
\fB--monitor\fP \fBy\fP|\fBn\fP
.ad b
@@ -88,6 +148,10 @@ lvchange - Change the attributes of logical volume(s)
\fB-P\fP|\fB--partial\fP
.ad b
.br
.ad l
\fB-p\fP|\fB--permission\fP \fBrw\fP|\fBr\fP
.ad b
.br
.ad l
\fB-M\fP|\fB--persistent\fP \fBy\fP|\fBn\fP
.ad b
@@ -104,6 +168,10 @@ lvchange - Change the attributes of logical volume(s)
\fB-q\fP|\fB--quiet\fP
.ad b
.br
.ad l
\fB-r\fP|\fB--readahead\fP \fBauto\fP|\fBnone\fP|\fINumber\fP
.ad b
.br
.ad l
\fB--readonly\fP
.ad b
@@ -128,6 +196,10 @@ lvchange - Change the attributes of logical volume(s)
\fB-S\fP|\fB--select\fP \fIString\fP
.ad b
.br
.ad l
\fB-k\fP|\fB--setactivationskip\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB--[raid]syncaction\fP \fBcheck\fP|\fBrepair\fP
.ad b
@@ -148,9 +220,21 @@ lvchange - Change the attributes of logical volume(s)
\fB--version\fP
.ad b
.br
.ad l
\fB--[raid]writebehind\fP \fINumber\fP
.ad b
.br
.ad l
\fB--[raid]writemostly\fP \fIPV\fP[\fB:t\fP|\fBn\fP|\fBy\fP]
.ad b
.br
.ad l
\fB-y\fP|\fB--yes\fP
.ad b
.br
.ad l
\fB-Z\fP|\fB--zero\fP \fBy\fP|\fBn\fP
.ad b
.SH DESCRIPTION
lvchange changes LV attributes in the VG, changes LV activation in the
kernel, and includes other utilities for LV maintenance.
@@ -565,6 +649,34 @@ See \fBlvmraid\fP(7) for more information.
.ad b
.HP
.ad l
\fB--addtag\fP \fITag\fP
.br
Adds a tag to a PV, VG or LV. This option can be repeated to add
multiple tags at once. See \fBlvm\fP(8) for information about tags.
.ad b
.HP
.ad l
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
.br
Determines the allocation policy when a command needs to allocate
Physical Extents (PEs) from the VG. Each VG and LV has an allocation policy
which can be changed with vgchange/lvchange, or overriden on the
command line.
\fBnormal\fP applies common sense rules such as not placing parallel stripes
on the same PV.
\fBinherit\fP applies the VG policy to an LV.
\fBcontiguous\fP requires new PEs be placed adjacent to existing PEs.
\fBcling\fP places new PEs on the same PV as existing PEs in the same
stripe of the LV.
If there are sufficient PEs for an allocation, but normal does not
use them, \fBanywhere\fP will use them even if it reduces performance,
e.g. by placing two stripes on the same PV.
Optional positional PV args on the command line can also be used to limit
which PVs the command will use for allocation.
See \fBlvm\fP(8) for more information about allocation.
.ad b
.HP
.ad l
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
.br
Specifies if metadata should be backed up automatically after a change.
@@ -572,6 +684,41 @@ Enabling this is strongly advised! See \fBvgcfgbackup\fP(8) for more information
.ad b
.HP
.ad l
\fB--cachemode\fP \fBwritethrough\fP|\fBwriteback\fP|\fBpassthrough\fP
.br
Specifies when writes to a cache LV should be considered complete.
\fBwriteback\fP considers a write complete as soon as it is
stored in the cache pool.
\fBwritethough\fP considers a write complete only when it has
been stored in both the cache pool and on the origin LV.
While writethrough may be slower for writes, it is more
resilient if something should happen to a device associated with the
cache pool LV. With \fBpassthrough\fP, all reads are served
from the origin LV (all reads miss the cache) and all writes are
forwarded to the origin LV; additionally, write hits cause cache
block invalidates. See \fBlvmcache\fP(7) for more information.
.ad b
.HP
.ad l
\fB--cachepolicy\fP \fIString\fP
.br
Specifies the cache policy for a cache LV.
See \fBlvmcache\fP(7) for more information.
.ad b
.HP
.ad l
\fB--cachesettings\fP \fIString\fP
.br
Specifies tunable values for a cache LV in "Key = Value" form.
Repeat this option to specify multiple values.
(The default values should usually be adequate.)
The special string value \fBdefault\fP switches
settings back to their default kernel values and removes
them from the list of settings stored in LVM metadata.
See \fBlvmcache\fP(7) for more information.
.ad b
.HP
.ad l
\fB--commandprofile\fP \fIString\fP
.br
The command profile to use for command configuration.
@@ -579,6 +726,13 @@ See \fBlvm.conf\fP(5) for more information about profiles.
.ad b
.HP
.ad l
\fB--compression\fP \fBy\fP|\fBn\fP
.br
Controls whether compression is enabled or disable for VDO volume.
See \fBlvmvdo\fP(7) for more information about VDO usage.
.ad b
.HP
.ad l
\fB--config\fP \fIString\fP
.br
Config settings for the command. These override lvm.conf settings.
@@ -588,6 +742,16 @@ See \fBlvm.conf\fP(5) for more information about config.
.ad b
.HP
.ad l
\fB-C\fP|\fB--contiguous\fP \fBy\fP|\fBn\fP
.br
Sets or resets the contiguous allocation policy for LVs.
Default is no contiguous allocation based on a next free principle.
It is only possible to change a non-contiguous allocation policy
to contiguous if all of the allocated physical extents in the LV
are already contiguous.
.ad b
.HP
.ad l
\fB-d\fP|\fB--debug\fP ...
.br
Set debug level. Repeat from 1 to 6 times to increase the detail of
@@ -595,6 +759,40 @@ messages sent to the log file and/or syslog (if configured).
.ad b
.HP
.ad l
\fB--deduplication\fP \fBy\fP|\fBn\fP
.br
Controls whether deduplication is enabled or disable for VDO volume.
See \fBlvmvdo\fP(7) for more information about VDO usage.
.ad b
.HP
.ad l
\fB--deltag\fP \fITag\fP
.br
Deletes a tag from a PV, VG or LV. This option can be repeated to delete
multiple tags at once. See \fBlvm\fP(8) for information about tags.
.ad b
.HP
.ad l
\fB--detachprofile\fP
.br
Detaches a metadata profile from a VG or LV.
See \fBlvm.conf\fP(5) for more information about profiles.
.ad b
.HP
.ad l
\fB--discards\fP \fBpassdown\fP|\fBnopassdown\fP|\fBignore\fP
.br
Specifies how the device-mapper thin pool layer in the kernel should
handle discards.
\fBignore\fP causes the thin pool to ignore discards.
\fBnopassdown\fP causes the thin pool to process discards itself to
allow reuse of unneeded extents in the thin pool.
\fBpassdown\fP causes the thin pool to process discards itself
(like nopassdown) and pass the discards to the underlying device.
See \fBlvmthin\fP(7) for more information.
.ad b
.HP
.ad l
\fB--driverloaded\fP \fBy\fP|\fBn\fP
.br
If set to no, the command will not attempt to use device-mapper.
@@ -602,6 +800,19 @@ For testing and debugging.
.ad b
.HP
.ad l
\fB--errorwhenfull\fP \fBy\fP|\fBn\fP
.br
Specifies thin pool behavior when data space is exhausted.
When yes, device-mapper will immediately return an error
when a thin pool is full and an I/O request requires space.
When no, device-mapper will queue these I/O requests for a
period of time to allow the thin pool to be extended.
Errors are returned if no space is available after the timeout.
(Also see dm-thin-pool kernel module option no_space_timeout.)
See \fBlvmthin\fP(7) for more information.
.ad b
.HP
.ad l
\fB-f\fP|\fB--force\fP ...
.br
Override various checks, confirmations and protections.
@@ -655,12 +866,37 @@ Sets the major number of an LV block device.
.ad b
.HP
.ad l
\fB--[raid]maxrecoveryrate\fP \fISize\fP[k|UNIT]
.br
Sets the maximum recovery rate for a RAID LV. The rate value
is an amount of data per second for each device in the array.
Setting the rate to 0 means it will be unbounded.
See \fBlvmraid\fP(7) for more information.
.ad b
.HP
.ad l
\fB--metadataprofile\fP \fIString\fP
.br
The metadata profile to use for command configuration.
See \fBlvm.conf\fP(5) for more information about profiles.
.ad b
.HP
.ad l
\fB--minor\fP \fINumber\fP
.br
Sets the minor number of an LV block device.
.ad b
.HP
.ad l
\fB--[raid]minrecoveryrate\fP \fISize\fP[k|UNIT]
.br
Sets the minimum recovery rate for a RAID LV. The rate value
is an amount of data per second for each device in the array.
Setting the rate to 0 means it will be unbounded.
See \fBlvmraid\fP(7) for more information.
.ad b
.HP
.ad l
\fB--monitor\fP \fBy\fP|\fBn\fP
.br
Start (yes) or stop (no) monitoring an LV with dmeventd.
@@ -694,6 +930,12 @@ Metadata may not be changed with this option.
.ad b
.HP
.ad l
\fB-p\fP|\fB--permission\fP \fBrw\fP|\fBr\fP
.br
Set access permission to read only \fBr\fP or read and write \fBrw\fP.
.ad b
.HP
.ad l
\fB-M\fP|\fB--persistent\fP \fBy\fP|\fBn\fP
.br
When yes, makes the specified minor number persistent.
@@ -726,6 +968,15 @@ Repeat once to also suppress any prompts with answer 'no'.
.ad b
.HP
.ad l
\fB-r\fP|\fB--readahead\fP \fBauto\fP|\fBnone\fP|\fINumber\fP
.br
Sets read ahead sector count of an LV.
\fBauto\fP is the default which allows the kernel to choose
a suitable value automatically.
\fBnone\fP is equivalent to zero.
.ad b
.HP
.ad l
\fB--readonly\fP
.br
Run the command in a special read-only mode which will read on-disk
@@ -793,6 +1044,17 @@ used to choose items to process.
.ad b
.HP
.ad l
\fB-k\fP|\fB--setactivationskip\fP \fBy\fP|\fBn\fP
.br
Persistently sets (yes) or clears (no) the "activation skip" flag on an LV.
An LV with this flag set is not activated unless the
--ignoreactivationskip option is used by the activation command.
This flag is set by default on new thin snapshot LVs.
The flag is not applied to deactivation.
The current value of the flag is indicated in the lvs lv_attr bits.
.ad b
.HP
.ad l
\fB--[raid]syncaction\fP \fBcheck\fP|\fBrepair\fP
.br
Initiate different types of RAID synchronization.
@@ -840,12 +1102,43 @@ Display version information.
.ad b
.HP
.ad l
\fB--[raid]writebehind\fP \fINumber\fP
.br
The maximum number of outstanding writes that are allowed to
devices in a RAID1 LV that is marked write-mostly.
Once this value is exceeded, writes become synchronous (i.e. all writes
to the constituent devices must complete before the array signals the
write has completed). Setting the value to zero clears the preference
and allows the system to choose the value arbitrarily.
.ad b
.HP
.ad l
\fB--[raid]writemostly\fP \fIPV\fP[\fB:t\fP|\fBn\fP|\fBy\fP]
.br
Mark a device in a RAID1 LV as write-mostly. All reads
to these drives will be avoided unless absolutely necessary. This keeps
the number of I/Os to the drive to a minimum. The default behavior is to
set the write-mostly attribute for the specified PV.
It is also possible to remove the write-mostly flag by adding the
suffix \fB:n\fP at the end of the PV name, or to toggle the value with
the suffix \fB:t\fP. Repeat this option to change the attribute on
multiple PVs.
.ad b
.HP
.ad l
\fB-y\fP|\fB--yes\fP
.br
Do not prompt for confirmation interactively but always assume the
answer yes. Use with extreme caution.
(For automatic no, see -qq.)
.ad b
.HP
.ad l
\fB-Z\fP|\fB--zero\fP \fBy\fP|\fBn\fP
.br
Set zeroing mode for thin pool. Note: already provisioned blocks from pool
in non-zero mode are not cleared in unwritten parts when setting --zero y.
.ad b
.SH VARIABLES
.HP
\fIVG\fP

View File

@@ -42,10 +42,6 @@ lvconvert - Change logical volume layout
\fB--cachesettings\fP \fIString\fP
.ad b
.br
.ad l
\fB--cachevol\fP \fILV\fP
.ad b
.br
.ad l
\fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT]
.ad b
@@ -571,7 +567,7 @@ Convert LV to a thin LV, using the original LV as an external origin.
.br
-
Attach a cache pool to an LV, converts the LV to type cache.
Attach a cache to an LV, converts the LV to type cache.
.br
.P
\fBlvconvert\fP \fB--type\fP \fBcache\fP \fB--cachepool\fP \fILV\fP \fILV\fP\fI_linear_striped_thinpool_vdo_vdopool_vdopooldata_raid\fP
@@ -633,7 +629,7 @@ Attach a cache pool to an LV, converts the LV to type cache.
Attach a writecache to an LV, converts the LV to type writecache.
.br
.P
\fBlvconvert\fP \fB--type\fP \fBwritecache\fP \fB--cachevol\fP \fILV\fP \fILV\fP\fI_linear_striped_raid\fP
\fBlvconvert\fP \fB--type\fP \fBwritecache\fP \fB--cachepool\fP \fILV\fP \fILV\fP\fI_linear_striped_raid\fP
.br
.RS 4
.ad l
@@ -645,49 +641,6 @@ Attach a writecache to an LV, converts the LV to type writecache.
.br
-
Attach a cache to an LV, converts the LV to type cache.
.br
.P
\fBlvconvert\fP \fB--type\fP \fBcache\fP \fB--cachevol\fP \fILV\fP \fILV\fP\fI_linear_striped_thinpool_raid\fP
.br
.RS 4
.ad l
[ \fB-H\fP|\fB--cache\fP ]
.ad b
.br
.ad l
[ \fB-Z\fP|\fB--zero\fP \fBy\fP|\fBn\fP ]
.ad b
.br
.ad l
[ \fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT] ]
.ad b
.br
.ad l
[ \fB--cachemetadataformat\fP \fBauto\fP|\fB1\fP|\fB2\fP ]
.ad b
.br
.ad l
[ \fB--cachemode\fP \fBwritethrough\fP|\fBwriteback\fP|\fBpassthrough\fP ]
.ad b
.br
.ad l
[ \fB--cachepolicy\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--cachesettings\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--poolmetadatasize\fP \fISize\fP[m|UNIT] ]
.ad b
.br
[ COMMON_OPTIONS ]
.RE
.br
-
Convert LV to type thin-pool.
.br
.P
@@ -1094,7 +1047,7 @@ See \fBlvmcache\fP(7) for more information.
.ad l
\fB--cachepool\fP \fILV\fP
.br
The name of a cache pool.
The name of a cache pool LV.
.ad b
.HP
.ad l
@@ -1110,12 +1063,6 @@ See \fBlvmcache\fP(7) for more information.
.ad b
.HP
.ad l
\fB--cachevol\fP \fILV\fP
.br
The name of a cache volume.
.ad b
.HP
.ad l
\fB-c\fP|\fB--chunksize\fP \fISize\fP[k|UNIT]
.br
The size of chunks in a snapshot, cache pool or thin pool.
@@ -1742,7 +1689,7 @@ Convert LV to a thin LV, using the original LV as an external origin
.br
-
Attach a cache pool to an LV (infers --type cache).
Attach a cache to an LV (infers --type cache).
.br
.P
\fBlvconvert\fP \fB-H\fP|\fB--cache\fP \fB--cachepool\fP \fILV\fP \fILV\fP\fI_linear_striped_thinpool_vdo_vdopool_vdopooldata_raid\fP

View File

@@ -309,8 +309,7 @@ numeric suffix.
In the usage section below, when creating a pool and the name is omitted
the new LV pool name is generated with the
"vpool" for vdo-pools for prefix and a unique numeric suffix.
Pool name can be specified together with \fIVG\fP name i.e.:
Also pool name can be specified together with \fIVG\fP name i.e.:
vg00/mythinpool.
.SH USAGE
Create a linear LV.
@@ -1098,7 +1097,7 @@ See \fBlvmcache\fP(7) for more information.
.ad l
\fB--cachepool\fP \fILV\fP
.br
The name of a cache pool.
The name of a cache pool LV.
.ad b
.HP
.ad l

View File

@@ -92,6 +92,10 @@ if information changes between commands.
.ad b
.br
.ad l
[ \fB--trustcache\fP ]
.ad b
.br
.ad l
[ \fB--unbuffered\fP ]
.ad b
.br
@@ -402,6 +406,12 @@ back metadata it believes has changed but hasn't.
.ad b
.HP
.ad l
\fB--trustcache\fP
.br
Avoids certain device scanning during command processing. Do not use.
.ad b
.HP
.ad l
\fB--unbuffered\fP
.br
Produce output immediately without sorting or aligning the columns properly.

View File

@@ -96,6 +96,10 @@ lvs produces formatted output about LVs.
.ad b
.br
.ad l
[ \fB--trustcache\fP ]
.ad b
.br
.ad l
[ \fB--unbuffered\fP ]
.ad b
.br
@@ -423,6 +427,12 @@ back metadata it believes has changed but hasn't.
.ad b
.HP
.ad l
\fB--trustcache\fP
.br
Avoids certain device scanning during command processing. Do not use.
.ad b
.HP
.ad l
\fB--unbuffered\fP
.br
Produce output immediately without sorting or aligning the columns properly.

View File

@@ -16,7 +16,7 @@ others are optional.
Change properties of all PVs.
.br
.P
\fBpvchange\fP \fB-a\fP|\fB--all\fP
\fBpvchange\fP
.RS 4
( \fB-x\fP|\fB--allocatable\fP \fBy\fP|\fBn\fP,
.ad b
@@ -25,6 +25,10 @@ Change properties of all PVs.
\fB-u\fP|\fB--uuid\fP,
.ad b
.br
.ad l
\fB-a\fP|\fB--all\fP,
.ad b
.br
.ad l
\fB--addtag\fP \fITag\fP,
.ad b
@@ -160,12 +164,25 @@ Common options for lvm:
.SH OPTIONS
.HP
.ad l
\fB--addtag\fP \fITag\fP
.br
Adds a tag to a PV, VG or LV. This option can be repeated to add
multiple tags at once. See \fBlvm\fP(8) for information about tags.
.ad b
.HP
.ad l
\fB-a\fP|\fB--all\fP
.br
Change all visible PVs.
.ad b
.HP
.ad l
\fB-x\fP|\fB--allocatable\fP \fBy\fP|\fBn\fP
.br
Enable or disable allocation of physical extents on this PV.
.ad b
.HP
.ad l
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
.br
Specifies if metadata should be backed up automatically after a change.
@@ -196,6 +213,13 @@ messages sent to the log file and/or syslog (if configured).
.ad b
.HP
.ad l
\fB--deltag\fP \fITag\fP
.br
Deletes a tag from a PV, VG or LV. This option can be repeated to delete
multiple tags at once. See \fBlvm\fP(8) for information about tags.
.ad b
.HP
.ad l
\fB--driverloaded\fP \fBy\fP|\fBn\fP
.br
If set to no, the command will not attempt to use device-mapper.
@@ -229,6 +253,15 @@ Display long help text.
.ad b
.HP
.ad l
\fB--metadataignore\fP \fBy\fP|\fBn\fP
.br
Specifies the metadataignore property of a PV.
If yes, metadata areas on the PV are ignored, and lvm will
not store metadata in the metadata areas of the PV.
If no, lvm will store metadata on the PV.
.ad b
.HP
.ad l
\fB--nolocking\fP
.br
Disable locking.

View File

@@ -1,57 +1,25 @@
.TH PVCK 8 "LVM TOOLS #VERSION#" "Red Hat, Inc."
.SH NAME
pvck - Check metadata on physical volumes
pvck - Check the consistency of physical volume(s)
.
.SH SYNOPSIS
\fBpvck\fP \fIoption_args\fP \fIposition_args\fP
\fBpvck\fP \fIposition_args\fP
.br
[ \fIoption_args\fP ]
.br
.SH DESCRIPTION
pvck checks LVM metadata on PVs.
Use the --dump option to extract metadata from PVs for debugging.
With dump, set --pvmetadatacopies 2 to extract metadata from a
second metadata area at the end of the device. Use the --file
option to save the raw metadata to a specified file. (The raw
metadata is not usable with vgcfgbackup and vgcfgrestore.)
pvck checks the LVM metadata for consistency on PVs.
.SH USAGE
Check for metadata on a device
.br
.P
\fBpvck\fP \fIPV\fP ...
.br
.RS 4
[ COMMON_OPTIONS ]
.RE
.br
Print metadata from a device
.br
.P
\fBpvck\fP \fB--dump\fP \fIString\fP \fIPV\fP
.br
.RS 4
.ad l
[ \fB-f\fP|\fB--file\fP \fIString\fP ]
.ad b
.br
.ad l
[ \fB--[pv]metadatacopies\fP \fB0\fP|\fB1\fP|\fB2\fP ]
.ad b
.br
[ COMMON_OPTIONS ]
.RE
.br
Common options for command:
.
.RS 4
.ad l
[ \fB--labelsector\fP \fINumber\fP ]
.ad b
.br
[ COMMON_OPTIONS ]
.RE
.br
Common options for lvm:
.
@@ -145,21 +113,6 @@ For testing and debugging.
.ad b
.HP
.ad l
\fB--dump\fP \fIString\fP
.br
Dump metadata from a PV. Option values include \fBmetadata\fP
to print or save the current text metadata, \fBmetadata_area\fP
to save the entire text metadata area to a file, \fBmetadata_all\fP
to save the current and any previous complete versions of metadata
to a file, and \fBheaders\fP to print and check LVM headers.
.ad b
.HP
.ad l
\fB-f\fP|\fB--file\fP \fIString\fP
.br
.ad b
.HP
.ad l
\fB-h\fP|\fB--help\fP
.br
Display help text.
@@ -201,18 +154,6 @@ on the command.
.ad b
.HP
.ad l
\fB--[pv]metadatacopies\fP \fB0\fP|\fB1\fP|\fB2\fP
.br
The number of metadata areas to set aside on a PV for storing VG metadata.
When 2, one copy of the VG metadata is stored at the front of the PV
and a second copy is stored at the end.
When 1, one copy of the VG metadata is stored at the front of the PV.
When 0, no copies of the VG metadata are stored on the given PV.
This may be useful in VGs containing many PVs (this places limitations
on the ability to use vgsplit later.)
.ad b
.HP
.ad l
\fB-q\fP|\fB--quiet\fP ...
.br
Suppress output and log messages. Overrides --debug and --verbose.

View File

@@ -92,6 +92,10 @@ pvs produces formatted output about PVs.
.ad b
.br
.ad l
[ \fB--trustcache\fP ]
.ad b
.br
.ad l
[ \fB--unbuffered\fP ]
.ad b
.br
@@ -412,6 +416,12 @@ back metadata it believes has changed but hasn't.
.ad b
.HP
.ad l
\fB--trustcache\fP
.br
Avoids certain device scanning during command processing. Do not use.
.ad b
.HP
.ad l
\fB--unbuffered\fP
.br
Produce output immediately without sorting or aligning the columns properly.

View File

@@ -18,6 +18,14 @@ vgchange - Change volume group attributes
\fB--activationmode\fP \fBpartial\fP|\fBdegraded\fP|\fBcomplete\fP
.ad b
.br
.ad l
\fB--addtag\fP \fITag\fP
.ad b
.br
.ad l
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
.ad b
.br
.ad l
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
.ad b
@@ -34,6 +42,14 @@ vgchange - Change volume group attributes
\fB-d\fP|\fB--debug\fP
.ad b
.br
.ad l
\fB--deltag\fP \fITag\fP
.ad b
.br
.ad l
\fB--detachprofile\fP
.ad b
.br
.ad l
\fB--driverloaded\fP \fBy\fP|\fBn\fP
.ad b
@@ -74,10 +90,22 @@ vgchange - Change volume group attributes
\fB--locktype\fP \fBsanlock\fP|\fBdlm\fP|\fBnone\fP
.ad b
.br
.ad l
\fB-l\fP|\fB--logicalvolume\fP \fINumber\fP
.ad b
.br
.ad l
\fB--longhelp\fP
.ad b
.br
.ad l
\fB-p\fP|\fB--maxphysicalvolumes\fP \fINumber\fP
.ad b
.br
.ad l
\fB--metadataprofile\fP \fIString\fP
.ad b
.br
.ad l
\fB--monitor\fP \fBy\fP|\fBn\fP
.ad b
@@ -94,6 +122,10 @@ vgchange - Change volume group attributes
\fB-P\fP|\fB--partial\fP
.ad b
.br
.ad l
\fB-s\fP|\fB--physicalextentsize\fP \fISize\fP[m|UNIT]
.ad b
.br
.ad l
\fB--poll\fP \fBy\fP|\fBn\fP
.ad b
@@ -102,6 +134,10 @@ vgchange - Change volume group attributes
\fB--profile\fP \fIString\fP
.ad b
.br
.ad l
\fB--pvmetadatacopies\fP \fB0\fP|\fB1\fP|\fB2\fP
.ad b
.br
.ad l
\fB-q\fP|\fB--quiet\fP
.ad b
@@ -118,6 +154,10 @@ vgchange - Change volume group attributes
\fB--reportformat\fP \fBbasic\fP|\fBjson\fP
.ad b
.br
.ad l
\fB-x\fP|\fB--resizeable\fP \fBy\fP|\fBn\fP
.ad b
.br
.ad l
\fB-S\fP|\fB--select\fP \fIString\fP
.ad b
@@ -134,6 +174,10 @@ vgchange - Change volume group attributes
\fB-t\fP|\fB--test\fP
.ad b
.br
.ad l
\fB-u\fP|\fB--uuid\fP
.ad b
.br
.ad l
\fB-v\fP|\fB--verbose\fP
.ad b
@@ -142,6 +186,10 @@ vgchange - Change volume group attributes
\fB--version\fP
.ad b
.br
.ad l
\fB--[vg]metadatacopies\fP \fBall\fP|\fBunmanaged\fP|\fINumber\fP
.ad b
.br
.ad l
\fB-y\fP|\fB--yes\fP
.ad b
@@ -622,6 +670,34 @@ See \fBlvmraid\fP(7) for more information.
.ad b
.HP
.ad l
\fB--addtag\fP \fITag\fP
.br
Adds a tag to a PV, VG or LV. This option can be repeated to add
multiple tags at once. See \fBlvm\fP(8) for information about tags.
.ad b
.HP
.ad l
\fB--alloc\fP \fBcontiguous\fP|\fBcling\fP|\fBcling_by_tags\fP|\fBnormal\fP|\fBanywhere\fP|\fBinherit\fP
.br
Determines the allocation policy when a command needs to allocate
Physical Extents (PEs) from the VG. Each VG and LV has an allocation policy
which can be changed with vgchange/lvchange, or overriden on the
command line.
\fBnormal\fP applies common sense rules such as not placing parallel stripes
on the same PV.
\fBinherit\fP applies the VG policy to an LV.
\fBcontiguous\fP requires new PEs be placed adjacent to existing PEs.
\fBcling\fP places new PEs on the same PV as existing PEs in the same
stripe of the LV.
If there are sufficient PEs for an allocation, but normal does not
use them, \fBanywhere\fP will use them even if it reduces performance,
e.g. by placing two stripes on the same PV.
Optional positional PV args on the command line can also be used to limit
which PVs the command will use for allocation.
See \fBlvm\fP(8) for more information about allocation.
.ad b
.HP
.ad l
\fB-A\fP|\fB--autobackup\fP \fBy\fP|\fBn\fP
.br
Specifies if metadata should be backed up automatically after a change.
@@ -652,6 +728,20 @@ messages sent to the log file and/or syslog (if configured).
.ad b
.HP
.ad l
\fB--deltag\fP \fITag\fP
.br
Deletes a tag from a PV, VG or LV. This option can be repeated to delete
multiple tags at once. See \fBlvm\fP(8) for information about tags.
.ad b
.HP
.ad l
\fB--detachprofile\fP
.br
Detaches a metadata profile from a VG or LV.
See \fBlvm.conf\fP(5) for more information about profiles.
.ad b
.HP
.ad l
\fB--driverloaded\fP \fBy\fP|\fBn\fP
.br
If set to no, the command will not attempt to use device-mapper.
@@ -723,12 +813,34 @@ See \fBlvmlockd\fP(8) for more information.
.ad b
.HP
.ad l
\fB-l\fP|\fB--logicalvolume\fP \fINumber\fP
.br
Sets the maximum number of LVs allowed in a VG.
.ad b
.HP
.ad l
\fB--longhelp\fP
.br
Display long help text.
.ad b
.HP
.ad l
\fB-p\fP|\fB--maxphysicalvolumes\fP \fINumber\fP
.br
Sets the maximum number of PVs that can belong to the VG.
The value 0 removes any limitation.
For large numbers of PVs, also see options --pvmetadatacopies,
and --vgmetadatacopies for improving performance.
.ad b
.HP
.ad l
\fB--metadataprofile\fP \fIString\fP
.br
The metadata profile to use for command configuration.
See \fBlvm.conf\fP(5) for more information about profiles.
.ad b
.HP
.ad l
\fB--monitor\fP \fBy\fP|\fBn\fP
.br
Start (yes) or stop (no) monitoring an LV with dmeventd.
@@ -762,6 +874,20 @@ Metadata may not be changed with this option.
.ad b
.HP
.ad l
\fB-s\fP|\fB--physicalextentsize\fP \fISize\fP[m|UNIT]
.br
Sets the physical extent size of PVs in the VG.
The value must be either a power of 2 of at least 1 sector
(where the sector size is the largest sector size of the PVs
currently used in the VG), or at least 128KiB.
Once this value has been set, it is difficult to change
without recreating the VG, unless no extents need moving.
Before increasing the physical extent size, you might need to use lvresize,
pvresize and/or pvmove so that everything fits. For example, every
contiguous range of extents used in a LV must start and end on an extent boundary.
.ad b
.HP
.ad l
\fB--poll\fP \fBy\fP|\fBn\fP
.br
When yes, start the background transformation of an LV.
@@ -781,6 +907,18 @@ on the command.
.ad b
.HP
.ad l
\fB--pvmetadatacopies\fP \fB0\fP|\fB1\fP|\fB2\fP
.br
The number of metadata areas to set aside on a PV for storing VG metadata.
When 2, one copy of the VG metadata is stored at the front of the PV
and a second copy is stored at the end.
When 1, one copy of the VG metadata is stored at the front of the PV.
When 0, no copies of the VG metadata are stored on the given PV.
This may be useful in VGs containing many PVs (this places limitations
on the ability to use vgsplit later.)
.ad b
.HP
.ad l
\fB-q\fP|\fB--quiet\fP ...
.br
Suppress output and log messages. Overrides --debug and --verbose.
@@ -819,6 +957,13 @@ output in JSON format. See \fBlvmreport\fP(7) for more information.
.ad b
.HP
.ad l
\fB-x\fP|\fB--resizeable\fP \fBy\fP|\fBn\fP
.br
Enables or disables the addition or removal of PVs to/from a VG
(by vgextend/vgreduce).
.ad b
.HP
.ad l
\fB-S\fP|\fB--select\fP \fIString\fP
.br
Select objects for processing and reporting based on specified criteria.
@@ -863,6 +1008,12 @@ back metadata it believes has changed but hasn't.
.ad b
.HP
.ad l
\fB-u\fP|\fB--uuid\fP
.br
Generate new random UUID for specified VGs.
.ad b
.HP
.ad l
\fB-v\fP|\fB--verbose\fP ...
.br
Set verbose level. Repeat from 1 to 4 times to increase the detail
@@ -876,6 +1027,24 @@ Display version information.
.ad b
.HP
.ad l
\fB--[vg]metadatacopies\fP \fBall\fP|\fBunmanaged\fP|\fINumber\fP
.br
Number of copies of the VG metadata that are kept.
VG metadata is kept in VG metadata areas on PVs in the VG,
i.e. reserved space at the start and/or end of the PVs.
Keeping a copy of the VG metadata on every PV can reduce performance
in VGs containing a large number of PVs.
When this number is set to a non-zero value, LVM will automatically
choose PVs on which to store metadata, using the metadataignore flags
on PVs to achieve the specified number.
The number can also be replaced with special string values:
\fBunmanaged\fP causes LVM to not automatically manage the PV
metadataignore flags.
\fBall\fP causes LVM to first clear the metadataignore flags on
all PVs, and then to become unmanaged.
.ad b
.HP
.ad l
\fB-y\fP|\fB--yes\fP
.br
Do not prompt for confirmation interactively but always assume the

View File

@@ -3,7 +3,7 @@
vgck - Check the consistency of volume group(s)
.
.SH SYNOPSIS
\fBvgck\fP \fIoption_args\fP \fIposition_args\fP
\fBvgck\fP
.br
[ \fIoption_args\fP ]
.br
@@ -12,9 +12,6 @@ vgck - Check the consistency of volume group(s)
.SH DESCRIPTION
vgck checks LVM metadata for consistency.
.SH USAGE
Read and display information about a VG.
.br
.P
\fBvgck\fP
.br
.RS 4
@@ -29,21 +26,6 @@ Read and display information about a VG.
[ \fIVG\fP|\fITag\fP ... ]
.RE
Rewrite VG metadata to correct problems.
.br
.P
\fBvgck\fP \fB--updatemetadata\fP \fIVG\fP
.br
.RS 4
[ COMMON_OPTIONS ]
.RE
.br
Common options for command:
.
.RS 4
.RE
Common options for lvm:
.
.RS 4
@@ -196,12 +178,6 @@ back metadata it believes has changed but hasn't.
.ad b
.HP
.ad l
\fB--updatemetadata\fP
.br
Update VG metadata to correct problems.
.ad b
.HP
.ad l
\fB-v\fP|\fB--verbose\fP ...
.br
Set verbose level. Repeat from 1 to 4 times to increase the detail

View File

@@ -88,6 +88,10 @@ vgs produces formatted output about VGs.
.ad b
.br
.ad l
[ \fB--trustcache\fP ]
.ad b
.br
.ad l
[ \fB--unbuffered\fP ]
.ad b
.br
@@ -399,6 +403,12 @@ back metadata it believes has changed but hasn't.
.ad b
.HP
.ad l
\fB--trustcache\fP
.br
Avoids certain device scanning during command processing. Do not use.
.ad b
.HP
.ad l
\fB--unbuffered\fP
.br
Produce output immediately without sorting or aligning the columns properly.

View File

@@ -49,9 +49,9 @@ include $(top_builddir)/make.tmpl
T ?= .
S ?= @ # never match anything by default
VERBOSE ?= 0
ALL := $(shell find -L $(srcdir) \( -path \*/shell/\*.sh -or -path \*/api/\*.sh -or -path \*/unit/\*.sh \) | $(SORT))
ALL := $(shell find -L $(srcdir) \( -path \*/shell/\*.sh -or -path \*/unit/\*.sh \) | $(SORT))
comma = ,
RUN := $(shell find -L $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/api/\*.sh -or -path \*/unit/\*.sh \) -and -regex "$(srcdir)/.*($(subst $(comma),|,$(T))).*" -and -not -regex "$(srcdir)/.*($(subst $(comma),|,$(S))).*" | $(SORT))
RUN := $(shell find -L $(srcdir) -regextype posix-egrep \( -path \*/shell/\*.sh -or -path \*/unit/\*.sh \) -and -regex "$(srcdir)/.*($(subst $(comma),|,$(T))).*" -and -not -regex "$(srcdir)/.*($(subst $(comma),|,$(S))).*" | $(SORT))
RUN_BASE = $(subst $(srcdir)/,,$(RUN))
ifeq ("@BUILD_LVMPOLLD@", "yes")
@@ -200,9 +200,8 @@ LIB_SHARED = check aux inittest utils get lvm-wrapper
install: .tests-stamp lib/paths-installed
@echo $(srcdir)
$(Q) $(INSTALL_DIR) $(DATADIR)/{shell,api,unit,lib,dbus} $(EXECDIR)
$(Q) $(INSTALL_DIR) $(DATADIR)/{shell,unit,lib,dbus} $(EXECDIR)
$(Q) $(INSTALL_DATA) shell/*.sh $(DATADIR)/shell
$(INSTALL_DATA) api/*.sh $(DATADIR)/api
$(Q) $(INSTALL_DATA) unit/*.sh $(DATADIR)/unit
-$(Q) $(INSTALL_PROGRAM) unit/unit-test $(DATADIR)/unit
-$(Q) $(INSTALL_PROGRAM) dbus/*.py $(DATADIR)/dbus/
@@ -292,7 +291,7 @@ lib/paths-installed: lib/paths-common
$(Q) $(RM) $@-t
$(Q) cat lib/paths-common > $@-t
$(Q) echo 'installed_testsuite=1' >> $@-t
$(Q) echo 'export PATH=@libexecdir@/lvm2-testsuite:@datadir@/lvm2-testsuite/lib:@datadir@/lvm2-testsuite/api:$$PATH' >> $@-t
$(Q) echo 'export PATH=@libexecdir@/lvm2-testsuite:@datadir@/lvm2-testsuite/lib:$$PATH' >> $@-t
$(Q) mv $@-t $@
lib/paths: lib/paths-common

View File

@@ -1090,7 +1090,7 @@ extend_filter() {
for rx in "$@"; do
filter=$(echo "$filter" | sed -e "s:\\[:[ \"$rx\", :")
done
lvmconf "$filter" "devices/scan_lvs = 1"
lvmconf "$filter"
}
extend_filter_LVMTEST() {
@@ -1421,7 +1421,7 @@ target_at_least() {
fi
local version
version=$(dmsetup targets 2>/dev/null | grep "^${1##dm-} " 2>/dev/null)
version=$(dmsetup targets 2>/dev/null | grep "${1##dm-} " 2>/dev/null)
version=${version##* v}
version_at_least "$version" "${@:2}" || {
@@ -1478,14 +1478,6 @@ have_vdo() {
target_at_least dm-vdo "$@"
}
have_writecache() {
lvm segtypes 2>/dev/null | grep -q writecache$ || {
echo "writecache is not built-in." >&2
return 1
}
target_at_least dm-writecache "$@"
}
have_raid() {
target_at_least dm-raid "$@"

View File

@@ -1,45 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2019 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU 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
# Check reporting of no_discard_passdown
SKIP_WITH_LVMPOLLD=1
# Until new version of cache_check tools - no integrity validation
LVM_TEST_CACHE_CHECK_CMD=""
. lib/inittest
aux kernel_at_least 5 1 || skip
aux have_cache 2 0
aux prepare_vg 1
# Create thinLV without discard
lvcreate --discards=ignore -T -V20 -L20 -n $lv $vg/pool
aux extend_filter_LVMTEST
# Use discard-less LV as PV for $vg1
pvcreate "$DM_DEV_DIR/$vg/$lv"
vgcreate -s 128K $vg1 "$DM_DEV_DIR/$vg/$lv"
# Create simple cache LV
lvcreate -L2 -n $lv1 $vg1
lvcreate -H -L2 $vg1/$lv1
#lvs -ao+kernel_discards $vg1
check lv_field $vg1/$lv1 kernel_discards "nopassdown"
vgremove -f $vg1
vgremove -f $vg

View File

@@ -31,10 +31,6 @@ test -f /proc/mdstat && grep -q raid1 /proc/mdstat || \
aux lvmconf 'devices/md_component_detection = 1'
# This stops lvm from taking advantage of hints which
# will have already excluded md components.
aux lvmconf 'devices/hints = "none"'
# This stops lvm from asking udev if a dev is an md component.
# LVM will ask udev if a dev is an md component, but we don't
# want to rely on that ability in this test.
@@ -65,10 +61,6 @@ check lv_field $vg/$lv1 lv_active "active"
pvs "$mddev"
not pvs "$dev1"
not pvs "$dev2"
pvs > out
not grep "$dev1" out
not grep "$dev2" out
sleep 1
vgchange -an $vg
@@ -80,14 +72,12 @@ sleep 1
mdadm --stop "$mddev"
aux udev_wait
# The md components should still be detected and excluded.
not pvs "$dev1"
not pvs "$dev2"
pvs > out
not grep "$dev1" out
not grep "$dev2" out
pvs -vvvv
# with md superblock 1.0 this pvs will report duplicates
# for the two md legs since the md device itself is not
# started
pvs 2>&1 |tee out
cat out
grep "prefers device" out
# should not activate from the md legs
not vgchange -ay $vg
@@ -114,20 +104,16 @@ not grep "active" out
mdadm --assemble "$mddev" "$dev1" "$dev2"
aux udev_wait
# Now that the md dev is online, pvs can see it
# and check for components even if
# md_component_checks is "start" (which disables
# most default end-of-device scans)
aux lvmconf 'devices/md_component_checks = "start"'
# Now that the md dev is online, pvs can see it and
# ignore the two legs, so there's no duplicate warning
not pvs "$dev1"
not pvs "$dev2"
pvs > out
not grep "$dev1" out
not grep "$dev2" out
pvs 2>&1 |tee out
cat out
not grep "prefers device" out
vgchange -ay $vg
vgchange -ay $vg 2>&1 |tee out
cat out
not grep "prefers device" out
check lv_field $vg/$lv1 lv_active "active"
@@ -138,9 +124,6 @@ vgremove -f $vg
aux cleanup_md_dev
# Put this setting back to the default
aux lvmconf 'devices/md_component_checks = "auto"'
# create 2 disk MD raid0 array
# by default using metadata format 1.0 with data at the end of device
# When a raid0 md array is stopped, the components will not look like
@@ -166,10 +149,6 @@ check lv_field $vg/$lv1 lv_active "active"
pvs "$mddev"
not pvs "$dev1"
not pvs "$dev2"
pvs > out
not grep "$dev1" out
not grep "$dev2" out
sleep 1
vgchange -an $vg
@@ -181,14 +160,7 @@ sleep 1
mdadm --stop "$mddev"
aux udev_wait
# The md components should still be detected and excluded.
not pvs "$dev1"
not pvs "$dev2"
pvs > out
not grep "$dev1" out
not grep "$dev2" out
pvs -vvvv
pvs 2>&1 |tee pvs.out
# should not activate from the md legs
not vgchange -ay $vg
@@ -215,19 +187,16 @@ not grep "active" out
mdadm --assemble "$mddev" "$dev1" "$dev2"
aux udev_wait
# Now that the md dev is online, pvs can see it
# and check for components even if
# md_component_checks is "start" (which disables
# most default end-of-device scans)
aux lvmconf 'devices/md_component_checks = "start"'
# Now that the md dev is online, pvs can see it and
# ignore the two legs, so there's no duplicate warning
not pvs "$dev1"
not pvs "$dev2"
pvs > out
not grep "$dev1" out
not grep "$dev2" out
pvs 2>&1 |tee out
cat out
not grep "prefers device" out
vgchange -ay $vg 2>&1 |tee out
cat out
not grep "prefers device" out
check lv_field $vg/$lv1 lv_active "active"

View File

@@ -1,80 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU 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
. lib/inittest
aux prepare_devs 3
get_devs
#
# Test corrupted mda_header.version field, which also
# causes the mda_header checksum to be bad.
#
# FIXME: if a VG has only a single PV, this repair
# doesn't work since there's no good PV to get
# metadata from. A more advanced repair capability
# is needed.
#
dd if=/dev/zero of="$dev1" || true
dd if=/dev/zero of="$dev2" || true
dd if=/dev/zero of="$dev3" || true
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
pvs
if [ -e "/usr/bin/xxd" ]; then
# read mda_header which is 4k from start of disk
dd if="$dev1" of=meta1 bs=4k count=1 skip=1
# convert binary to text
xxd meta1 > meta1.txt
# Corrupt mda_header by changing the version field from 0100 to 0200
sed 's/0000010:\ 304e\ 2a3e\ 0100\ 0000\ 0010\ 0000\ 0000\ 0000/0000010:\ 304e\ 2a3e\ 0200\ 0000\ 0010\ 0000\ 0000\ 0000/' meta1.txt > meta1-bad.txt
# convert text to binary
xxd -r meta1-bad.txt > meta1-bad
# write bad mda_header back to disk
dd if=meta1-bad of="$dev1" bs=4k seek=1
# pvs reports bad metadata header
pvs 2>&1 | tee out
grep "bad metadata header" out
fi
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
# bad metadata in one mda doesn't prevent using
# the VG since other mdas are fine and usable
lvcreate -l1 $vg
vgck --updatemetadata $vg
pvs 2>&1 | tee out
not grep "bad metadata header" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
vgchange -an $vg
vgremove -ff $vg

View File

@@ -1,236 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU 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
. lib/inittest
aux prepare_devs 3
get_devs
dd if=/dev/zero of="$dev1" || true
dd if=/dev/zero of="$dev2" || true
dd if=/dev/zero of="$dev3" || true
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
pvs
dd if="$dev1" of=meta1 bs=4k count=2
sed 's/flags =/flagx =/' meta1 > meta1.bad
dd if=meta1.bad of="$dev1"
pvs 2>&1 | tee out
grep "bad metadata text" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
# bad metadata in one mda doesn't prevent using
# the VG since other mdas are fine and usable
lvcreate -l1 $vg
vgck --updatemetadata $vg
pvs 2>&1 | tee out
not grep "bad metadata text" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
vgchange -an $vg
vgremove -ff $vg
#
# Same test as above, but corrupt metadata text
# on two of the three PVs, leaving one good
# copy of the metadata.
#
dd if=/dev/zero of="$dev1" || true
dd if=/dev/zero of="$dev2" || true
dd if=/dev/zero of="$dev3" || true
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
pvs
dd if="$dev1" of=meta1 bs=4k count=2
dd if="$dev2" of=meta2 bs=4k count=2
sed 's/READ/RRRR/' meta1 > meta1.bad
sed 's/seqno =/sss =/' meta2 > meta2.bad
dd if=meta1.bad of="$dev1"
dd if=meta2.bad of="$dev2"
pvs 2>&1 | tee out
grep "bad metadata text" out > out2
grep "$dev1" out2
grep "$dev2" out2
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
# bad metadata in one mda doesn't prevent using
# the VG since other mdas are fine
lvcreate -l1 $vg
vgck --updatemetadata $vg
pvs 2>&1 | tee out
not grep "bad metadata text" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
vgchange -an $vg
vgremove -ff $vg
#
# Three PVs where two have one mda, and the third
# has two mdas. The first mda is corrupted on all
# thee PVs, but the second mda on the third PV
# makes the VG usable.
#
dd if=/dev/zero of="$dev1" || true
dd if=/dev/zero of="$dev2" || true
dd if=/dev/zero of="$dev3" || true
pvcreate "$dev1"
pvcreate "$dev2"
pvcreate --pvmetadatacopies 2 "$dev3"
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
pvs
dd if="$dev1" of=meta1 bs=4k count=2
dd if="$dev2" of=meta2 bs=4k count=2
dd if="$dev3" of=meta3 bs=4k count=2
sed 's/READ/RRRR/' meta1 > meta1.bad
sed 's/seqno =/sss =/' meta2 > meta2.bad
sed 's/id =/id/' meta3 > meta3.bad
dd if=meta1.bad of="$dev1"
dd if=meta2.bad of="$dev2"
dd if=meta3.bad of="$dev3"
pvs 2>&1 | tee out
grep "bad metadata text" out > out2
grep "$dev1" out2
grep "$dev2" out2
grep "$dev3" out2
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
# bad metadata in some mdas doesn't prevent using
# the VG if there's a good mda found
lvcreate -l1 $vg
vgck --updatemetadata $vg
pvs 2>&1 | tee out
not grep "bad metadata text" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
vgchange -an $vg
vgremove -ff $vg
#
# Test that vgck --updatemetadata will update old metadata
# and repair bad metadata text at the same time from different
# devices.
#
dd if=/dev/zero of="$dev1" || true
dd if=/dev/zero of="$dev2" || true
dd if=/dev/zero of="$dev3" || true
pvcreate "$dev1"
pvcreate "$dev2"
pvcreate --pvmetadatacopies 2 "$dev3"
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
# Put bad metadata onto dev1
dd if="$dev1" of=meta1 bs=4k count=2
sed 's/READ/RRRR/' meta1 > meta1.bad
dd if=meta1.bad of="$dev1"
pvs 2>&1 | tee out
grep "bad metadata text" out > out2
grep "$dev1" out2
# We can still use the VG with other available
# mdas, skipping the bad mda.
lvcreate -n $lv1 -l1 -an $vg "$dev1"
lvcreate -n $lv2 -l1 -an $vg "$dev1"
# Put old metadata onto dev2 by updating
# the VG while dev2 is disabled.
aux disable_dev "$dev2"
pvs
pvs "$dev1"
not pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
lvs $vg/$lv2
lvremove $vg/$lv2
aux enable_dev "$dev2"
# Both old and bad metadata are reported.
pvs 2>&1 | tee out
grep "ignoring metadata seqno" out
grep "bad metadata text" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
not lvs $vg/$lv2
# fixes the bad metadata on dev1, and
# fixes the old metadata on dev2.
vgck --updatemetadata $vg
pvs 2>&1 | tee out
not grep "ignoring metadata seqno" out
not grep "bad metadata text" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
vgchange -an $vg
vgremove -ff $vg

View File

@@ -1,177 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU 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
. lib/inittest
aux prepare_devs 3
get_devs
#
# Test "old metadata" repair which occurs when the VG is written
# and one of the PVs in the VG does not get written to, and then
# the PV reappears with the old metadata. This can happen if
# a command is killed or crashes after writing new metadata to
# only some of the PVs in the VG, or if a PV is temporarily
# inaccessible while a VG is written.
#
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
#
# Test that vgck --updatemetadata will update old metadata.
#
lvcreate -n $lv1 -l1 -an $vg "$dev1"
lvcreate -n $lv2 -l1 -an $vg "$dev1"
aux disable_dev "$dev2"
pvs
pvs "$dev1"
not pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
lvs $vg/$lv2
lvremove $vg/$lv2
aux enable_dev "$dev2"
pvs 2>&1 | tee out
grep "ignoring metadata seqno" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
not lvs $vg/$lv2
# fixes the old metadata on dev1
vgck --updatemetadata $vg
pvs 2>&1 | tee out
not grep "ignoring metadata seqno" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
not lvs $vg/$lv2
#
# Test that any writing command will also update the
# old metadata.
#
lvcreate -n $lv2 -l1 -an $vg "$dev1"
aux disable_dev "$dev2"
pvs
pvs "$dev1"
not pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
lvs $vg/$lv2
lvremove $vg/$lv2
aux enable_dev "$dev2"
pvs 2>&1 | tee out
grep "ignoring metadata seqno" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
not lvs $vg/$lv2
# fixes the old metadata on dev1
lvcreate -n $lv3 -l1 -an $vg
pvs 2>&1 | tee out
not grep "ignoring metadata seqno" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
not lvs $vg/$lv2
vgremove -ff $vg
#
# First two PVs with one mda, where both have old metadata.
# Third PV with two mdas, where the first mda has old
# metadata, and the second mda has current metadata.
#
dd if=/dev/zero of="$dev1" || true
dd if=/dev/zero of="$dev2" || true
dd if=/dev/zero of="$dev3" || true
pvcreate "$dev1"
pvcreate "$dev2"
pvcreate --pvmetadatacopies 2 "$dev3"
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
lvcreate -n $lv1 -l1 -an $vg "$dev3"
lvcreate -n $lv2 -l1 -an $vg "$dev3"
# Save the metadata at this point...
dd if="$dev1" of=meta1 bs=4k count=4
dd if="$dev2" of=meta2 bs=4k count=4
dd if="$dev3" of=meta3 bs=4k count=4
# and now change metadata so the saved copies are old
lvcreate -n $lv3 -l1 -an $vg "$dev3"
# Copy the saved metadata back to the three
# devs first mda, leaving the second mda on
# dev3 as the only latest copy of the metadata.
dd if=meta1 of="$dev1"
dd if=meta2 of="$dev2"
dd if=meta3 of="$dev3"
pvs 2>&1 | tee out
grep "ignoring metadata seqno" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
# We still see the three LVs since we are using
# the latest copy of metadata from dev3:mda2
lvs $vg/$lv1
lvs $vg/$lv2
lvs $vg/$lv3
# This command which writes the VG should update
# all of the old copies.
lvcreate -n $lv4 -l1 -an $vg
pvs 2>&1 | tee out
not grep "ignoring metadata seqno" out
pvs "$dev1"
pvs "$dev2"
pvs "$dev3"
lvs $vg/$lv1
lvs $vg/$lv2
lvs $vg/$lv3
lvs $vg/$lv4
vgchange -an $vg
vgremove -ff $vg

View File

@@ -123,16 +123,13 @@ check_and_cleanup_lvs_()
recover_vg_()
{
aux enable_dev "$@"
# ensure hints are updated
pvscan --cache
# clear outdated metadata on PVs so they can be used again
vgck --updatemetadata $vg
pvscan --cache
pvcreate -ff "$@"
# wipefs -a "$@"
vgextend $vg "$@"
check_and_cleanup_lvs_
}

View File

@@ -1,66 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU 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
. lib/inittest
aux prepare_devs 3
get_devs
#
# Test handling of "outdated PV" which occurs when a PV goes missing
# from a VG, and while it's missing the PV is removed from the VG.
# Then the PV reappears with the old VG metadata that shows it is a
# member. That outdated metadata needs to be cleared.
#
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
lvcreate -n $lv1 -l1 -an $vg "$dev1"
lvcreate -n $lv2 -l1 -an $vg "$dev1"
aux disable_dev "$dev2"
vgreduce --removemissing $vg
pvs
aux enable_dev "$dev2"
pvs 2>&1 | tee out
grep "outdated" out
not pvs "$dev2"
# The VG can still be used with the outdated PV around
lvcreate -n $lv3 -l1 $vg
lvchange -ay $vg
lvs $vg
lvchange -an $vg
# Clears the outdated PV
vgck --updatemetadata $vg
pvs 2>&1 | tee out
not grep "outdated" out
# The PV is no longer in the VG
pvs "$dev2" | tee out
not grep "$vg" out
# The cleared PV can be added back to the VG
vgextend $vg "$dev2"
pvs "$dev2" | tee out
grep "$vg" out
vgremove -ff $vg

View File

@@ -1,119 +0,0 @@
#!/usr/bin/env bash
# Copyright (C) 2008-2013,2018 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU 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
. lib/inittest
aux prepare_devs 3
get_devs
dd if=/dev/zero of="$dev1" || true
dd if=/dev/zero of="$dev2" || true
dd if=/dev/zero of="$dev3" || true
pvcreate "$dev1"
pvcreate "$dev2"
pvcreate --pvmetadatacopies 2 "$dev3"
vgcreate $SHARED $vg "$dev1" "$dev2" "$dev3"
pvck --dump headers "$dev1" > h1
pvck --dump headers "$dev2" > h2
pvck --dump headers "$dev3" > h3
grep "label_header at 512" h1
grep "label_header at 512" h2
grep "label_header at 512" h3
grep "pv_header at 544" h1
grep "pv_header at 544" h2
grep "pv_header at 544" h3
grep "pv_header.disk_locn\[0\].offset 1048576" h1
grep "pv_header.disk_locn\[0\].offset 1048576" h2
grep "pv_header.disk_locn\[0\].offset 1048576" h3
grep "pv_header.disk_locn\[2\].offset 4096" h1
grep "pv_header.disk_locn\[2\].offset 4096" h2
grep "pv_header.disk_locn\[2\].offset 4096" h3
grep "pv_header.disk_locn\[2\].size 1044480" h1
grep "pv_header.disk_locn\[2\].size 1044480" h2
grep "pv_header.disk_locn\[2\].size 1044480" h3
grep "mda_header_1 at 4096" h1
grep "mda_header_1 at 4096" h2
grep "mda_header_1 at 4096" h3
grep "mda_header_1.start 4096" h1
grep "mda_header_1.start 4096" h2
grep "mda_header_1.start 4096" h3
grep "mda_header_1.size 1044480" h1
grep "mda_header_1.size 1044480" h2
grep "mda_header_1.size 1044480" h3
grep "mda_header_2 at " h3
grep "mda_header_2.start " h3
grep "metadata text at " h1
grep "metadata text at " h2
grep "metadata text at " h3
not grep CHECK h1
not grep CHECK h2
not grep CHECK h3
pvck --dump metadata "$dev1" > m1
pvck --dump metadata "$dev2" > m2
pvck --dump metadata "$dev3" > m3
pvck --dump metadata --pvmetadatacopies 2 "$dev3" > m3b
diff m1 m2
diff m1 m3
not diff m1 m3b > tmp
grep "metadata text at" tmp
lvcreate -an -l1 $vg
pvck --dump metadata_all -f all1 "$dev1" > out1
pvck --dump metadata_all -f all2 "$dev2" > out2
pvck --dump metadata_all -f all3 "$dev3" > out3
pvck --dump metadata_all --pvmetadatacopies 2 -f all3b "$dev3" > out3b
diff out1 out2
diff out1 out3
grep "seqno 1 with" out1
grep "seqno 1 with" out3b
grep "seqno 2 with" out1
grep "seqno 2 with" out3b
diff all1 all2
diff all1 all3
diff all1 all3b
grep "seqno = 1" all1
grep "seqno = 2" all1
pvck --dump metadata_area -f area1 "$dev1"
pvck --dump metadata_area -f area2 "$dev2"
pvck --dump metadata_area -f area3 "$dev3"
pvck --dump metadata_area -f area3b "$dev3"
diff area1 area2
diff area1 area3
diff area1 area3b
vgremove -ff $vg

View File

@@ -33,9 +33,9 @@ test_pvmove_resume() {
# next LV on same VG and differetnt PV (we want to test 2 pvmoves per VG)
lvcreate -an -Zn -l30 -n $lv2 $vg "$dev3"
aux delay_dev "$dev4" 0 500 "$(get first_extent_sector "$dev4"):"
aux delay_dev "$dev4" 0 250 "$(get first_extent_sector "$dev4"):"
test -e HAVE_DM_DELAY || { lvremove -f $vg; return 0; }
aux delay_dev "$dev5" 0 500 "$(get first_extent_sector "$dev5"):"
aux delay_dev "$dev5" 0 250 "$(get first_extent_sector "$dev5"):"
pvmove -i5 "$dev1" "$dev4" &
PVMOVE=$!

View File

@@ -134,8 +134,6 @@ not ls "$RUNDIR/lvm/pvs_online/$PVID3"
# pvscan cache ignores pv in a foreign vg
if [ -e "/etc/machine-id" ]; then
aux lvmconf "global/system_id_source = machineid"
_clear_online_files
@@ -170,8 +168,6 @@ cat tmp
grep $lv2 tmp
check lv_field $vg2/$lv2 lv_active "" --foreign
fi
# Test the case where pvscan --cache -aay (with no devs)
# gets the final PV to complete the VG, where that final PV

View File

@@ -215,10 +215,8 @@ arg(driverloaded_ARG, '\0', "driverloaded", bool_VAL, 0, 0,
arg(dump_ARG, '\0', "dump", string_VAL, 0, 0,
"Dump metadata from a PV. Option values include \\fBmetadata\\fP\n"
"to print or save the current text metadata, \\fBmetadata_area\\fP\n"
"to save the entire text metadata area to a file, \\fBmetadata_all\\fP\n"
"to save the current and any previous complete versions of metadata\n"
"to a file, and \\fBheaders\\fP to print and check LVM headers.\n")
"to extract the current text metadata, and \\fBmetadata_area\\fP\n"
"to extract the entire text metadata area.\n")
arg(errorwhenfull_ARG, '\0', "errorwhenfull", bool_VAL, 0, 0,
"Specifies thin pool behavior when data space is exhausted.\n"
@@ -713,8 +711,9 @@ arg(trackchanges_ARG, '\0', "trackchanges", 0, 0, 0,
"merging the split image (see --mergemirrors) or permanently splitting\n"
"the image (see --splitmirrors with --name.\n")
/* TODO: hide this? */
arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0,
"No longer used.\n")
"Avoids certain device scanning during command processing. Do not use.\n")
arg(type_ARG, '\0', "type", segtype_VAL, 0, 0,
"The LV type, also known as \"segment type\" or \"segtype\".\n"

View File

@@ -198,7 +198,7 @@ OO_REPORT: --aligned, --all, --binary, --configreport ConfigReport, --foreign,
--nameprefixes, --noheadings, --nosuffix,
--options String, --readonly, --reportformat ReportFmt, --rows,
--select String, --separator String, --shared, --sort String,
--unbuffered, --units Units, --unquoted
--trustcache, --unbuffered, --units Units, --unquoted
#
# options for config, dumpconfig, lvmconfig
@@ -1384,7 +1384,7 @@ DESC: Resize a pool metadata SubLV by a specified size.
lvs
OO: --history, --segments, OO_REPORT
OP: VG|LV|Tag ...
IO: --partial, --ignoreskippedcluster, --trustcache
IO: --partial, --ignoreskippedcluster
ID: lvs_general
---
@@ -1404,7 +1404,7 @@ OO_PVCHANGE: --autobackup Bool, --force, --reportformat ReportFmt, --uuid
OO_PVCHANGE_META: --allocatable Bool, --addtag Tag, --deltag Tag,
--uuid, --metadataignore Bool
pvchange --all OO_PVCHANGE_META
pvchange OO_PVCHANGE_META --all
OO: OO_PVCHANGE
IO: --ignoreskippedcluster
ID: pvchange_properties_all
@@ -1430,9 +1430,9 @@ ID: pvck_general
DESC: Check for metadata on a device
pvck --dump String PV
OO: --file String, --pvmetadatacopies MetadataCopiesPV, --labelsector Number
ID: pvck_dump
DESC: Print metadata from a device
OO: --file String, --pvmetadatacopies MetadataCopiesPV
ID: pvck_dumpmetadata
DESC: Dump raw metadata from a device
---
@@ -1486,7 +1486,7 @@ ID: pvremove_general
pvs
OO: --segments, OO_REPORT
OP: PV|Tag ...
IO: --partial, --ignoreskippedcluster, --trustcache
IO: --partial, --ignoreskippedcluster
ID: pvs_general
---
@@ -1752,7 +1752,7 @@ DESC: Rename a VG by specifying the VG UUID.
vgs
OO: OO_REPORT
OP: VG|Tag ...
IO: --partial, --ignoreskippedcluster, --trustcache
IO: --partial, --ignoreskippedcluster
ID: vgs_general
---
@@ -1807,7 +1807,7 @@ ID: devtypes_general
fullreport
OO: OO_REPORT
OP: VG ...
IO: --partial, --ignoreskippedcluster, --trustcache
IO: --partial, --ignoreskippedcluster
ID: fullreport_general
lastlog

View File

@@ -1070,7 +1070,7 @@ static void _add_required_opt_line(struct cmd_context *cmdtool, struct command *
* (This is the special case of vgchange/lvchange where one
* optional option is required, and others are then optional.)
* The set of options from OO_FOO are saved in required_opt_args,
* and flag CMD_FLAG_ANY_REQUIRED_OPT is set on the cmd indicating
* and flag CMD_FLAG_ONE_REQUIRED_OPT is set on the cmd indicating
* this special case.
*/
@@ -1104,7 +1104,6 @@ static void _add_required_line(struct cmd_context *cmdtool, struct command *cmd,
int i;
int takes_arg;
int prev_was_opt = 0, prev_was_pos = 0;
int orig_ro_count = 0;
/* argv[0] is command name */
@@ -1129,20 +1128,10 @@ static void _add_required_line(struct cmd_context *cmdtool, struct command *cmd,
prev_was_pos = 1;
} else if (!strncmp(argv[i], "OO_", 3)) {
/*
* the first ro_count entries in required_opt_arg required,
* after which one or more of the next any_ro_count entries
* in required_opt_arg are required. required_opt_arg
* has a total of ro_count+any_ro_count entries.
*/
cmd->cmd_flags |= CMD_FLAG_ANY_REQUIRED_OPT;
orig_ro_count = cmd->ro_count;
/* one required_opt_arg is required, special case lv/vgchange */
cmd->cmd_flags |= CMD_FLAG_ONE_REQUIRED_OPT;
_include_required_opt_args(cmdtool, cmd, argv[i]);
cmd->any_ro_count = cmd->ro_count - orig_ro_count;
cmd->ro_count = orig_ro_count;
} else if (prev_was_pos) {
/* set property for previous required_pos_arg */
_update_prev_pos_arg(cmd, argv[i], REQUIRED);
@@ -1784,7 +1773,7 @@ static void _print_usage_def(struct command *cmd, int opt_enum, struct arg_def *
void print_usage(struct command *cmd, int longhelp, int desc_first)
{
struct command_name *cname = _find_command_name(cmd->name);
int any_req = (cmd->cmd_flags & CMD_FLAG_ANY_REQUIRED_OPT) ? 1 : 0;
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
int include_extents = 0;
int ro, rp, oo, op, opt_enum, first;
@@ -1799,31 +1788,20 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
printf(" %s", cmd->name);
if (any_req) {
for (ro = 0; ro < cmd->ro_count; ro++) {
opt_enum = cmd->required_opt_args[ro].opt;
if (opt_names[opt_enum].short_opt)
printf(" -%c|%s", opt_names[opt_enum].short_opt, opt_names[opt_enum].long_opt);
else
printf(" %s", opt_names[opt_enum].long_opt);
if (cmd->required_opt_args[ro].def.val_bits) {
printf(" ");
_print_usage_def(cmd, opt_enum, &cmd->required_opt_args[ro].def);
}
}
if (onereq && cmd->ro_count) {
/* one required option in a set */
first = 1;
/* options with short and long */
for (ro = cmd->ro_count; ro < cmd->ro_count + cmd->any_ro_count; ro++) {
for (ro = 0; ro < cmd->ro_count; ro++) {
opt_enum = cmd->required_opt_args[ro].opt;
if (!opt_names[opt_enum].short_opt)
continue;
if ((opt_enum == size_ARG) && command_has_alternate_extents(cmd->name))
include_extents = 1;
if (first)
printf("\n\t(");
else
@@ -1839,7 +1817,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
}
/* options with only long */
for (ro = cmd->ro_count; ro < cmd->ro_count + cmd->any_ro_count; ro++) {
for (ro = 0; ro < cmd->ro_count; ro++) {
opt_enum = cmd->required_opt_args[ro].opt;
if (opt_names[opt_enum].short_opt)
@@ -1865,7 +1843,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
printf(" )\n");
}
if (!any_req && cmd->ro_count) {
if (!onereq && cmd->ro_count) {
for (ro = 0; ro < cmd->ro_count; ro++) {
opt_enum = cmd->required_opt_args[ro].opt;
@@ -1885,7 +1863,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first)
}
if (cmd->rp_count) {
if (any_req)
if (onereq)
printf("\t");
for (rp = 0; rp < cmd->rp_count; rp++) {
if (cmd->required_pos_args[rp].def.val_bits) {
@@ -2425,7 +2403,7 @@ static const char *_man_long_opt_name(const char *cmdname, int opt_enum)
static void _print_man_usage(char *lvmname, struct command *cmd)
{
struct command_name *cname;
int any_req = (cmd->cmd_flags & CMD_FLAG_ANY_REQUIRED_OPT) ? 1 : 0;
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
int sep, ro, rp, oo, op, opt_enum;
int need_ro_indent_end = 0;
int include_extents = 0;
@@ -2435,44 +2413,9 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
printf("\\fB%s\\fP", lvmname);
if (!any_req)
if (!onereq)
goto ro_normal;
/*
* required options that follow command name, all required
*/
if (cmd->ro_count) {
sep = 0;
for (ro = 0; ro < cmd->ro_count; ro++) {
/* avoid long line wrapping */
if ((cmd->ro_count > 2) && (sep == 2)) {
printf("\n.RS 5\n");
need_ro_indent_end = 1;
}
opt_enum = cmd->required_opt_args[ro].opt;
if ((opt_enum == size_ARG) && command_has_alternate_extents(cmd->name))
include_extents = 1;
if (opt_names[opt_enum].short_opt) {
printf(" \\fB-%c\\fP|\\fB%s\\fP",
opt_names[opt_enum].short_opt,
_man_long_opt_name(cmd->name, opt_enum));
} else
printf(" \\fB%s\\fP", opt_names[cmd->required_opt_args[ro].opt].long_opt);
if (cmd->required_opt_args[ro].def.val_bits) {
printf(" ");
_print_def_man(cname, opt_enum, &cmd->required_opt_args[ro].def, 1);
}
sep++;
}
}
/*
* one required option in a set, print as:
* ( -a|--a,
@@ -2484,7 +2427,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
* and the second loop prints those without short opts.
*/
if (cmd->any_ro_count) {
if (cmd->ro_count) {
printf("\n");
printf(".RS 4\n");
printf("(");
@@ -2492,7 +2435,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
sep = 0;
/* print required options with a short opt */
for (ro = cmd->ro_count; ro < cmd->ro_count + cmd->any_ro_count; ro++) {
for (ro = 0; ro < cmd->ro_count; ro++) {
opt_enum = cmd->required_opt_args[ro].opt;
if (!opt_names[opt_enum].short_opt)
@@ -2524,7 +2467,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
}
/* print required options without a short opt */
for (ro = cmd->ro_count; ro < cmd->ro_count + cmd->any_ro_count; ro++) {
for (ro = 0; ro < cmd->ro_count; ro++) {
opt_enum = cmd->required_opt_args[ro].opt;
if (opt_names[opt_enum].short_opt)
@@ -2554,7 +2497,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
printf(".RE\n");
}
/* print required position args on a new line after the any_req set */
/* print required position args on a new line after the onereq set */
if (cmd->rp_count) {
printf(".RS 4\n");
for (rp = 0; rp < cmd->rp_count; rp++) {

View File

@@ -164,16 +164,8 @@ struct cmd_rule {
/*
* one or more from required_opt_args is required,
* then the rest are optional.
*
* CMD_FLAG_ANY_REQUIRED_OPT: for lvchange/vgchange special case.
* The first ro_count entries of required_opt_args must be met
* (ro_count may be 0.) After this, one or more options must be
* set from the remaining required_opt_args. So, the first
* ro_count options in required_opt_args must match, and after
* that one or more of the remaining options in required_opt_args
* must match.
*/
#define CMD_FLAG_ANY_REQUIRED_OPT 1
#define CMD_FLAG_ONE_REQUIRED_OPT 1 /* lvchange/vgchage require one item from required_opt_args */
#define CMD_FLAG_SECONDARY_SYNTAX 2 /* allows syntax variants to be suppressed in certain output */
#define CMD_FLAG_PREVIOUS_SYNTAX 4 /* allows syntax variants to not be advertised in output */
#define CMD_FLAG_PARSE_ERROR 8 /* error parsing command-lines.in def */
@@ -210,8 +202,6 @@ struct command {
struct cmd_rule rules[CMD_MAX_RULES];
int any_ro_count;
int ro_count;
int oo_count;
int rp_count;

View File

@@ -177,7 +177,7 @@ xx(vgchange,
xx(vgck,
"Check the consistency of volume group(s)",
ALL_VGS_IS_DEFAULT | LOCKD_VG_SH)
ALL_VGS_IS_DEFAULT | LOCKD_VG_SH | ALLOW_HINTS)
xx(vgconvert,
"Change volume group metadata format",

View File

@@ -1084,7 +1084,7 @@ static int _lvchange_properties_single(struct cmd_context *cmd,
*/
/* First group of options which allow for one metadata commit/update for the whole group */
for (i = 0; i < cmd->command->ro_count + cmd->command->any_ro_count; i++) {
for (i = 0; i < cmd->command->ro_count; i++) {
opt_enum = cmd->command->required_opt_args[i].opt;
if (!arg_is_set(cmd, opt_enum))
@@ -1206,7 +1206,7 @@ static int _lvchange_properties_single(struct cmd_context *cmd,
return_ECMD_FAILED;
/* Second group of options which need per option metadata commit+reload(s) */
for (i = 0; i < cmd->command->ro_count + cmd->command->any_ro_count; i++) {
for (i = 0; i < cmd->command->ro_count; i++) {
opt_enum = cmd->command->required_opt_args[i].opt;
if (!arg_is_set(cmd, opt_enum))

View File

@@ -1192,7 +1192,7 @@ static void _set_valid_args_for_command_name(int ci)
if (strcmp(commands[i].name, command_names[ci].name))
continue;
for (ro = 0; ro < (commands[i].ro_count + commands[i].any_ro_count); ro++) {
for (ro = 0; ro < commands[i].ro_count; ro++) {
opt_enum = commands[i].required_opt_args[ro].opt;
all_args[opt_enum] = 1;
@@ -1533,7 +1533,7 @@ static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp
* For each command[i], check how many required opt/pos args cmd matches.
* Save the command[i] that matches the most.
*
* commands[i].cmd_flags & CMD_FLAG_ANY_REQUIRED_OPT means
* commands[i].cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT means
* any one item from commands[i].required_opt_args needs to be
* set to match.
*
@@ -1551,7 +1551,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
const char *name;
char opts_msg[MAX_OPTS_MSG];
char check_opts_msg[MAX_OPTS_MSG];
int match_required, match_ro, match_rp, match_any_ro, match_type, match_unused, mismatch_required;
int match_required, match_ro, match_rp, match_type, match_unused, mismatch_required;
int best_i = 0, best_required = 0, best_type = 0, best_unused = 0;
int close_i = 0, close_ro = 0, close_type = 0;
int only_i = 0;
@@ -1600,7 +1600,6 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
match_required = 0; /* required parameters that match */
match_ro = 0; /* required opt_args that match */
match_rp = 0; /* required pos_args that match */
match_any_ro = 0;
match_type = 0; /* type arg matches */
match_unused = 0; /* options set that are not accepted by command */
mismatch_required = 0; /* required parameters that do not match */
@@ -1629,19 +1628,20 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
}
}
for (ro = commands[i].ro_count; ro < commands[i].ro_count + commands[i].any_ro_count; ro++) {
if (_command_required_opt_matches(cmd, i, ro)) {
/* log_warn("match %d any ro opt %d", i, commands[i].required_opt_args[ro].opt); */
match_any_ro++;
/*
* Special case where missing required_opt_arg's does not matter
* if one required_opt_arg did match.
*/
if (commands[i].cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) {
if (match_ro) {
/* one or more of the required_opt_args is used */
mismatch_required = 0;
} else {
/* not even one of the required_opt_args is used */
mismatch_required = 1;
}
}
if ((commands[i].cmd_flags & CMD_FLAG_ANY_REQUIRED_OPT) && !match_any_ro) {
/* not even one of the any ro is used */
/* log_warn("match %d not one from any", i); */
mismatch_required = 1;
}
/* match required_pos_args */
for (rp = 0; rp < commands[i].rp_count; rp++) {
@@ -1697,7 +1697,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
accepted = 0;
/* NB in some cases required_opt_args are optional */
for (j = 0; j < commands[i].ro_count + commands[i].any_ro_count; j++) {
for (j = 0; j < commands[i].ro_count; j++) {
if (commands[i].required_opt_args[j].opt == opt_enum) {
accepted = 1;
break;
@@ -2396,6 +2396,17 @@ static int _get_current_settings(struct cmd_context *cmd)
if (arg_is_set(cmd, binary_ARG))
cmd->report_binary_values_as_numeric = 1;
if (arg_is_set(cmd, trustcache_ARG)) {
if (arg_is_set(cmd, all_ARG)) {
log_error("--trustcache is incompatible with --all");
return EINVALID_CMD_LINE;
}
init_trust_cache(1);
log_warn("WARNING: Cache file of PVs will be trusted. "
"New devices holding PVs may get ignored.");
} else
init_trust_cache(0);
if (arg_is_set(cmd, noudevsync_ARG))
cmd->current_settings.udev_sync = 0;
@@ -2755,53 +2766,20 @@ static int _init_lvmlockd(struct cmd_context *cmd)
return 1;
}
/*
* md_component_check full: always set use_full_md_check
* which causes filter-md to read the start+end of every
* device on the system (this could be optimized to only
* read the end of PVs.)
*
* md_component_check start: the end of devices will
* not generally be read to check for an md superblock
* (lvm may still scan for end-of-device md superblocks
* if it knows that some exists.)
*
* md_component_check auto: lvm will use some built-in
* heuristics to decide when it should scan the end of
* devices to look for md superblocks, e.g. commands
* like pvcreate that could clobber a component, or if
* udev info is not available and hints are not available.
*/
static void _init_md_checks(struct cmd_context *cmd)
{
const char *md_check;
cmd->md_component_detection = find_config_tree_bool(cmd, devices_md_component_detection_CFG, NULL);
md_check = find_config_tree_str(cmd, devices_md_component_checks_CFG, NULL);
if (!md_check)
cmd->md_component_checks = "auto";
else if (!strcmp(md_check, "auto") ||
!strcmp(md_check, "start") ||
!strcmp(md_check, "full"))
cmd->md_component_checks = md_check;
else {
log_warn("Ignoring unknown md_component_checks setting, using auto.");
cmd->md_component_checks = "auto";
}
if (!strcmp(cmd->md_component_checks, "full"))
/*
* use_full_md_check can also be set later.
* These commands are chosen to always perform
* a full md component check because they initialize
* a new device that could be an md component,
* and they are not run frequently during normal
* operation.
*/
if (!strcmp(cmd->name, "pvcreate") ||
!strcmp(cmd->name, "vgcreate") ||
!strcmp(cmd->name, "vgextend"))
cmd->use_full_md_check = 1;
else if (!strcmp(cmd->md_component_checks, "auto")) {
/* use_full_md_check can also be set later */
if (!strcmp(cmd->name, "pvcreate") ||
!strcmp(cmd->name, "vgcreate") ||
!strcmp(cmd->name, "vgextend"))
cmd->use_full_md_check = 1;
}
log_debug("Using md_component_checks %s use_full_md_check %d",
cmd->md_component_checks, cmd->use_full_md_check);
}
static int _cmd_no_meta_proc(struct cmd_context *cmd)
@@ -2931,12 +2909,12 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
!init_filters(cmd, !refresh_done))
return_ECMD_FAILED;
cmd->metadata_read_only = arg_is_set(cmd, readonly_ARG);
if (arg_is_set(cmd, readonly_ARG))
cmd->metadata_read_only = 1;
cmd->is_activating = (cmd->command->command_enum == vgchange_activate_CMD) ||
(cmd->command->command_enum == lvchange_activate_CMD);
cmd->wipe_outdated_pvs = 0;
if ((cmd->command->command_enum == vgchange_activate_CMD) ||
(cmd->command->command_enum == lvchange_activate_CMD))
cmd->is_activating = 1;
/*
* Now that all configs, profiles and command lines args are available,
@@ -3032,7 +3010,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
ret = cmd->command->fn(cmd, argc, argv);
lvmlockd_disconnect();
fin_locking(cmd);
fin_locking();
if (!_cmd_no_meta_proc(cmd) && find_config_tree_bool(cmd, global_notify_dbus_CFG, NULL))
lvmnotify_send(cmd);

File diff suppressed because it is too large Load Diff

View File

@@ -2262,7 +2262,7 @@ int process_each_vg(struct cmd_context *cmd,
*/
log_very_verbose("Obtaining the complete list of VGs to process");
if (!lvmcache_get_vgnameids(cmd, &vgnameids_on_system, NULL, include_internal)) {
if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, include_internal)) {
ret_max = ECMD_FAILED;
goto_out;
}
@@ -3807,7 +3807,7 @@ int process_each_lv(struct cmd_context *cmd,
*/
log_very_verbose("Obtaining the complete list of VGs before processing their LVs");
if (!lvmcache_get_vgnameids(cmd, &vgnameids_on_system, NULL, 0)) {
if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, 0)) {
ret_max = ECMD_FAILED;
goto_out;
}
@@ -4479,7 +4479,7 @@ int process_each_pv(struct cmd_context *cmd,
if (!(read_flags & PROCESS_SKIP_SCAN))
lvmcache_label_scan(cmd);
if (!lvmcache_get_vgnameids(cmd, &all_vgnameids, only_this_vgname, 1)) {
if (!get_vgnameids(cmd, &all_vgnameids, only_this_vgname, 1)) {
ret_max = ret;
goto_out;
}

View File

@@ -407,8 +407,8 @@ static int _vgchange_metadata_copies(struct cmd_context *cmd,
{
uint32_t mda_copies = arg_uint_value(cmd, vgmetadatacopies_ARG, DEFAULT_VGMETADATACOPIES);
log_debug("vgchange_metadata_copies new %u vg_mda_copies %u D %u",
mda_copies, vg_mda_copies(vg), DEFAULT_VGMETADATACOPIES);
log_warn("vgchange_metadata_copies new %u vg_mda_copies %u D %u",
mda_copies, vg_mda_copies(vg), DEFAULT_VGMETADATACOPIES);
if (mda_copies == vg_mda_copies(vg)) {
if (vg_mda_copies(vg) == VGMETADATACOPIES_UNMANAGED)

View File

@@ -71,7 +71,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
* then do the initial label scan which reads all devices and
* populates lvmcache with any VG name it finds. If the VG name
* we want to use exists, then the label scan will find it,
* and the vginfo_from_vgname call (used to check if the name exists)
* and the fmt_from_vgname call (used to check if the name exists)
* will return non-NULL.
*/
@@ -82,7 +82,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
lvmcache_label_scan(cmd);
if (lvmcache_vginfo_from_vgname(vp_new.vg_name, NULL)) {
if (lvmcache_fmt_from_vgname(cmd, vp_new.vg_name, NULL, 0)) {
unlock_vg(cmd, NULL, vp_new.vg_name);
log_error("A volume group called %s already exists.", vp_new.vg_name);
return ECMD_FAILED;

View File

@@ -296,7 +296,7 @@ int vgimportclone(struct cmd_context *cmd, int argc, char **argv)
vgname_count = 1;
}
if (!lvmcache_get_vgnameids(cmd, &vgnameids_on_system, NULL, 0))
if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, 0))
goto_out;
retry_name:

View File

@@ -445,6 +445,80 @@ static int _move_cache(struct volume_group *vg_from,
return 1;
}
/*
* Create or open the destination of the vgsplit operation.
* Returns
* - non-NULL: VG handle w/VG lock held
* - NULL: no VG lock held
*/
static struct volume_group *_vgsplit_to(struct cmd_context *cmd,
const char *vg_name_to,
int *existing_vg)
{
struct volume_group *vg_to = NULL;
int exists = 0;
log_verbose("Checking for new volume group \"%s\"", vg_name_to);
/*
* First try to create a new VG. If we cannot create it,
* and we get FAILED_EXIST (we will not be holding a lock),
* a VG must already exist with this name. We then try to
* read the existing VG - the vgsplit will be into an existing VG.
*
* Otherwise, if the lock was successful, it must be the case that
* we obtained a WRITE lock and could not find the vgname in the
* system. Thus, the split will be into a new VG.
*/
vg_to = vg_lock_and_create(cmd, vg_name_to, &exists);
if (!vg_to && !exists) {
log_error("Can't get lock for %s", vg_name_to);
release_vg(vg_to);
return NULL;
}
if (!vg_to && exists) {
*existing_vg = 1;
release_vg(vg_to);
vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0, 0);
if (vg_read_error(vg_to)) {
release_vg(vg_to);
return_NULL;
}
} else if (vg_read_error(vg_to) == SUCCESS) {
*existing_vg = 0;
}
return vg_to;
}
/*
* Open the source of the vgsplit operation.
* Returns
* - non-NULL: VG handle w/VG lock held
* - NULL: no VG lock held
*/
static struct volume_group *_vgsplit_from(struct cmd_context *cmd,
const char *vg_name_from)
{
struct volume_group *vg_from;
log_verbose("Checking for volume group \"%s\"", vg_name_from);
vg_from = vg_read_for_update(cmd, vg_name_from, NULL, 0, 0);
if (vg_read_error(vg_from)) {
release_vg(vg_from);
return NULL;
}
if (vg_is_shared(vg_from)) {
log_error("vgsplit not allowed for lock_type %s", vg_from->lock_type);
unlock_and_release_vg(cmd, vg_from, vg_name_from);
return NULL;
}
return vg_from;
}
/*
* Has the user given an option related to a new vg as the split destination?
*/
@@ -463,11 +537,11 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
struct vgcreate_params vp_def;
const char *vg_name_from, *vg_name_to;
struct volume_group *vg_to = NULL, *vg_from = NULL;
struct lvmcache_vginfo *vginfo_to;
int opt;
int existing_vg = 0;
int r = ECMD_FAILED;
const char *lv_name;
int lock_vg_from_first = 1;
if ((arg_is_set(cmd, name_ARG) + argc) < 3) {
log_error("Existing VG, new VG and either physical volumes "
@@ -503,44 +577,47 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
lvmcache_label_scan(cmd);
if (!(vginfo_to = lvmcache_vginfo_from_vgname(vg_name_to, NULL))) {
if (!validate_name(vg_name_to)) {
log_error("Invalid vg name %s.", vg_name_to);
return ECMD_FAILED;
}
if (strcmp(vg_name_to, vg_name_from) < 0)
lock_vg_from_first = 0;
if (!lock_vol(cmd, vg_name_to, LCK_VG_WRITE, NULL)) {
log_error("Failed to lock new VG name %s.", vg_name_to);
return ECMD_FAILED;
}
if (lock_vg_from_first) {
if (!(vg_from = _vgsplit_from(cmd, vg_name_from)))
return_ECMD_FAILED;
/*
* Set metadata format of original VG.
* NOTE: We must set the format before calling vg_lock_and_create()
* since vg_lock_and_create() calls the per-format constructor.
*/
cmd->fmt = vg_from->fid->fmt;
if (!(vg_to = vg_create(cmd, vg_name_to))) {
log_error("Failed to create new VG %s.", vg_name_to);
unlock_vg(cmd, NULL, vg_name_to);
return ECMD_FAILED;
if (!(vg_to = _vgsplit_to(cmd, vg_name_to, &existing_vg))) {
unlock_and_release_vg(cmd, vg_from, vg_name_from);
return_ECMD_FAILED;
}
} else {
if (!(vg_to = vg_read_for_update(cmd, vg_name_to, NULL, 0, 0))) {
log_error("Failed to read VG %s.", vg_name_to);
return ECMD_FAILED;
if (!(vg_to = _vgsplit_to(cmd, vg_name_to, &existing_vg)))
return_ECMD_FAILED;
if (!(vg_from = _vgsplit_from(cmd, vg_name_from))) {
unlock_and_release_vg(cmd, vg_to, vg_name_to);
return_ECMD_FAILED;
}
existing_vg = 1;
}
if (!(vg_from = vg_read_for_update(cmd, vg_name_from, NULL, 0, 0))) {
log_error("Failed to read VG %s.", vg_name_to);
unlock_and_release_vg(cmd, vg_to, vg_name_to);
return ECMD_FAILED;
if (cmd->fmt != vg_from->fid->fmt) {
/* In this case we don't know the vg_from->fid->fmt */
log_error("Unable to set new VG metadata type based on "
"source VG format - use -M option.");
goto bad;
}
}
cmd->fmt = vg_from->fid->fmt;
if (existing_vg) {
if (_new_vg_option_specified(cmd)) {
log_error("Volume group \"%s\" exists, but new VG option specified", vg_name_to);
log_error("Volume group \"%s\" exists, but new VG "
"option specified", vg_name_to);
goto bad;
}
if (!vgs_are_compatible(cmd, vg_from, vg_to))
if (!vgs_are_compatible(cmd, vg_from,vg_to))
goto_bad;
} else {
if (!vgcreate_params_set_defaults(cmd, &vp_def, vg_from)) {