1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-11-16 04:23:50 +03:00

Compare commits

..

2 Commits

Author SHA1 Message Date
David Teigland
31e2c4c1a6 locking: allow using global lock for scanning
When vg metadata consumes a major percentage of the metadata area,
acquire the global lock prior to label_scan.  Many commands
already acquire the global lock prior to label_scan, but
VG-specific commands may not otherwise use the global lock.

This attempts to avoid the rare situation in which the metadata is
large enough to wrap around the metadata area and invalidate the
metadata location information that a single command gathered from
label_scan.  If this wrapping with large sizes occurs, the metadata
locations seen during label scan may be overwritten before the
same command is able to use them for vg_read(), causing vg_read
to see invalid metadata and the command to fail.

A large number of concurrent lvm commands is also a factor that
can lead to this problem due to longer delays between label_scan
and vg_read.

This problem can be avoided if all commands acquire the global lock
prior to label scan, and hold it across all the vg_read() calls.
This ensures that the results from label scan are unchanging during
label scan and remain valid for use in vg_read.
Commands modifying vg metadata take the global lock ex, and those
only reading vg metadata use sh.

This extra use of the global lock is usually unnecessary, so lvm
automatically detects when the extra locking may be needed before
starting to use it.  When vg metadata is a large enough percentage
of the total metadata area, lvm begins doing extra locking.
Currently this is 25% (could be configurable.)

When one command sees this threshold has been reached, it creates
the file /run/lvm/scan_lock_global.  When subsequent commands see
this file exists, then will acquire the global lock prior to their
label_scan.  When metadata goes below the threshold, the temp file
is removed, and commands no longer do the extra locking.
2021-06-14 16:18:33 -05:00
David Teigland
09b0eea6a0 locking: hint-based vg locking optimization
This adds an optimization for some common cases in which
the VG lock can be acquired early, prior to label scan.
This reduces the chance that devices may be changed
between label scan and the normal vg lock in vg_read.

This is a proof-of-concept / experimental patch for testing.
2021-06-14 11:56:37 -05:00
128 changed files with 1687 additions and 2899 deletions

View File

@@ -1 +1 @@
2.03.14(2)-git (2021-08-11)
2.03.13(2)-git (2021-05-07)

View File

@@ -1 +1 @@
1.02.181-git (2021-08-11)
1.02.179-git (2021-05-07)

View File

@@ -1,23 +1,6 @@
Version 2.03.14 -
==================================
Version 2.03.13 - 11th August 2021
==================================
Changes in udev support:
- obtain_device_list_from_udev defaults to 0.
- see devices/external_device_info_source,
devices/obtain_device_list_from_udev, and devices/multipath_wwids_file help
in lvm.conf
Fix devices file handling of loop with deleted backing file.
Fix devices file handling of scsi_debug WWIDs.
Fix many static analysis issues.
Support --poolmetadataspare with vgsplit and vgmerge.
Fix detection of active components of external origin volume.
Add vdoimport tool to support conversion of VDO volumes.
Support configurable allocation/vdo_pool_header_size.
Fix handling of lvconvert --type vdo-pool --virtualsize.
Version 2.03.13 -
===============================
Simplified handling of archive() and backup() internal calls.
Add 'idm' locking type for IDM lock manager.
Fix load of kvdo target when it is not present in memory (2.03.12).
Version 2.03.12 - 07th May 2021

View File

@@ -1,8 +1,5 @@
Version 1.02.181 -
===================================
Version 1.02.179 - 11th August 2021
===================================
Version 1.02.179 -
================================
Version 1.02.177 - 07th May 2021
================================

View File

@@ -67,13 +67,25 @@ devices {
# setting applies only to the udev-managed device directory; other
# directories will be scanned fully. LVM needs to be compiled with
# udev support for this setting to apply.
obtain_device_list_from_udev = 0
obtain_device_list_from_udev = 1
# Configuration option devices/external_device_info_source.
# Enable device information from udev.
# If set to "udev", lvm will supplement its own native device information
# with information from libudev. This can potentially improve the detection
# of MD component devices and multipath component devices.
# Select an external device information source.
# Some information may already be available in the system and LVM can
# use this information to determine the exact type or use of devices it
# processes. Using an existing external device information source can
# speed up device processing as LVM does not need to run its own native
# routines to acquire this information. For example, this information
# is used to drive LVM filtering like MD component detection, multipath
# component detection, partition detection and others.
#
# Accepted values:
# none
# No external device information source is used.
# udev
# Reuse existing udev database records. Applicable only if LVM is
# compiled with udev support.
#
external_device_info_source = "none"
# Configuration option devices/hints.
@@ -220,12 +232,6 @@ devices {
# Ignore devices that are components of DM multipath devices.
multipath_component_detection = 1
# Configuration option devices/multipath_wwids_file.
# The path to the multipath wwids file used for multipath component detection.
# Set this to an empty string to disable the use of the multipath wwids file.
# This configuration option has an automatic default value.
# multipath_wwids_file = "/etc/multipath/wwids"
# 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
@@ -717,7 +723,7 @@ allocation {
# vdo_write_policy = "auto"
# Configuration option allocation/vdo_max_discard.
# Specified the maximum size of discard bio accepted, in 4096 byte blocks.
# Specified te maximum size of discard bio accepted, in 4096 byte blocks.
# I/O requests to a VDO volume are normally split into 4096-byte blocks,
# and processed up to 2048 at a time. However, discard requests to a VDO volume
# can be automatically split to a larger size, up to <max discard> 4096-byte blocks
@@ -727,11 +733,6 @@ allocation {
# The default and minimum is 1. The maximum is UINT_MAX / 4096.
# This configuration option has an automatic default value.
# vdo_max_discard = 1
# Configuration option allocation/vdo_pool_header_size.
# Specified the emptry header size in KiB at the front and end of vdo pool device.
# This configuration option has an automatic default value.
# vdo_pool_header_size = 512
}
# Configuration section log.

51
configure vendored
View File

@@ -643,8 +643,6 @@ WRITE_INSTALL
WRITECACHE
VDO_LIB
VDO_INCLUDE
VDOIMPORT_PATH
VDOIMPORT
VDO
VALGRIND_POOL
USRSBINDIR
@@ -749,6 +747,7 @@ BUILD_DMFILEMAPD
BUILD_LOCKDDLM_CONTROL
BUILD_LOCKDDLM
BUILD_LOCKDSANLOCK
BUILD_LOCKDIDM
BUILD_LVMLOCKD
BUILD_LVMPOLLD
BUILD_LVMDBUSD
@@ -774,18 +773,18 @@ UDEV_LIBS
UDEV_CFLAGS
SYSTEMD_LIBS
SYSTEMD_CFLAGS
NOTIFY_DBUS_LIBS
NOTIFY_DBUS_CFLAGS
BLKID_LIBS
BLKID_CFLAGS
LOCKD_IDM_LIBS
LOCKD_IDM_CFLAGS
NOTIFY_DBUS_LIBS
NOTIFY_DBUS_CFLAGS
LOCKD_DLM_CONTROL_LIBS
LOCKD_DLM_CONTROL_CFLAGS
LOCKD_DLM_LIBS
LOCKD_DLM_CFLAGS
LOCKD_SANLOCK_LIBS
LOCKD_SANLOCK_CFLAGS
LOCKD_IDM_LIBS
LOCKD_IDM_CFLAGS
VALGRIND_LIBS
VALGRIND_CFLAGS
GENPNG
@@ -971,7 +970,6 @@ enable_dbus_service
enable_pkgconfig
enable_write_install
enable_fsadm
enable_vdoimport
enable_blkdeactivate
enable_dmeventd
enable_selinux
@@ -1027,10 +1025,10 @@ LOCKD_DLM_CONTROL_CFLAGS
LOCKD_DLM_CONTROL_LIBS
LOCKD_IDM_CFLAGS
LOCKD_IDM_LIBS
BLKID_CFLAGS
BLKID_LIBS
NOTIFY_DBUS_CFLAGS
NOTIFY_DBUS_LIBS
BLKID_CFLAGS
BLKID_LIBS
SYSTEMD_CFLAGS
SYSTEMD_LIBS
UDEV_CFLAGS
@@ -1710,7 +1708,6 @@ Optional Features:
--enable-pkgconfig install pkgconfig support
--enable-write_install install user writable files
--disable-fsadm disable fsadm
--disable-vdoimport disable vdoimport
--disable-blkdeactivate disable blkdeactivate
--enable-dmeventd enable the device-mapper event daemon
--disable-selinux disable selinux support
@@ -1846,13 +1843,13 @@ Some influential environment variables:
C compiler flags for LOCKD_IDM, overriding pkg-config
LOCKD_IDM_LIBS
linker flags for LOCKD_IDM, overriding pkg-config
BLKID_CFLAGS
C compiler flags for BLKID, overriding pkg-config
BLKID_LIBS linker flags for BLKID, overriding pkg-config
NOTIFY_DBUS_CFLAGS
C compiler flags for NOTIFY_DBUS, overriding pkg-config
NOTIFY_DBUS_LIBS
linker flags for NOTIFY_DBUS, overriding pkg-config
BLKID_CFLAGS
C compiler flags for BLKID, overriding pkg-config
BLKID_LIBS linker flags for BLKID, overriding pkg-config
SYSTEMD_CFLAGS
C compiler flags for SYSTEMD, overriding pkg-config
SYSTEMD_LIBS
@@ -3143,7 +3140,6 @@ case "$host_os" in
DM_IOCTLS=yes
SELINUX=yes
FSADM=yes
VDOIMPORT=yes
BLKDEACTIVATE=yes
;;
darwin*)
@@ -3157,7 +3153,6 @@ case "$host_os" in
DM_IOCTLS=no
SELINUX=no
FSADM=no
VDOIMPORT=no
BLKDEACTIVATE=no
;;
*)
@@ -11265,7 +11260,7 @@ fi
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -11283,7 +11278,7 @@ fi
$bailout
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$bailout
else
@@ -11291,7 +11286,6 @@ else
LOCKD_IDM_LIBS=$pkg_cv_LOCKD_IDM_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
HAVE_LOCKD_IDM=yes
fi
pkg_failed=no
@@ -12550,18 +12544,6 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $FSADM" >&5
$as_echo "$FSADM" >&6; }
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install vdoimport" >&5
$as_echo_n "checking whether to install vdoimport... " >&6; }
# Check whether --enable-vdoimport was given.
if test "${enable_vdoimport+set}" = set; then :
enableval=$enable_vdoimport; VDOIMPORT=$enableval
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $VDOIMPORT" >&5
$as_echo "$VDOIMPORT" >&6; }
################################################################################
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install blkdeactivate" >&5
$as_echo_n "checking whether to install blkdeactivate... " >&6; }
@@ -14048,13 +14030,6 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
VDOIMPORT_PATH="$SBINDIR/vdoimport"
cat >>confdefs.h <<_ACEOF
#define VDOIMPORT_PATH "$VDOIMPORT_PATH"
_ACEOF
################################################################################
if test "$BUILD_DMEVENTD" = yes; then
@@ -14375,8 +14350,6 @@ _ACEOF

View File

@@ -46,7 +46,6 @@ case "$host_os" in
DM_IOCTLS=yes
SELINUX=yes
FSADM=yes
VDOIMPORT=yes
BLKDEACTIVATE=yes
;;
darwin*)
@@ -60,7 +59,6 @@ case "$host_os" in
DM_IOCTLS=no
SELINUX=no
FSADM=no
VDOIMPORT=no
BLKDEACTIVATE=no
;;
*)
@@ -1313,14 +1311,6 @@ AC_ARG_ENABLE(fsadm, AC_HELP_STRING([--disable-fsadm], [disable fsadm]),
FSADM=$enableval)
AC_MSG_RESULT($FSADM)
################################################################################
dnl -- Enable vdoimport
AC_MSG_CHECKING(whether to install vdoimport)
AC_ARG_ENABLE(vdoimport, AC_HELP_STRING([--disable-vdoimport], [disable vdoimport]),
VDOIMPORT=$enableval)
AC_MSG_RESULT($VDOIMPORT)
################################################################################
dnl -- Enable blkdeactivate
AC_MSG_CHECKING(whether to install blkdeactivate)
@@ -1676,9 +1666,6 @@ USRSBINDIR="$(eval echo $(eval echo $usrsbindir))"
FSADM_PATH="$SBINDIR/fsadm"
AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
VDOIMPORT_PATH="$SBINDIR/vdoimport"
AC_DEFINE_UNQUOTED(VDOIMPORT_PATH, ["$VDOIMPORT_PATH"], [Path to vdoimport binary.])
################################################################################
dnl -- dmeventd pidfile and executable path
if test "$BUILD_DMEVENTD" = yes; then
@@ -1915,8 +1902,6 @@ AC_SUBST(SILENT_RULES)
AC_SUBST(USRSBINDIR)
AC_SUBST(VALGRIND_POOL)
AC_SUBST(VDO)
AC_SUBST(VDOIMPORT)
AC_SUBST(VDOIMPORT_PATH)
AC_SUBST(VDO_FORMAT_CMD)
AC_SUBST(VDO_INCLUDE)
AC_SUBST(VDO_LIB)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -790,14 +790,14 @@ int lm_is_running_dlm(void)
int lm_refresh_lv_start_dlm(struct action *act)
{
char path[PATH_MAX] = { 0 };
char path[PATH_MAX];
char command[DLMC_RUN_COMMAND_LEN];
char run_uuid[DLMC_RUN_UUID_LEN];
char *p, *vgname, *lvname;
int rv;
/* split /dev/vgname/lvname into vgname and lvname strings */
strncpy(path, act->path, PATH_MAX-1);
strncpy(path, act->path, strlen(act->path));
/* skip past dev */
p = strchr(path + 1, '/');

View File

@@ -227,20 +227,6 @@ int lm_data_size_sanlock(void)
static uint64_t daemon_test_lv_count;
/*
* Copy a null-terminated string "str" into a fixed
* size (SANLK_NAME_LEN) struct field "buf" which is
* not null terminated.
*/
static void strcpy_name_len(char *buf, char *str, int len)
{
char tmp_name[SANLK_NAME_LEN + 1] = { 0 };
strncpy(tmp_name, str, SANLK_NAME_LEN);
memcpy(buf, str, SANLK_NAME_LEN);
}
static int lock_lv_name_from_args(char *vg_args, char *lock_lv_name)
{
return last_string_from_args(vg_args, lock_lv_name);
@@ -588,7 +574,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
}
}
strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN);
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
memcpy(ss.host_id_disk.path, disk.path, SANLK_PATH_LEN);
ss.host_id_disk.offset = 0;
ss.flags = (sector_size == 4096) ? (SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M) :
@@ -621,7 +607,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
gl_name = R_NAME_GL;
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)gl_name, SANLK_NAME_LEN);
strncpy(rd.rs.name, gl_name, SANLK_NAME_LEN);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
rd.rs.disks[0].offset = align_size * GL_LOCK_BEGIN;
rd.rs.num_disks = 1;
@@ -636,7 +622,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)R_NAME_VG, SANLK_NAME_LEN);
strncpy(rd.rs.name, R_NAME_VG, SANLK_NAME_LEN);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
rd.rs.disks[0].offset = align_size * VG_LOCK_BEGIN;
rd.rs.num_disks = 1;
@@ -670,8 +656,8 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
memcpy(rd.rs.disks[0].path, disk.path, SANLK_PATH_LEN);
strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)"#unused", SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strcpy(rd.rs.name, "#unused");
offset = align_size * LV_LOCK_BEGIN;
@@ -739,7 +725,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
return 0;
}
strcpy_name_len(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls_name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
if ((rv = build_dm_path(rd.rs.disks[0].path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
return rv;
@@ -814,7 +800,7 @@ int lm_init_lv_sanlock(char *ls_name, char *vg_name, char *lv_name,
log_debug("S %s init_lv_san %s found unused area at %llu",
ls_name, lv_name, (unsigned long long)offset);
strcpy_name_len(rd.rs.name, lv_name, SANLK_NAME_LEN);
strncpy(rd.rs.name, lv_name, SANLK_NAME_LEN);
rd.rs.flags = (sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -913,7 +899,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
if (!sector_size || !align_size)
return -1;
strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN);
strncpy(ss.name, ls_name, SANLK_NAME_LEN);
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
@@ -938,7 +924,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return rv;
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -963,7 +949,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return rv;
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv < 0) {
@@ -997,7 +983,7 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
break;
}
memcpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ss.name, SANLK_NAME_LEN);
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (rv) {
@@ -1023,7 +1009,7 @@ int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r)
if (daemon_test)
return 0;
strcpy_name_len(rs->name, (char *)"#unused", SANLK_NAME_LEN);
strcpy(rs->name, "#unused");
rv = sanlock_write_resource(rs, 0, 0, 0);
if (rv < 0) {
@@ -1057,14 +1043,14 @@ int lm_ex_disable_gl_sanlock(struct lockspace *ls)
memset(&rd1, 0, sizeof(rd1));
memset(&rd2, 0, sizeof(rd2));
strcpy_name_len(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd1.rs.name, (char *)R_NAME_GL, SANLK_NAME_LEN);
strncpy(rd1.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd1.rs.name, R_NAME_GL, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd2.rs.name, (char *)R_NAME_GL_DISABLED, SANLK_NAME_LEN);
strncpy(rd2.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd2.rs.name, R_NAME_GL_DISABLED, SANLK_NAME_LEN);
rd1.rs.num_disks = 1;
memcpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
strncpy(rd1.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd1.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
rd1.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
@@ -1126,11 +1112,11 @@ int lm_able_gl_sanlock(struct lockspace *ls, int enable)
memset(&rd, 0, sizeof(rd));
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rd.rs.name, (char *)gl_name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd.rs.name, gl_name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd.rs.disks[0].offset = lms->align_size * GL_LOCK_BEGIN;
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -1167,12 +1153,12 @@ static int gl_is_enabled(struct lockspace *ls, struct lm_sanlock *lms)
memset(&rd, 0, sizeof(rd));
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
/* leave rs.name empty, it is what we're checking */
rd.rs.num_disks = 1;
memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
offset = lms->align_size * GL_LOCK_BEGIN;
rd.rs.disks[0].offset = offset;
@@ -1238,9 +1224,9 @@ int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t *free_offset, int *
memset(&rd, 0, sizeof(rd));
strcpy_name_len(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rd.rs.lockspace_name, ls->name, SANLK_NAME_LEN);
rd.rs.num_disks = 1;
memcpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
strncpy(rd.rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN-1);
rd.rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) :
(SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -1425,7 +1411,7 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls)
memcpy(lms->ss.name, lsname, SANLK_NAME_LEN);
lms->ss.host_id_disk.offset = 0;
lms->ss.host_id = ls->host_id;
memcpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1);
strncpy(lms->ss.host_id_disk.path, disk_path, SANLK_PATH_LEN-1);
if (daemon_test) {
if (!gl_lsname_sanlock[0]) {
@@ -1591,7 +1577,7 @@ int lm_rem_lockspace_sanlock(struct lockspace *ls, int free_vg)
* This shouldn't be generally necessary, but there may some races
* between nodes starting and removing a vg which this could help.
*/
strcpy_name_len(lms->ss.name, (char *)"#unused", SANLK_NAME_LEN);
strncpy(lms->ss.name, "#unused", SANLK_NAME_LEN);
rv = sanlock_write_lockspace(&lms->ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
@@ -1619,8 +1605,8 @@ static int lm_add_resource_sanlock(struct lockspace *ls, struct resource *r)
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
struct rd_sanlock *rds = (struct rd_sanlock *)r->lm_data;
strcpy_name_len(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strcpy_name_len(rds->rs.name, r->name, SANLK_NAME_LEN);
strncpy(rds->rs.lockspace_name, ls->name, SANLK_NAME_LEN);
strncpy(rds->rs.name, r->name, SANLK_NAME_LEN);
rds->rs.num_disks = 1;
memcpy(rds->rs.disks[0].path, lms->ss.host_id_disk.path, SANLK_PATH_LEN);
rds->rs.flags = (lms->sector_size == 4096) ? (SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M) : (SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M);
@@ -2049,7 +2035,7 @@ static int release_rename(struct lockspace *ls, struct resource *r)
res1 = (struct sanlk_resource *)&rd1;
res2 = (struct sanlk_resource *)&rd2;
strcpy_name_len(res2->name, (char *)"invalid_removed", SANLK_NAME_LEN);
strcpy(res2->name, "invalid_removed");
res_args[0] = res1;
res_args[1] = res2;
@@ -2242,8 +2228,8 @@ int lm_get_lockspaces_sanlock(struct list_head *ls_rejoin)
ls->lm_type = LD_LM_SANLOCK;
ls->host_id = ss->host_id;
memcpy(ls->name, ss->name, SANLK_NAME_LEN);
memcpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), SANLK_NAME_LEN - strlen(LVM_LS_PREFIX));
strncpy(ls->name, ss->name, MAX_NAME);
strncpy(ls->vg_name, ss->name + strlen(LVM_LS_PREFIX), MAX_NAME);
list_add_tail(&ls->list, ls_rejoin);
ss++;

View File

@@ -1920,7 +1920,7 @@ static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, si
continue;
if ((sz = dm_snprintf(path, sizeof(path), "%sblock/%s/dev",
_sysfs_dir, name)) < 5) {
_sysfs_dir, name)) == -1) {
log_warn("Couldn't create path for %s.", name);
continue;
}

View File

@@ -558,12 +558,12 @@
/* Define to 1 to include code that uses lvmlockd dlm option. */
#undef LOCKDDLM_SUPPORT
/* Define to 1 to include code that uses lvmlockd IDM option. */
#undef LOCKDIDM_SUPPORT
/* Define to 1 to include code that uses lvmlockd sanlock option. */
#undef LOCKDSANLOCK_SUPPORT
/* Define to 1 to include code that uses lvmlockd IDM option. */
#undef LOCKDIDM_SUPPORT
/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
slash. */
#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
@@ -687,9 +687,6 @@
/* Enable a valgrind aware build of pool */
#undef VALGRIND_POOL
/* Path to vdoimport binary. */
#undef VDOIMPORT_PATH
/* The path to 'vdoformat', if available. */
#undef VDO_FORMAT_CMD

View File

@@ -34,7 +34,6 @@ SOURCES =\
device/dev-ext.c \
device/dev-io.c \
device/dev-md.c \
device/dev-mpath.c \
device/dev-swap.c \
device/dev-type.c \
device/dev-luks.c \

View File

@@ -563,7 +563,7 @@ int module_present(struct cmd_context *cmd, const char *target_name)
dm_sysfs_dir(), target_name);
if (i > 0) {
while ((i > 0) && path[--i] != '/') /* stop on dm_ */
while (path[--i] != '/') /* stop on dm_ */
if (path[i] == '-')
path[i] = '_'; /* replace '-' with '_' */
@@ -2740,10 +2740,7 @@ static int _component_cb(struct logical_volume *lv, void *data)
(lv_is_thin_pool(lv) && pool_is_active(lv)))
return -1;
/* External origin is activated through thinLV and uses -real suffix.
* Note: for old clustered logic we would need to check for all thins */
if ((lv_is_external_origin(lv) && lv_info(lv->vg->cmd, lv, 1, NULL, 0, 0)) ||
lv_is_active(lv)) {
if (lv_is_active(lv)) {
if (!lv_is_component(lv) || lv_is_visible(lv))
return -1; /* skip whole subtree */

View File

@@ -2118,7 +2118,7 @@ static int _check_holder(struct dev_manager *dm, struct dm_tree *dtree,
if (!strncmp(default_uuid_prefix, uuid, default_uuid_prefix_len))
uuid += default_uuid_prefix_len;
if (!memcmp(uuid, &lv->vg->id, ID_LEN) &&
if (!strncmp(uuid, (char*)&lv->vg->id, sizeof(lv->vg->id)) &&
!dm_tree_find_node_by_uuid(dtree, uuid)) {
/* trims any UUID suffix (i.e. -cow) */
(void) dm_strncpy((char*)&id, uuid, 2 * sizeof(struct id) + 1);

354
lib/cache/lvmcache.c vendored
View File

@@ -88,6 +88,9 @@ static int _vgs_locked = 0;
static int _found_duplicate_vgnames = 0;
static int _outdated_warning = 0;
static const char *_scan_lock_global_file = DEFAULT_RUN_DIR "/scan_lock_global";
static int _scan_lock_global_file_exists = 0;
int lvmcache_init(struct cmd_context *cmd)
{
/*
@@ -316,7 +319,7 @@ static struct lvmcache_vginfo *_search_vginfos_list(const char *vgname, const ch
if (vgid) {
dm_list_iterate_items(vginfo, &_vginfos) {
if (!memcmp(vgid, vginfo->vgid, ID_LEN))
if (!strcmp(vgid, vginfo->vgid))
return vginfo;
}
} else {
@@ -328,21 +331,20 @@ static struct lvmcache_vginfo *_search_vginfos_list(const char *vgname, const ch
return NULL;
}
static struct lvmcache_vginfo *_vginfo_lookup(const char *vgname, const char *vgid_arg)
static struct lvmcache_vginfo *_vginfo_lookup(const char *vgname, const char *vgid)
{
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct lvmcache_vginfo *vginfo;
char id[ID_LEN + 1] __attribute__((aligned(8)));
/* In case vgid is not null terminated */
if (vgid_arg)
memcpy(vgid, vgid_arg, ID_LEN);
if (vgid) {
/* vgid not necessarily NULL-terminated */
(void) dm_strncpy(id, vgid, sizeof(id));
if (vgid_arg) {
if ((vginfo = dm_hash_lookup(_vgid_hash, vgid))) {
if ((vginfo = dm_hash_lookup(_vgid_hash, id))) {
if (vgname && strcmp(vginfo->vgname, vgname)) {
/* should never happen */
log_error(INTERNAL_ERROR "vginfo_lookup vgid %s has two names %s %s",
vgid, vginfo->vgname, vgname);
id, vginfo->vgname, vgname);
return NULL;
}
return vginfo;
@@ -364,7 +366,7 @@ static struct lvmcache_vginfo *_vginfo_lookup(const char *vgname, const char *vg
}
if (vgname && _found_duplicate_vgnames) {
if ((vginfo = _search_vginfos_list(vgname, vgid[0] ? vgid : NULL))) {
if ((vginfo = _search_vginfos_list(vgname, vgid))) {
if (vginfo->has_duplicate_local_vgname) {
log_debug("vginfo_lookup %s has_duplicate_local_vgname return none.", vgname);
return NULL;
@@ -451,18 +453,17 @@ bool lvmcache_has_duplicate_local_vgname(const char *vgid, const char *vgname)
* When the device being worked with is known, pass that dev as the second arg.
* This ensures that when duplicates exist, the wrong dev isn't used.
*/
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid_arg, struct device *dev, int valid_only)
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *dev, int valid_only)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct lvmcache_info *info;
char id[ID_LEN + 1] __attribute__((aligned(8)));
if (!_pvid_hash || !pvid_arg)
if (!_pvid_hash || !pvid)
return NULL;
/* For cases where pvid_arg is not null terminated. */
memcpy(pvid, pvid_arg, ID_LEN);
(void) dm_strncpy(id, pvid, sizeof(id));
if (!(info = dm_hash_lookup(_pvid_hash, pvid)))
if (!(info = dm_hash_lookup(_pvid_hash, id)))
return NULL;
/*
@@ -470,23 +471,13 @@ struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid_arg, struct devic
*/
if (dev && info->dev && (info->dev != dev)) {
log_debug_cache("Ignoring lvmcache info for dev %s because dev %s was requested for PVID %s.",
dev_name(info->dev), dev_name(dev), pvid);
dev_name(info->dev), dev_name(dev), id);
return NULL;
}
return info;
}
struct lvmcache_info *lvmcache_info_from_pv_id(const struct id *pv_id, struct device *dev, int valid_only)
{
/*
* Since we know that lvmcache_info_from_pvid directly above
* does not assume pvid_arg is null-terminated, we make an
* exception here and cast a struct id to char *.
*/
return lvmcache_info_from_pvid((const char *)pv_id, dev, valid_only);
}
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info)
{
return info->fmt;
@@ -499,18 +490,16 @@ const char *lvmcache_vgname_from_info(struct lvmcache_info *info)
return NULL;
}
static uint64_t _get_pvsummary_size(const char *pvid_arg)
static uint64_t _get_pvsummary_size(char *pvid)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
struct lvmcache_vginfo *vginfo;
struct pv_list *pvl;
/* In case pvid_arg is not null terminated. */
memcpy(pvid, pvid_arg, ID_LEN);
dm_list_iterate_items(vginfo, &_vginfos) {
dm_list_iterate_items(pvl, &vginfo->pvsummaries) {
if (!memcmp(pvid, &pvl->pv->id.uuid, ID_LEN))
(void) dm_strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s));
if (!strcmp(pvid_s, pvid))
return pvl->pv->size;
}
}
@@ -518,18 +507,16 @@ static uint64_t _get_pvsummary_size(const char *pvid_arg)
return 0;
}
static const char *_get_pvsummary_device_hint(const char *pvid_arg)
static const char *_get_pvsummary_device_hint(char *pvid)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
struct lvmcache_vginfo *vginfo;
struct pv_list *pvl;
/* In case pvid_arg is not null terminated. */
memcpy(pvid, pvid_arg, ID_LEN);
dm_list_iterate_items(vginfo, &_vginfos) {
dm_list_iterate_items(pvl, &vginfo->pvsummaries) {
if (!memcmp(pvid, &pvl->pv->id.uuid, ID_LEN))
(void) dm_strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s));
if (!strcmp(pvid_s, pvid))
return pvl->pv->device_hint;
}
}
@@ -537,18 +524,16 @@ static const char *_get_pvsummary_device_hint(const char *pvid_arg)
return NULL;
}
static const char *_get_pvsummary_device_id(const char *pvid_arg, const char **device_id_type)
static const char *_get_pvsummary_device_id(char *pvid, const char **device_id_type)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
struct lvmcache_vginfo *vginfo;
struct pv_list *pvl;
/* In case pvid_arg is not null terminated. */
memcpy(pvid, pvid_arg, ID_LEN);
dm_list_iterate_items(vginfo, &_vginfos) {
dm_list_iterate_items(pvl, &vginfo->pvsummaries) {
if (!memcmp(&pvid, &pvl->pv->id.uuid, ID_LEN)) {
(void) dm_strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s));
if (!strcmp(pvid_s, pvid)) {
*device_id_type = pvl->pv->device_id_type;
return pvl->pv->device_id;
}
@@ -570,7 +555,7 @@ int vg_has_duplicate_pvs(struct volume_group *vg)
dm_list_iterate_items(pvl, &vg->pvs) {
dm_list_iterate_items(devl, &_unused_duplicates) {
if (!memcmp(&pvl->pv->id.uuid, devl->dev->pvid, ID_LEN))
if (id_equal(&pvl->pv->id, (const struct id *)devl->dev->pvid))
return 1;
}
}
@@ -584,17 +569,15 @@ bool lvmcache_dev_is_unused_duplicate(struct device *dev)
static void _warn_unused_duplicates(struct cmd_context *cmd)
{
char pvid_dashed[64] __attribute__((aligned(8)));
char uuid[64] __attribute__((aligned(8)));
struct lvmcache_info *info;
struct device_list *devl;
struct id id;
dm_list_iterate_items(devl, &_unused_duplicates) {
memcpy(&id, devl->dev->pvid, ID_LEN);
if (!id_write_format(&id, pvid_dashed, sizeof(pvid_dashed)))
if (!id_write_format((const struct id *)devl->dev->pvid, uuid, sizeof(uuid)))
stack;
log_warn("WARNING: Not using device %s for PV %s.", dev_name(devl->dev), pvid_dashed);
log_warn("WARNING: Not using device %s for PV %s.", dev_name(devl->dev), uuid);
}
dm_list_iterate_items(devl, &_unused_duplicates) {
@@ -602,12 +585,11 @@ static void _warn_unused_duplicates(struct cmd_context *cmd)
if (!(info = lvmcache_info_from_pvid(devl->dev->pvid, NULL, 0)))
continue;
memcpy(&id, info->dev->pvid, ID_LEN);
if (!id_write_format(&id, pvid_dashed, sizeof(pvid_dashed)))
if (!id_write_format((const struct id *)info->dev->pvid, uuid, sizeof(uuid)))
stack;
log_warn("WARNING: PV %s prefers device %s because %s.",
pvid_dashed, dev_name(info->dev), info->dev->duplicate_prefer_reason);
uuid, dev_name(info->dev), info->dev->duplicate_prefer_reason);
}
}
@@ -657,7 +639,7 @@ static void _choose_duplicates(struct cmd_context *cmd,
struct dm_list *del_cache_devs,
struct dm_list *add_cache_devs)
{
const char *pvid;
char *pvid;
const char *reason;
const char *device_hint;
struct dm_list altdevs;
@@ -713,7 +695,7 @@ next:
*/
info = lvmcache_info_from_pvid(pvid, NULL, 0);
if (info && dev_is_md_component(cmd, info->dev, NULL, 1)) {
if (info && dev_is_md_component(info->dev, NULL, 1)) {
/* does not go in del_cache_devs which become unused_duplicates */
log_debug_cache("PV %s drop MD component from scan selection %s", pvid, dev_name(info->dev));
lvmcache_del(info);
@@ -721,7 +703,7 @@ next:
}
dm_list_iterate_items_safe(devl, devl_safe, &altdevs) {
if (dev_is_md_component(cmd, devl->dev, NULL, 1)) {
if (dev_is_md_component(devl->dev, NULL, 1)) {
log_debug_cache("PV %s drop MD component from scan duplicates %s", pvid, dev_name(devl->dev));
dm_list_del(&devl->list);
}
@@ -820,8 +802,8 @@ next:
same_id2 = !strcmp(idname2, device_id);
}
has_lv1 = dev_is_used_by_active_lv(cmd, dev1, NULL, NULL, NULL, NULL);
has_lv2 = dev_is_used_by_active_lv(cmd, dev2, NULL, NULL, NULL, NULL);
has_lv1 = (dev1->flags & DEV_USED_FOR_LV) ? 1 : 0;
has_lv2 = (dev2->flags & DEV_USED_FOR_LV) ? 1 : 0;
in_subsys1 = dev_subsystem_part_major(dt, dev1);
in_subsys2 = dev_subsystem_part_major(dt, dev2);
@@ -875,11 +857,6 @@ next:
dev_name(dev1), has_lv1 ? "is used for" : "is not used for",
dev_name(dev2), has_lv2 ? "is used for" : "is not used for");
free((void *)idname1);
free((void *)idname2);
idname1 = NULL;
idname2 = NULL;
change = 0;
if (prev_unchosen1 && !prev_unchosen2) {
@@ -1225,7 +1202,7 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd)
(unsigned long long)pvsize, (unsigned long long)devsize,
device_hint ?: "none", dev_name(dev));
if (dev_is_md_component(cmd, dev, NULL, 1)) {
if (dev_is_md_component(dev, NULL, 1)) {
log_debug("dropping PV from md component %s", dev_name(dev));
dev->flags &= ~DEV_SCAN_FOUND_LABEL;
/* lvmcache_del will also delete vginfo if info was last one */
@@ -1391,15 +1368,28 @@ int lvmcache_get_vgnameids(struct cmd_context *cmd,
return 1;
}
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pv_id, uint64_t *label_sector)
static struct device *_device_from_pvid(const struct id *pvid, uint64_t *label_sector)
{
struct lvmcache_info *info;
if ((info = lvmcache_info_from_pv_id(pv_id, NULL, 0))) {
if ((info = lvmcache_info_from_pvid((const char *) pvid, NULL, 0))) {
if (info->label && label_sector)
*label_sector = info->label->sector;
return info->dev;
}
return NULL;
}
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector)
{
struct device *dev;
dev = _device_from_pvid(pvid, label_sector);
if (dev)
return dev;
log_debug_devs("No device with uuid %s.", (const char *)pvid);
return NULL;
}
@@ -1408,7 +1398,7 @@ int lvmcache_pvid_in_unused_duplicates(const char *pvid)
struct device_list *devl;
dm_list_iterate_items(devl, &_unused_duplicates) {
if (!memcmp(devl->dev->pvid, pvid, ID_LEN))
if (!strncmp(devl->dev->pvid, pvid, ID_LEN))
return 1;
}
return 0;
@@ -1463,7 +1453,7 @@ void lvmcache_del_dev(struct device *dev)
{
struct lvmcache_info *info;
if ((info = lvmcache_info_from_pvid(dev->pvid, dev, 0)))
if ((info = lvmcache_info_from_pvid((const char *)dev->pvid, dev, 0)))
lvmcache_del(info);
}
@@ -1475,7 +1465,7 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info,
const char *vgid)
{
if (!vgid || !vginfo ||
!memcmp(vginfo->vgid, vgid, ID_LEN))
!strncmp(vginfo->vgid, vgid, ID_LEN))
return 1;
if (vginfo && *vginfo->vgid)
@@ -1486,8 +1476,7 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info,
return 1;
}
memset(vginfo->vgid, 0, sizeof(vginfo->vgid));
memcpy(vginfo->vgid, vgid, ID_LEN);
(void) dm_strncpy(vginfo->vgid, vgid, sizeof(vginfo->vgid));
if (!dm_hash_insert(_vgid_hash, vginfo->vgid, vginfo)) {
log_error("_lvmcache_update: vgid hash insertion failed: %s",
vginfo->vgid);
@@ -1508,8 +1497,8 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
const char *system_id,
const struct format_type *fmt)
{
char vgid_dashed[64] __attribute__((aligned(8)));
char other_dashed[64] __attribute__((aligned(8)));
char vgid_str[64] __attribute__((aligned(8)));
char other_str[64] __attribute__((aligned(8)));
struct lvmcache_vginfo *vginfo;
struct lvmcache_vginfo *other;
int vginfo_is_allowed;
@@ -1518,7 +1507,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
return 1;
if (!id_write_format((const struct id *)vgid, vgid_dashed, sizeof(vgid_dashed)))
if (!id_write_format((const struct id *)vgid, vgid_str, sizeof(vgid_str)))
stack;
/*
@@ -1564,7 +1553,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
* into the hash table.
*/
log_debug_cache("lvmcache adding vginfo for %s %s", vgname, vgid_dashed);
log_debug_cache("lvmcache adding vginfo for %s %s", vgname, vgid_str);
if (!(vginfo = zalloc(sizeof(*vginfo)))) {
log_error("lvmcache adding vg list alloc failed %s", vgname);
@@ -1594,7 +1583,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
if (!memcmp(other->vgid, vgid, ID_LEN)) {
/* shouldn't happen since we looked up by vgid above */
log_error(INTERNAL_ERROR "lvmcache_update_vgname %s %s %s %s",
vgname, vgid, other->vgname, other->vgid);
vgname, vgid_str, other->vgname, other->vgid);
free(vginfo->vgname);
free(vginfo);
return 0;
@@ -1604,7 +1593,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
other_is_allowed = is_system_id_allowed(cmd, other->system_id);
if (vginfo_is_allowed && other_is_allowed) {
if (!id_write_format((const struct id *)other->vgid, other_dashed, sizeof(other_dashed)))
if (!id_write_format((const struct id *)other->vgid, other_str, sizeof(other_str)))
stack;
vginfo->has_duplicate_local_vgname = 1;
@@ -1612,7 +1601,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
_found_duplicate_vgnames = 1;
log_warn("WARNING: VG name %s is used by VGs %s and %s.",
vgname, vgid_dashed, other_dashed);
vgname, vgid_str, other_str);
log_warn("Fix duplicate VG names with vgrename uuid, a device filter, or system IDs.");
}
@@ -1645,7 +1634,7 @@ static int _lvmcache_update_vgname(struct cmd_context *cmd,
info->vginfo = vginfo;
dm_list_add(&vginfo->infos, &info->list);
log_debug_cache("lvmcache %s: now in VG %s %s", dev_name(info->dev), vgname, vgid);
log_debug_cache("lvmcache %s: now in VG %s %s", dev_name(info->dev), vgname, vgid_str);
return 1;
}
@@ -1746,7 +1735,7 @@ static void _lvmcache_update_pvsummaries(struct lvmcache_vginfo *vginfo, struct
int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info *info, struct lvmcache_vgsummary *vgsummary)
{
const char *vgname = vgsummary->vgname;
const char *vgid = vgsummary->vgid;
const char *vgid = (char *)&vgsummary->vgid;
struct lvmcache_vginfo *vginfo;
if (!vgname && !info->vginfo) {
@@ -1935,21 +1924,21 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
int lvmcache_update_vg_from_write(struct volume_group *vg)
{
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct pv_list *pvl;
struct lvmcache_info *info;
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
struct lvmcache_vgsummary vgsummary = {
.vgname = vg->name,
.vgid = vg->id,
.vgstatus = vg->status,
.system_id = vg->system_id,
.lock_type = vg->lock_type
};
memcpy(vgid, &vg->id, ID_LEN);
memcpy(vgsummary.vgid, vgid, ID_LEN);
dm_list_iterate_items(pvl, &vg->pvs) {
if ((info = lvmcache_info_from_pv_id(&pvl->pv->id, pvl->pv->dev, 0)) &&
(void) dm_strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s));
/* FIXME Could pvl->pv->dev->pvid ever be different? */
if ((info = lvmcache_info_from_pvid(pvid_s, pvl->pv->dev, 0)) &&
!lvmcache_update_vgname_and_id(vg->cmd, info, &vgsummary))
return_0;
}
@@ -1970,23 +1959,20 @@ int lvmcache_update_vg_from_write(struct volume_group *vg)
int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct pv_list *pvl;
struct lvmcache_vginfo *vginfo;
struct lvmcache_info *info, *info2;
struct metadata_area *mda;
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
struct lvmcache_vgsummary vgsummary = {
.vgname = vg->name,
.vgid = vg->id,
.vgstatus = vg->status,
.system_id = vg->system_id,
.lock_type = vg->lock_type
};
memcpy(vgid, &vg->id, ID_LEN);
memcpy(vgsummary.vgid, vgid, ID_LEN);
if (!(vginfo = lvmcache_vginfo_from_vgname(vg->name, vgid))) {
if (!(vginfo = lvmcache_vginfo_from_vgname(vg->name, (const char *)&vg->id))) {
log_error(INTERNAL_ERROR "lvmcache_update_vg %s no vginfo", vg->name);
return 0;
}
@@ -2020,11 +2006,12 @@ int lvmcache_update_vg_from_read(struct volume_group *vg, unsigned precommitted)
}
dm_list_iterate_items(pvl, &vg->pvs) {
memcpy(pvid, &pvl->pv->id.uuid, ID_LEN);
(void) dm_strncpy(pvid_s, (char *) &pvl->pv->id, sizeof(pvid_s));
if (!(info = lvmcache_info_from_pvid(pvid, pvl->pv->dev, 0))) {
if (!(info = lvmcache_info_from_pvid(pvid_s, pvl->pv->dev, 0))) {
log_debug_cache("lvmcache_update_vg %s no info for %s %s",
vg->name, pvid,
vg->name,
(char *) &pvl->pv->id,
pvl->pv->dev ? dev_name(pvl->pv->dev) : "missing");
continue;
}
@@ -2148,30 +2135,23 @@ static struct lvmcache_info * _create_info(struct labeller *labeller, struct dev
}
struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *labeller,
const char *pvid_arg, struct device *dev, uint64_t label_sector,
const char *vgname, const char *vgid_arg, uint32_t vgstatus,
const char *pvid, struct device *dev, uint64_t label_sector,
const char *vgname, const char *vgid, uint32_t vgstatus,
int *is_duplicate)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char pvid_dashed[64] __attribute__((aligned(8)));
char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
char uuid[64] __attribute__((aligned(8)));
struct lvmcache_vgsummary vgsummary = { 0 };
struct lvmcache_info *info;
struct lvmcache_info *info_lookup;
struct device_list *devl;
int created = 0;
/* pvid_arg and vgid_arg may not be null terminated */
memcpy(pvid, pvid_arg, ID_LEN);
(void) dm_strncpy(pvid_s, pvid, sizeof(pvid_s));
if (vgid_arg)
memcpy(vgid, vgid_arg, ID_LEN);
if (!id_write_format((const struct id *)&pvid, pvid_dashed, sizeof(pvid_dashed)))
if (!id_write_format((const struct id *)&pvid_s, uuid, sizeof(uuid)))
stack;
log_debug_cache("Found PVID %s on %s", pvid, dev_name(dev));
/*
* Find existing info struct in _pvid_hash or create a new one.
*
@@ -2179,7 +2159,7 @@ struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *lab
* devs for the duplicate case is checked below.
*/
info = lvmcache_info_from_pvid(pvid, NULL, 0);
info = lvmcache_info_from_pvid(pvid_s, NULL, 0);
if (!info)
info = lvmcache_info_from_pvid(dev->pvid, NULL, 0);
@@ -2198,10 +2178,9 @@ struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *lab
if (!created) {
if (info->dev != dev) {
log_debug_cache("Saving initial duplicate device %s previously seen on %s with PVID %s.",
dev_name(dev), dev_name(info->dev), pvid_dashed);
dev_name(dev), dev_name(info->dev), uuid);
memset(&dev->pvid, 0, sizeof(dev->pvid));
memcpy(dev->pvid, pvid, ID_LEN);
strncpy(dev->pvid, pvid_s, sizeof(dev->pvid));
/* shouldn't happen */
if (dev_in_device_list(dev, &_initial_duplicates))
@@ -2228,10 +2207,10 @@ struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *lab
return NULL;
}
if (info->dev->pvid[0] && pvid[0] && memcmp(pvid, info->dev->pvid, ID_LEN)) {
if (info->dev->pvid[0] && pvid[0] && strcmp(pvid_s, info->dev->pvid)) {
/* This happens when running pvcreate on an existing PV. */
log_debug_cache("Changing pvid on dev %s from %s to %s",
dev_name(info->dev), info->dev->pvid, pvid);
dev_name(info->dev), info->dev->pvid, pvid_s);
}
if (info->label->labeller != labeller) {
@@ -2250,31 +2229,30 @@ struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *lab
* Add or update the _pvid_hash mapping, pvid to info.
*/
info_lookup = dm_hash_lookup(_pvid_hash, pvid);
if ((info_lookup == info) && !memcmp(info->dev->pvid, pvid, ID_LEN))
info_lookup = dm_hash_lookup(_pvid_hash, pvid_s);
if ((info_lookup == info) && !strcmp(info->dev->pvid, pvid_s))
goto update_vginfo;
if (info->dev->pvid[0])
dm_hash_remove(_pvid_hash, info->dev->pvid);
memset(info->dev->pvid, 0, sizeof(info->dev->pvid));
memcpy(info->dev->pvid, pvid, ID_LEN);
strncpy(info->dev->pvid, pvid_s, sizeof(info->dev->pvid));
if (!dm_hash_insert(_pvid_hash, pvid, info)) {
log_error("Adding pvid to hash failed %s", pvid);
if (!dm_hash_insert(_pvid_hash, pvid_s, info)) {
log_error("Adding pvid to hash failed %s", pvid_s);
return NULL;
}
update_vginfo:
vgsummary.vgstatus = vgstatus;
vgsummary.vgname = vgname;
if (vgid[0])
memcpy(vgsummary.vgid, vgid, ID_LEN);
if (vgid)
strncpy((char *)&vgsummary.vgid, vgid, sizeof(vgsummary.vgid));
if (!lvmcache_update_vgname_and_id(cmd, info, &vgsummary)) {
if (created) {
dm_hash_remove(_pvid_hash, pvid);
info->dev->pvid[0] = 0;
dm_hash_remove(_pvid_hash, pvid_s);
strcpy(info->dev->pvid, "");
free(info->label);
free(info);
}
@@ -2399,8 +2377,7 @@ int lvmcache_populate_pv_fields(struct lvmcache_info *info,
pv->fmt = info->fmt;
pv->size = info->device_size >> SECTOR_SHIFT;
pv->vg_name = FMT_TEXT_ORPHAN_VG_NAME;
memset(&pv->id, 0, sizeof(pv->id));
memcpy(&pv->id, &info->dev->pvid, ID_LEN);
memcpy(&pv->id, &info->dev->pvid, sizeof(pv->id));
if (!pv->size) {
log_error("PV %s size is zero.", dev_name(info->dev));
@@ -2667,8 +2644,9 @@ int lvmcache_lookup_mda(struct lvmcache_vgsummary *vgsummary)
vgsummary->creation_host = vginfo->creation_host;
vgsummary->vgstatus = vginfo->status;
vgsummary->seqno = vginfo->seqno;
memset(&vgsummary->vgid, 0, sizeof(vgsummary->vgid));
memcpy(&vgsummary->vgid, vginfo->vgid, ID_LEN);
/* vginfo->vgid has 1 extra byte then vgsummary->vgid */
memcpy(&vgsummary->vgid, vginfo->vgid, sizeof(vgsummary->vgid));
return 1;
}
}
@@ -2767,31 +2745,123 @@ bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const c
return true;
}
static uint64_t _max_metadata_size;
/*
* max_size_bytes and max_size_percent may come from different areas and
* different vgs because of different area sizes.
*/
static uint64_t _max_metadata_size_bytes;
static dm_percent_t _max_metadata_size_percent = DM_PERCENT_INVALID;
void lvmcache_save_metadata_size(uint64_t val)
void lvmcache_save_metadata_size_bytes(uint64_t val)
{
if (!_max_metadata_size)
_max_metadata_size = val;
else if (_max_metadata_size < val)
_max_metadata_size = val;
if (!_max_metadata_size_bytes)
_max_metadata_size_bytes = val;
else if (_max_metadata_size_bytes < val)
_max_metadata_size_bytes = val;
}
uint64_t lvmcache_max_metadata_size(void)
uint64_t lvmcache_max_metadata_size_bytes(void)
{
return _max_metadata_size;
return _max_metadata_size_bytes;
}
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, const char *pvid_arg)
/*
* TODO: enable/disable scan_lock_global with config setting:
* y: always use it
* n: never use it
* auto (default): use based on /run/lvm/scan_lock_global
*/
void lvmcache_save_metadata_size_percent(uint64_t meta_size, uint64_t mdah_size)
{
dm_percent_t pc = dm_make_percent(meta_size, mdah_size);
if (pc == DM_PERCENT_INVALID || pc == DM_PERCENT_FAILED ||
pc == DM_PERCENT_0 || pc == DM_PERCENT_1)
return;
if (_max_metadata_size_percent == DM_PERCENT_INVALID) {
_max_metadata_size_percent = pc;
return;
}
if (_max_metadata_size_percent < pc)
_max_metadata_size_percent = pc;
}
/*
* TODO: make the percent at which scan_lock_global is used
* configurable?
*/
#define SCAN_LOCK_GLOBAL_METADATA_PERCENT (DM_PERCENT_1 * 25)
void set_scan_lock_global(struct cmd_context *cmd)
{
FILE *fp;
if (_max_metadata_size_percent == DM_PERCENT_INVALID)
return;
if (_max_metadata_size_percent >= SCAN_LOCK_GLOBAL_METADATA_PERCENT) {
if (_scan_lock_global_file_exists)
return;
log_debug("Creating %s.", _scan_lock_global_file);
if (!(fp = fopen(_scan_lock_global_file, "w")))
return;
if (fclose(fp))
stack;
} else {
if (_scan_lock_global_file_exists) {
log_debug("Unlinking %s.", _scan_lock_global_file);
if (unlink(_scan_lock_global_file))
stack;
}
}
}
int do_scan_lock_global(struct cmd_context *cmd, int *gl_ex)
{
struct stat buf;
if (cmd->nolocking)
return 0;
/* global lock is already held */
if (cmd->lockf_global_ex)
return 0;
if (!stat(_scan_lock_global_file, &buf)) {
_scan_lock_global_file_exists = 1;
/*
* Tell the caller to use sh or ex. A command that may write
* vg metadata should use ex, otherwise sh.
*
* lockd_vg_default_sh/LOCKD_VG_SH is set for commands that
* do not modify vg metadata.
*
* FIXME: this variable/flag was previously used only for
* lvmlockd locking logic, but is now more general, so
* it should be renamed.
*/
if (cmd->lockd_vg_default_sh)
*gl_ex = 0;
else
*gl_ex = 1;
return 1;
}
return 0;
}
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct lvmcache_info *info;
/* In case pvid_arg is not null terminated. */
memcpy(pvid, pvid_arg, ID_LEN);
dm_list_iterate_items(info, &vginfo->infos) {
if (!memcmp(info->dev->pvid, pvid, ID_LEN))
if (!strcmp(info->dev->pvid, pvid))
return 1;
}
return 0;

16
lib/cache/lvmcache.h vendored
View File

@@ -47,7 +47,7 @@ struct lvmcache_vginfo;
*/
struct lvmcache_vgsummary {
const char *vgname;
char vgid[ID_LEN + 1];
struct id vgid;
uint64_t vgstatus;
char *creation_host;
const char *system_id;
@@ -96,10 +96,9 @@ struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname,
const char *vgid);
struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid);
struct lvmcache_info *lvmcache_info_from_pvid(const char *pvid, struct device *dev, int valid_only);
struct lvmcache_info *lvmcache_info_from_pv_id(const struct id *pv_id, struct device *dev, int valid_only);
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid);
const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgname);
struct device *lvmcache_device_from_pv_id(struct cmd_context *cmd, const struct id *pv_id, uint64_t *label_sector);
struct device *lvmcache_device_from_pvid(struct cmd_context *cmd, const struct id *pvid, uint64_t *label_sector);
const char *lvmcache_vgname_from_info(struct lvmcache_info *info);
const struct format_type *lvmcache_fmt_from_info(struct lvmcache_info *info);
@@ -182,10 +181,11 @@ int lvmcache_vg_is_foreign(struct cmd_context *cmd, const char *vgname, const ch
bool lvmcache_scan_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, const char *pvid_arg);
int lvmcache_vginfo_has_pvid(struct lvmcache_vginfo *vginfo, char *pvid);
uint64_t lvmcache_max_metadata_size(void);
void lvmcache_save_metadata_size(uint64_t val);
uint64_t lvmcache_max_metadata_size_bytes(void);
void lvmcache_save_metadata_size_bytes(uint64_t val);
void lvmcache_save_metadata_size_percent(uint64_t meta_size, uint64_t mdah_size);
int dev_in_device_list(struct device *dev, struct dm_list *head);
@@ -227,4 +227,8 @@ void lvmcache_extra_md_component_checks(struct cmd_context *cmd);
unsigned int lvmcache_vg_info_count(void);
void set_scan_lock_global(struct cmd_context *cmd);
int do_scan_lock_global(struct cmd_context *cmd, int *gl_ex);
#endif

View File

@@ -402,12 +402,15 @@ static void _init_logging(struct cmd_context *cmd)
reset_lvm_errno(1);
}
static int _check_disable_udev(const char *msg)
{
static int _check_disable_udev(const char *msg) {
if (getenv("DM_DISABLE_UDEV")) {
log_very_verbose("DM_DISABLE_UDEV environment variable set.");
log_very_verbose("Overriding configuration to use udev_rules=0, udev_sync=0, verify_udev_operations=1.");
log_very_verbose("LVM will %s.", msg);
log_very_verbose("DM_DISABLE_UDEV environment variable set. "
"Overriding configuration to use "
"udev_rules=0, udev_sync=0, verify_udev_operations=1.");
if (udev_is_running())
log_warn("Udev is running and DM_DISABLE_UDEV environment variable is set. "
"Bypassing udev, LVM will %s.", msg);
return 1;
}
@@ -560,7 +563,7 @@ static int _init_system_id(struct cmd_context *cmd)
static int _process_config(struct cmd_context *cmd)
{
mode_t old_umask;
const char *dev_ext_info_src = NULL;
const char *dev_ext_info_src;
const char *read_ahead;
struct stat st;
const struct dm_config_node *cn;
@@ -594,25 +597,14 @@ static int _process_config(struct cmd_context *cmd)
#endif
dev_ext_info_src = find_config_tree_str(cmd, devices_external_device_info_source_CFG, NULL);
if (dev_ext_info_src &&
strcmp(dev_ext_info_src, "none") &&
strcmp(dev_ext_info_src, "udev")) {
log_warn("WARNING: unknown external device info source, using none.");
dev_ext_info_src = NULL;
}
if (dev_ext_info_src && !strcmp(dev_ext_info_src, "udev")) {
if (udev_init_library_context()) {
init_external_device_info_source(DEV_EXT_UDEV);
} else {
log_warn("WARNING: failed to init udev for external device info, using none.");
dev_ext_info_src = NULL;
}
}
if (!dev_ext_info_src || !strcmp(dev_ext_info_src, "none"))
if (dev_ext_info_src && !strcmp(dev_ext_info_src, "none"))
init_external_device_info_source(DEV_EXT_NONE);
else if (dev_ext_info_src && !strcmp(dev_ext_info_src, "udev"))
init_external_device_info_source(DEV_EXT_UDEV);
else {
log_error("Invalid external device info source specification.");
return 0;
}
/* proc dir */
if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
@@ -974,13 +966,8 @@ static void _destroy_config(struct cmd_context *cmd)
/* CONFIG_FILE/CONFIG_MERGED_FILES */
if ((cft = remove_config_tree_by_source(cmd, CONFIG_MERGED_FILES)))
config_destroy(cft);
else if ((cft = remove_config_tree_by_source(cmd, CONFIG_FILE))) {
dm_list_iterate_items(cfl, &cmd->config_files) {
if (cfl->cft == cft)
dm_list_del(&cfl->list);
}
else if ((cft = remove_config_tree_by_source(cmd, CONFIG_FILE)))
config_destroy(cft);
}
dm_list_iterate_items(cfl, &cmd->config_files)
config_destroy(cfl->cft);
@@ -1026,10 +1013,16 @@ static int _init_dev_cache(struct cmd_context *cmd)
if (!dev_cache_init(cmd))
return_0;
if ((device_list_from_udev = find_config_tree_bool(cmd, devices_obtain_device_list_from_udev_CFG, NULL))) {
if (!udev_init_library_context())
device_list_from_udev = 0;
}
/*
* Override existing config and hardcode device_list_from_udev = 0 if:
* - udev is not running
* - udev is disabled using DM_DISABLE_UDEV environment variable
*/
if (_check_disable_udev("obtain device list by scanning device directory"))
device_list_from_udev = 0;
else
device_list_from_udev = udev_is_running() ?
find_config_tree_bool(cmd, devices_obtain_device_list_from_udev_CFG, NULL) : 0;
init_obtain_device_list_from_udev(device_list_from_udev);
@@ -1184,7 +1177,7 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
nr_filt++;
}
if (!(composite = composite_filter_create(nr_filt, filters)))
if (!(composite = composite_filter_create(nr_filt, 1, filters)))
goto_bad;
return composite;
@@ -1615,7 +1608,6 @@ struct cmd_context *create_toolcontext(unsigned is_clvmd,
cmd->handles_missing_pvs = 0;
cmd->handles_unknown_segments = 0;
cmd->hosttags = 0;
cmd->check_devs_used = 1;
dm_list_init(&cmd->arg_value_groups);
dm_list_init(&cmd->formats);
dm_list_init(&cmd->segtypes);

View File

@@ -30,7 +30,6 @@ struct config_info {
int verbose;
int silent;
int test;
int yes;
int syslog;
int activation;
int suffix;
@@ -193,10 +192,6 @@ struct cmd_context {
unsigned filter_nodata_only:1; /* only use filters that do not require data from the dev */
unsigned run_by_dmeventd:1; /* command is being run by dmeventd */
unsigned sysinit:1; /* --sysinit is used */
unsigned ignorelockingfailure:1; /* --ignorelockingfailure is used */
unsigned check_devs_used:1; /* check devs used by LVs */
unsigned print_device_id_not_found:1; /* print devices file entries not found */
unsigned ignore_device_name_mismatch:1; /* skip updating devices file names */
/*
* Devices and filtering.
@@ -261,6 +256,7 @@ struct cmd_context {
unsigned rand_seed;
struct dm_list pending_delete; /* list of LVs for removal */
struct dm_pool *pending_delete_mem; /* memory pool for pending deletes */
int early_lock_vg_mode;
};
/*

View File

@@ -501,9 +501,6 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
checksum_fn_t checksum_fn, uint32_t checksum,
int checksum_only, int no_dup_node_check)
{
char namebuf[NAME_LEN + 1] __attribute__((aligned(8)));
int namelen = 0;
int bad_name = 0;
char *fb, *fe;
int r = 0;
int sz, use_plain_read = 1;
@@ -551,23 +548,6 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
fb = buf;
if (!(dev->flags & DEV_REGULAR)) {
memcpy(namebuf, buf, NAME_LEN);
while (namebuf[namelen] && !isspace(namebuf[namelen]) && namebuf[namelen] != '{' && namelen < (NAME_LEN - 1))
namelen++;
namebuf[namelen] = '\0';
/*
* Check that the text metadata begins with a valid name.
*/
if (!validate_name(namebuf)) {
log_warn("WARNING: Metadata location on %s at offset %llu begins with invalid name.",
dev_name(dev), (unsigned long long)offset);
bad_name = 1;
}
}
/*
* The checksum passed in is the checksum from the mda_header
* preceding this metadata. They should always match.
@@ -577,13 +557,10 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
if (checksum_fn && checksum !=
(checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size),
(const uint8_t *)(fb + size), size2))) {
log_warn("WARNING: Checksum error on %s at offset %llu.", dev_name(dev), (unsigned long long)offset);
log_error("%s: Checksum error at offset %" PRIu64, dev_name(dev), (uint64_t) offset);
goto out;
}
if (bad_name)
goto out;
if (!checksum_only) {
fe = fb + size + size2;
if (no_dup_node_check) {

View File

@@ -238,10 +238,22 @@ cfg(devices_obtain_device_list_from_udev_CFG, "obtain_device_list_from_udev", de
"udev support for this setting to apply.\n")
cfg(devices_external_device_info_source_CFG, "external_device_info_source", devices_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE, vsn(2, 2, 116), NULL, 0, NULL,
"Enable device information from udev.\n"
"If set to \"udev\", lvm will supplement its own native device information\n"
"with information from libudev. This can potentially improve the detection\n"
"of MD component devices and multipath component devices.\n")
"Select an external device information source.\n"
"Some information may already be available in the system and LVM can\n"
"use this information to determine the exact type or use of devices it\n"
"processes. Using an existing external device information source can\n"
"speed up device processing as LVM does not need to run its own native\n"
"routines to acquire this information. For example, this information\n"
"is used to drive LVM filtering like MD component detection, multipath\n"
"component detection, partition detection and others.\n"
"#\n"
"Accepted values:\n"
" none\n"
" No external device information source is used.\n"
" udev\n"
" Reuse existing udev database records. Applicable only if LVM is\n"
" compiled with udev support.\n"
"#\n")
cfg(devices_hints_CFG, "hints", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_HINTS, vsn(2, 3, 2), NULL, 0, NULL,
"Use a local file to remember which devices have PVs on them.\n"
@@ -381,10 +393,6 @@ cfg(devices_scan_lvs_CFG, "scan_lvs", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEF
cfg(devices_multipath_component_detection_CFG, "multipath_component_detection", devices_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_MULTIPATH_COMPONENT_DETECTION, vsn(2, 2, 89), NULL, 0, NULL,
"Ignore devices that are components of DM multipath devices.\n")
cfg(devices_multipath_wwids_file_CFG, "multipath_wwids_file", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED | CFG_ALLOW_EMPTY, CFG_TYPE_STRING, DEFAULT_WWIDS_FILE, vsn(2, 3, 13), NULL, 0, NULL,
"The path to the multipath wwids file used for multipath component detection.\n"
"Set this to an empty string to disable the use of the multipath wwids file.\n")
cfg(devices_md_component_detection_CFG, "md_component_detection", devices_CFG_SECTION, 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"
@@ -799,7 +807,7 @@ cfg(allocation_vdo_write_policy_CFG, "vdo_write_policy", allocation_CFG_SECTION,
" Data which has not been flushed is not guaranteed to persist in this mode.\n")
cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_MAX_DISCARD, VDO_1ST_VSN, NULL, 0, NULL,
"Specified the maximum size of discard bio accepted, in 4096 byte blocks.\n"
"Specified te maximum size of discard bio accepted, in 4096 byte blocks.\n"
"I/O requests to a VDO volume are normally split into 4096-byte blocks,\n"
"and processed up to 2048 at a time. However, discard requests to a VDO volume\n"
"can be automatically split to a larger size, up to <max discard> 4096-byte blocks\n"
@@ -808,9 +816,6 @@ cfg(allocation_vdo_max_discard_CFG, "vdo_max_discard", allocation_CFG_SECTION, C
"increased latency for the individual discard requests.\n"
"The default and minimum is 1. The maximum is UINT_MAX / 4096.\n")
cfg(allocation_vdo_pool_header_size_CFG, "vdo_pool_header_size", allocation_CFG_SECTION, CFG_PROFILABLE | CFG_PROFILABLE_METADATA | CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_VDO_POOL_HEADER_SIZE_KB, vsn(2, 3, 12), NULL, 0, NULL,
"Specified the emptry header size in KiB at the front and end of vdo pool device.\n")
cfg(log_report_command_log_CFG, "report_command_log", log_CFG_SECTION, CFG_PROFILABLE | CFG_DEFAULT_COMMENTED | CFG_DISALLOW_INTERACTIVE, CFG_TYPE_BOOL, DEFAULT_COMMAND_LOG_REPORT, vsn(2, 2, 158), NULL, 0, NULL,
"Enable or disable LVM log reporting.\n"
"If enabled, LVM will collect a log of operations, messages,\n"

View File

@@ -42,7 +42,7 @@
#define DEFAULT_DEV_DIR "/dev"
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_SYSTEM_ID_SOURCE "none"
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 0
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 1
#define DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE "none"
#define DEFAULT_SYSFS_SCAN 1
#define DEFAULT_MD_COMPONENT_DETECTION 1
@@ -181,7 +181,8 @@
* VDO pool will reverve some sectors in the front and the back of pool device to avoid
* seeing same device twice in the system.
*/
#define DEFAULT_VDO_POOL_HEADER_SIZE_KB (512)
#define DEFAULT_VDO_POOL_HEADER_SIZE (1024) // 512KiB
#define DEFAULT_FSADM_PATH FSADM_PATH
@@ -327,6 +328,4 @@
#define DEFAULT_SEARCH_FOR_DEVNAMES "auto"
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
#endif /* _LVM_DEFAULTS_H */

View File

@@ -412,7 +412,7 @@ out:
return r;
}
int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor)
static int _get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor)
{
char path[PATH_MAX];
@@ -533,7 +533,7 @@ static int _get_vgid_and_lvid_for_dev(struct device *dev)
char uuid[DM_UUID_LEN];
size_t uuid_len;
if (!get_dm_uuid_from_sysfs(uuid, sizeof(uuid), (int) MAJOR(dev->dev), (int) MINOR(dev->dev)))
if (!_get_dm_uuid_from_sysfs(uuid, sizeof(uuid), (int) MAJOR(dev->dev), (int) MINOR(dev->dev)))
return_0;
uuid_len = strlen(uuid);
@@ -1139,7 +1139,7 @@ static int _insert(const char *path, const struct stat *info,
return 1;
}
void dev_cache_scan(struct cmd_context *cmd)
void dev_cache_scan(void)
{
log_debug_devs("Creating list of system devices.");
@@ -1147,8 +1147,7 @@ void dev_cache_scan(struct cmd_context *cmd)
_insert_dirs(&_cache.dirs);
if (cmd->check_devs_used)
(void) dev_cache_index_devs();
(void) dev_cache_index_devs();
}
int dev_cache_has_scanned(void)
@@ -1584,7 +1583,7 @@ struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t dev, struct
log_debug_devs("Device num not found in dev_cache repeat dev_cache_scan for %d:%d",
(int)MAJOR(dev), (int)MINOR(dev));
dev_cache_scan(cmd);
dev_cache_scan();
d = (struct device *) btree_lookup(_cache.devices, (uint32_t) dev);
if (!d)
@@ -1829,7 +1828,7 @@ int setup_devices_file(struct cmd_context *cmd)
* Add all system devices to dev-cache, and attempt to
* match all devices_file entries to dev-cache entries.
*/
static int _setup_devices(struct cmd_context *cmd, int no_file_match)
int setup_devices(struct cmd_context *cmd)
{
int file_exists;
int lock_mode = 0;
@@ -1954,14 +1953,7 @@ static int _setup_devices(struct cmd_context *cmd, int no_file_match)
* This will not open or read any devices, but may look at sysfs properties.
* This list of devs comes from looking /dev entries, or from asking libudev.
*/
dev_cache_scan(cmd);
/*
* The caller uses "no_file_match" if it wants to match specific devs
* itself, instead of matching everything in device_ids_match.
*/
if (no_file_match && cmd->enable_devices_file)
return 1;
dev_cache_scan();
/*
* Match entries from cmd->use_devices with device structs in dev-cache.
@@ -1971,16 +1963,6 @@ static int _setup_devices(struct cmd_context *cmd, int no_file_match)
return 1;
}
int setup_devices(struct cmd_context *cmd)
{
return _setup_devices(cmd, 0);
}
int setup_devices_no_file_match(struct cmd_context *cmd)
{
return _setup_devices(cmd, 1);
}
/*
* The alternative to setup_devices() when the command is interested
* in using only one PV.

View File

@@ -48,7 +48,7 @@ int dev_cache_exit(void);
*/
int dev_cache_check_for_open_devices(void);
void dev_cache_scan(struct cmd_context *cmd);
void dev_cache_scan(void);
int dev_cache_has_scanned(void);
int dev_cache_add_dir(const char *path);
@@ -68,16 +68,16 @@ struct dev_iter *dev_iter_create(struct dev_filter *f, int unused);
void dev_iter_destroy(struct dev_iter *iter);
struct device *dev_iter_get(struct cmd_context *cmd, struct dev_iter *iter);
void dev_reset_error_count(struct cmd_context *cmd);
void dev_cache_failed_path(struct device *dev, const char *path);
bool dev_cache_has_md_with_end_superblock(struct dev_types *dt);
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value);
int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
int setup_devices_file(struct cmd_context *cmd);
int setup_devices(struct cmd_context *cmd);
int setup_devices_no_file_match(struct cmd_context *cmd);
int setup_device(struct cmd_context *cmd, const char *devname);
#endif

View File

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

View File

@@ -17,7 +17,6 @@
#include "lib/device/dev-type.h"
#include "lib/mm/xlate.h"
#include "lib/misc/crc.h"
#include "lib/commands/toolcontext.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h> /* for MD detection using udev db records */
#include "lib/device/dev-ext-udev-constants.h"
@@ -145,16 +144,25 @@ static int _dev_has_ddf_magic(struct device *dev, uint64_t devsize_sectors, uint
return 0;
}
/*
* _udev_dev_is_md_component() only works if
* external_device_info_source="udev"
*
* but
*
* udev_dev_is_md_component() in dev-type.c only works if
* obtain_device_list_from_udev=1
*
* and neither of those config setting matches very well
* with what we're doing here.
*/
#ifdef UDEV_SYNC_SUPPORT
static int _dev_is_md_component_udev(struct device *dev)
static int _udev_dev_is_md_component(struct device *dev)
{
const char *value;
struct dev_ext *ext;
/*
* external_device_info_source="udev" enables these udev checks.
* external_device_info_source="none" disables them.
*/
if (!(ext = dev_ext_get(dev)))
return_0;
@@ -164,7 +172,7 @@ static int _dev_is_md_component_udev(struct device *dev)
return !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID);
}
#else
static int _dev_is_md_component_udev(struct device *dev)
static int _udev_dev_is_md_component(struct device *dev)
{
return 0;
}
@@ -173,16 +181,13 @@ static int _dev_is_md_component_udev(struct device *dev)
/*
* Returns -1 on error
*/
static int _dev_is_md_component_native(struct device *dev, uint64_t *offset_found, int full)
static int _native_dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
{
uint64_t size, sb_offset = 0;
int ret;
/* i/o layer has not been set up */
if (!scan_bcache) {
log_error(INTERNAL_ERROR "dev_is_md_component_native requires io layer.");
return -1;
}
if (!scan_bcache)
return -EAGAIN;
if (!dev_get_size(dev, &size)) {
stack;
@@ -290,20 +295,41 @@ out:
return ret;
}
int dev_is_md_component(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full)
int dev_is_md_component(struct device *dev, uint64_t *offset_found, int full)
{
if (_dev_is_md_component_native(dev, offset_found, full) == 1)
goto found;
int ret;
if (external_device_info_source() == DEV_EXT_UDEV) {
if (_dev_is_md_component_udev(dev) == 1)
goto found;
/*
* If non-native device status source is selected, use it
* only if offset_found is not requested as this
* information is not in udev db.
*/
if ((dev->ext.src == DEV_EXT_NONE) || offset_found) {
ret = _native_dev_is_md_component(dev, offset_found, full);
if (!full) {
if (!ret || (ret == -EAGAIN)) {
if (udev_dev_is_md_component(dev))
ret = 1;
}
}
if (ret && (ret != -EAGAIN))
dev->flags |= DEV_IS_MD_COMPONENT;
return ret;
}
return 0;
found:
dev->flags |= DEV_IS_MD_COMPONENT;
return 1;
if (dev->ext.src == DEV_EXT_UDEV) {
ret = _udev_dev_is_md_component(dev);
if (ret && (ret != -EAGAIN))
dev->flags |= DEV_IS_MD_COMPONENT;
return ret;
}
log_error(INTERNAL_ERROR "Missing hook for MD device recognition "
"using external device info source %s", dev_ext_name(dev));
return -1;
}
static int _md_sysfs_attribute_snprintf(char *path, size_t size,
@@ -526,8 +552,7 @@ int dev_is_md_with_end_superblock(struct dev_types *dt, struct device *dev)
#else
int dev_is_md_component(struct cmd_context *cmd __attribute__((unused)),
struct device *dev __attribute__((unused)),
int dev_is_md_component(struct device *dev __attribute__((unused)),
uint64_t *sb __attribute__((unused)))
{
return 0;

View File

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

View File

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

View File

@@ -22,7 +22,6 @@
#include "lib/device/bcache.h"
#include "lib/label/label.h"
#include "lib/commands/toolcontext.h"
#include "device_mapper/misc/dm-ioctl.h"
#ifdef BLKID_WIPING_SUPPORT
#include <blkid.h>
@@ -35,7 +34,6 @@
#include <libgen.h>
#include <ctype.h>
#include <dirent.h>
/*
* An nvme device has major number 259 (BLKEXT), minor number <minor>,
@@ -79,124 +77,6 @@ int dev_is_lv(struct device *dev)
return ret;
}
int dev_is_used_by_active_lv(struct cmd_context *cmd, struct device *dev, int *used_by_lv_count,
char **used_by_dm_name, char **used_by_vg_uuid, char **used_by_lv_uuid)
{
char holders_path[PATH_MAX];
char dm_dev_path[PATH_MAX];
char dm_uuid[DM_UUID_LEN];
struct stat info;
DIR *d;
struct dirent *dirent;
char *holder_name;
int dm_dev_major, dm_dev_minor;
size_t lvm_prefix_len = sizeof(UUID_PREFIX) - 1;
size_t lvm_uuid_len = sizeof(UUID_PREFIX) - 1 + 2 * ID_LEN;
size_t uuid_len;
int used_count = 0;
char *used_name = NULL;
char *used_vgid = NULL;
char *used_lvid = NULL;
/*
* An LV using this device will be listed as a "holder" in the device's
* sysfs "holders" dir.
*/
if (dm_snprintf(holders_path, sizeof(holders_path), "%sdev/block/%d:%d/holders/", dm_sysfs_dir(), (int) MAJOR(dev->dev), (int) MINOR(dev->dev)) < 0) {
log_error("%s: dm_snprintf failed for path to holders directory.", dev_name(dev));
return 0;
}
if (!(d = opendir(holders_path)))
return 0;
while ((dirent = readdir(d))) {
if (!strcmp(".", dirent->d_name) || !strcmp("..", dirent->d_name))
continue;
holder_name = dirent->d_name;
/*
* dirent->d_name is the dev name of the holder, e.g. "dm-1"
* from this name, create path "/dev/dm-1" to run stat on.
*/
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0)
continue;
/*
* stat "/dev/dm-1" which is the holder of the dev we're checking
* dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
*/
if (stat(dm_dev_path, &info))
continue;
dm_dev_major = (int)MAJOR(info.st_rdev);
dm_dev_minor = (int)MINOR(info.st_rdev);
if (dm_dev_major != cmd->dev_types->device_mapper_major)
continue;
/*
* if "dm-1" is a dm device, then check if it's an LVM LV
* by reading /sys/block/<holder_name>/dm/uuid and seeing
* if the uuid begins with LVM-
* UUID_PREFIX is "LVM-"
*/
dm_uuid[0] = '\0';
if (!get_dm_uuid_from_sysfs(dm_uuid, sizeof(dm_uuid), dm_dev_major, dm_dev_minor))
continue;
if (!strncmp(dm_uuid, UUID_PREFIX, 4))
used_count++;
if (used_by_dm_name && !used_name)
used_name = dm_pool_strdup(cmd->mem, holder_name);
if (!used_by_vg_uuid && !used_by_lv_uuid)
continue;
/*
* UUID for LV is either "LVM-<vg_uuid><lv_uuid>" or
* "LVM-<vg_uuid><lv_uuid>-<suffix>", where vg_uuid and lv_uuid
* has length of ID_LEN and suffix len is not restricted (only
* restricted by whole DM UUID max len).
*/
uuid_len = strlen(dm_uuid);
if (((uuid_len == lvm_uuid_len) ||
((uuid_len > lvm_uuid_len) && (dm_uuid[lvm_uuid_len] == '-'))) &&
!strncmp(dm_uuid, UUID_PREFIX, lvm_prefix_len)) {
if (used_by_vg_uuid && !used_vgid)
used_vgid = dm_pool_strndup(cmd->mem, dm_uuid + lvm_prefix_len, ID_LEN);
if (used_by_lv_uuid && !used_lvid)
used_lvid = dm_pool_strndup(cmd->mem, dm_uuid + lvm_prefix_len + ID_LEN, ID_LEN);
}
}
if (closedir(d))
log_sys_debug("closedir", holders_path);
if (used_by_lv_count)
*used_by_lv_count = used_count;
if (used_by_dm_name)
*used_by_dm_name = used_name;
if (used_by_vg_uuid)
*used_by_vg_uuid = used_vgid;
if (used_by_lv_uuid)
*used_by_lv_uuid = used_lvid;
if (used_count)
return 1;
return 0;
}
struct dev_types *create_dev_types(const char *proc_dir,
const struct dm_config_node *cn)
{
@@ -624,16 +504,12 @@ static int _has_partition_table(struct device *dev)
}
#ifdef UDEV_SYNC_SUPPORT
static int _dev_is_partitioned_udev(struct dev_types *dt, struct device *dev)
static int _udev_dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
struct dev_ext *ext;
struct udev_device *device;
const char *value;
/*
* external_device_info_source="udev" enables these udev checks.
* external_device_info_source="none" disables them.
*/
if (!(ext = dev_ext_get(dev)))
return_0;
@@ -664,20 +540,21 @@ static int _dev_is_partitioned_udev(struct dev_types *dt, struct device *dev)
return !strcmp(value, DEV_EXT_UDEV_DEVTYPE_DISK);
}
#else
static int _dev_is_partitioned_udev(struct dev_types *dt, struct device *dev)
static int _udev_dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
return 0;
}
#endif
static int _dev_is_partitioned_native(struct dev_types *dt, struct device *dev)
static int _native_dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
int r;
if (!scan_bcache) {
log_error(INTERNAL_ERROR "dev_is_partitioned_native requires i/o.");
return -1;
}
if (!scan_bcache)
return -EAGAIN;
if (!_is_partitionable(dt, dev))
return 0;
/* Unpartitioned DASD devices are not supported. */
if ((MAJOR(dev->dev) == dt->dasd_major) && dasd_is_cdl_formatted(dev))
@@ -688,20 +565,16 @@ static int _dev_is_partitioned_native(struct dev_types *dt, struct device *dev)
return r;
}
int dev_is_partitioned(struct cmd_context *cmd, struct device *dev)
int dev_is_partitioned(struct dev_types *dt, struct device *dev)
{
struct dev_types *dt = cmd->dev_types;
if (dev->ext.src == DEV_EXT_NONE)
return _native_dev_is_partitioned(dt, dev);
if (!_is_partitionable(dt, dev))
return 0;
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_partitioned(dt, dev);
if (_dev_is_partitioned_native(dt, dev) == 1)
return 1;
if (external_device_info_source() == DEV_EXT_UDEV) {
if (_dev_is_partitioned_udev(dt, dev) == 1)
return 1;
}
log_error(INTERNAL_ERROR "Missing hook for partition table recognition "
"using external device info source %s", dev_ext_name(dev));
return 0;
}
@@ -873,7 +746,7 @@ static int _blkid_wipe(blkid_probe probe, struct device *dev, const char *name,
const char *offset = NULL, *type = NULL, *magic = NULL,
*usage = NULL, *label = NULL, *uuid = NULL;
loff_t offset_value;
size_t len = 0;
size_t len;
if (!blkid_probe_lookup_value(probe, "TYPE", &type, NULL)) {
if (_type_in_flag_list(type, types_to_exclude))
@@ -1013,14 +886,14 @@ out:
#endif /* BLKID_WIPING_SUPPORT */
static int _wipe_signature(struct cmd_context *cmd, struct device *dev, const char *type, const char *name,
static int _wipe_signature(struct device *dev, const char *type, const char *name,
int wipe_len, int yes, force_t force, int *wiped,
int (*signature_detection_fn)(struct cmd_context *cmd, struct device *dev, uint64_t *offset_found, int full))
int (*signature_detection_fn)(struct device *dev, uint64_t *offset_found, int full))
{
int wipe;
uint64_t offset_found = 0;
wipe = signature_detection_fn(cmd, dev, &offset_found, 1);
wipe = signature_detection_fn(dev, &offset_found, 1);
if (wipe == -1) {
log_error("Fatal error while trying to detect %s on %s.",
type, name);
@@ -1048,7 +921,7 @@ static int _wipe_signature(struct cmd_context *cmd, struct device *dev, const ch
return 1;
}
static int _wipe_known_signatures_with_lvm(struct cmd_context *cmd, struct device *dev, const char *name,
static int _wipe_known_signatures_with_lvm(struct device *dev, const char *name,
uint32_t types_to_exclude __attribute__((unused)),
uint32_t types_no_prompt __attribute__((unused)),
int yes, force_t force, int *wiped)
@@ -1059,9 +932,9 @@ static int _wipe_known_signatures_with_lvm(struct cmd_context *cmd, struct devic
wiped = &wiped_tmp;
*wiped = 0;
if (!_wipe_signature(cmd, dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md_component) ||
!_wipe_signature(cmd, dev, "swap signature", name, 10, yes, force, wiped, dev_is_swap) ||
!_wipe_signature(cmd, dev, "LUKS signature", name, 8, yes, force, wiped, dev_is_luks))
if (!_wipe_signature(dev, "software RAID md superblock", name, 4, yes, force, wiped, dev_is_md_component) ||
!_wipe_signature(dev, "swap signature", name, 10, yes, force, wiped, dev_is_swap) ||
!_wipe_signature(dev, "LUKS signature", name, 8, yes, force, wiped, dev_is_luks))
return 0;
return 1;
@@ -1086,7 +959,7 @@ int wipe_known_signatures(struct cmd_context *cmd, struct device *dev,
"while LVM is not compiled with blkid wiping support.");
log_warn("WARNING: Falling back to native LVM signature detection.");
}
return _wipe_known_signatures_with_lvm(cmd, dev, name,
return _wipe_known_signatures_with_lvm(dev, name,
types_to_exclude,
types_no_prompt,
yes, force, wiped);
@@ -1276,3 +1149,147 @@ int dev_is_pmem(struct dev_types *dt, struct device *dev)
}
#endif
#ifdef UDEV_SYNC_SUPPORT
/*
* Udev daemon usually has 30s timeout to process each event by default.
* But still, that value can be changed in udev configuration and we
* don't have libudev API to read the actual timeout value used.
*/
/* FIXME: Is this long enough to wait for udev db to get initialized?
*
* Take also into consideration that this check is done for each
* device that is scanned so we don't want to wait for a long time
* if there's something wrong with udev, e.g. timeouts! With current
* libudev API, we can't recognize whether the event processing has
* not finished yet and it's still being processed or whether it has
* failed already due to timeout in udev - in both cases the
* udev_device_get_is_initialized returns 0.
*/
#define UDEV_DEV_IS_COMPONENT_ITERATION_COUNT 100
#define UDEV_DEV_IS_COMPONENT_USLEEP 100000
static struct udev_device *_udev_get_dev(struct device *dev)
{
struct udev *udev_context = udev_get_library_context();
struct udev_device *udev_device = NULL;
int initialized = 0;
unsigned i = 0;
if (!udev_context) {
log_warn("WARNING: No udev context available to check if device %s is multipath component.", dev_name(dev));
return NULL;
}
while (1) {
if (i >= UDEV_DEV_IS_COMPONENT_ITERATION_COUNT)
break;
if (udev_device)
udev_device_unref(udev_device);
if (!(udev_device = udev_device_new_from_devnum(udev_context, 'b', dev->dev))) {
log_warn("WARNING: Failed to get udev device handler for device %s.", dev_name(dev));
return NULL;
}
#ifdef HAVE_LIBUDEV_UDEV_DEVICE_GET_IS_INITIALIZED
if ((initialized = udev_device_get_is_initialized(udev_device)))
break;
#else
if ((initialized = (udev_device_get_property_value(udev_device, DEV_EXT_UDEV_DEVLINKS) != NULL)))
break;
#endif
log_debug("Device %s not initialized in udev database (%u/%u, %u microseconds).", dev_name(dev),
i + 1, UDEV_DEV_IS_COMPONENT_ITERATION_COUNT,
i * UDEV_DEV_IS_COMPONENT_USLEEP);
if (!udev_sleeping())
break;
usleep(UDEV_DEV_IS_COMPONENT_USLEEP);
i++;
}
if (!initialized) {
log_warn("WARNING: Device %s not initialized in udev database even after waiting %u microseconds.",
dev_name(dev), i * UDEV_DEV_IS_COMPONENT_USLEEP);
goto out;
}
out:
return udev_device;
}
int udev_dev_is_mpath_component(struct device *dev)
{
struct udev_device *udev_device;
const char *value;
int ret = 0;
if (!obtain_device_list_from_udev())
return 0;
if (!(udev_device = _udev_get_dev(dev)))
return 0;
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH)) {
log_debug("Device %s is multipath component based on blkid variable in udev db (%s=\"%s\").",
dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value);
ret = 1;
goto out;
}
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_MPATH_DEVICE_PATH);
if (value && !strcmp(value, "1")) {
log_debug("Device %s is multipath component based on multipath variable in udev db (%s=\"%s\").",
dev_name(dev), DEV_EXT_UDEV_MPATH_DEVICE_PATH, value);
ret = 1;
goto out;
}
out:
udev_device_unref(udev_device);
return ret;
}
int udev_dev_is_md_component(struct device *dev)
{
struct udev_device *udev_device;
const char *value;
int ret = 0;
if (!obtain_device_list_from_udev())
return 0;
if (!(udev_device = _udev_get_dev(dev)))
return 0;
value = udev_device_get_property_value(udev_device, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_SW_RAID)) {
log_debug("Device %s is md raid component based on blkid variable in udev db (%s=\"%s\").",
dev_name(dev), DEV_EXT_UDEV_BLKID_TYPE, value);
dev->flags |= DEV_IS_MD_COMPONENT;
ret = 1;
goto out;
}
out:
udev_device_unref(udev_device);
return ret;
}
#else
int udev_dev_is_mpath_component(struct device *dev)
{
return 0;
}
int udev_dev_is_md_component(struct device *dev)
{
return 0;
}
#endif

View File

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

View File

@@ -205,7 +205,4 @@ void dev_destroy_file(struct device *dev);
/* Return a valid device name from the alias list; NULL otherwise */
const char *dev_name_confirmed(struct device *dev, int quiet);
int dev_mpath_init(const char *config_wwids_file);
void dev_mpath_exit(void);
#endif

View File

@@ -180,7 +180,7 @@ void free_dids(struct dm_list *ids)
}
}
int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize)
static int _read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize)
{
char path[PATH_MAX];
dev_t devt = dev->dev;
@@ -246,7 +246,7 @@ static int _dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, cons
char sysbuf[PATH_MAX] = { 0 };
const char *idname;
if (!read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)))
if (!_read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)))
return 0;
if (!_dm_uuid_has_prefix(sysbuf, "mpath-"))
@@ -265,7 +265,7 @@ static int _dev_has_crypt_uuid(struct cmd_context *cmd, struct device *dev, cons
char sysbuf[PATH_MAX] = { 0 };
const char *idname;
if (!read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)))
if (!_read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)))
return 0;
if (!_dm_uuid_has_prefix(sysbuf, "CRYPT-"))
@@ -284,7 +284,7 @@ static int _dev_has_lvmlv_uuid(struct cmd_context *cmd, struct device *dev, cons
char sysbuf[PATH_MAX] = { 0 };
const char *idname;
if (!read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)))
if (!_read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)))
return 0;
if (!_dm_uuid_has_prefix(sysbuf, "LVM-"))
@@ -304,37 +304,29 @@ const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, u
const char *idname = NULL;
if (idtype == DEV_ID_TYPE_SYS_WWID) {
read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf));
_read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf));
if (!sysbuf[0])
read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf));
/* scsi_debug wwid begins "t10.Linux scsi_debug ..." */
if (strstr(sysbuf, "scsi_debug"))
sysbuf[0] = '\0';
/* qemu wwid begins "t10.ATA QEMU HARDDISK ..." */
if (strstr(sysbuf, "QEMU HARDDISK"))
sysbuf[0] = '\0';
_read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf));
}
else if (idtype == DEV_ID_TYPE_SYS_SERIAL)
read_sys_block(cmd, dev, "device/serial", sysbuf, sizeof(sysbuf));
_read_sys_block(cmd, dev, "device/serial", sysbuf, sizeof(sysbuf));
else if (idtype == DEV_ID_TYPE_MPATH_UUID)
read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf));
_read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf));
else if (idtype == DEV_ID_TYPE_CRYPT_UUID)
read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf));
_read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf));
else if (idtype == DEV_ID_TYPE_LVMLV_UUID)
read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf));
_read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf));
else if (idtype == DEV_ID_TYPE_MD_UUID)
read_sys_block(cmd, dev, "md/uuid", sysbuf, sizeof(sysbuf));
_read_sys_block(cmd, dev, "md/uuid", sysbuf, sizeof(sysbuf));
else if (idtype == DEV_ID_TYPE_LOOP_FILE) {
read_sys_block(cmd, dev, "loop/backing_file", sysbuf, sizeof(sysbuf));
_read_sys_block(cmd, dev, "loop/backing_file", sysbuf, sizeof(sysbuf));
/* if backing file is deleted, fall back to devname */
if (strstr(sysbuf, "(deleted)"))
sysbuf[0] = '\0';
@@ -372,17 +364,17 @@ static int _dev_has_stable_id(struct cmd_context *cmd, struct device *dev)
return 1;
}
if (read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf)))
if (_read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf)))
return 1;
if (read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf)))
if (_read_sys_block(cmd, dev, "wwid", sysbuf, sizeof(sysbuf)))
return 1;
if (read_sys_block(cmd, dev, "device/serial", sysbuf, sizeof(sysbuf)))
if (_read_sys_block(cmd, dev, "device/serial", sysbuf, sizeof(sysbuf)))
return 1;
if ((MAJOR(dev->dev) == cmd->dev_types->device_mapper_major)) {
if (!read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)))
if (!_read_sys_block(cmd, dev, "dm/uuid", sysbuf, sizeof(sysbuf)))
goto_out;
if (_dm_uuid_has_prefix(sysbuf, "mpath-"))
@@ -394,11 +386,11 @@ static int _dev_has_stable_id(struct cmd_context *cmd, struct device *dev)
}
if ((MAJOR(dev->dev) == cmd->dev_types->md_major) &&
read_sys_block(cmd, dev, "md/uuid", sysbuf, sizeof(sysbuf)))
_read_sys_block(cmd, dev, "md/uuid", sysbuf, sizeof(sysbuf)))
return 1;
if ((MAJOR(dev->dev) == cmd->dev_types->loop_major) &&
read_sys_block(cmd, dev, "loop/backing_file", sysbuf, sizeof(sysbuf)))
_read_sys_block(cmd, dev, "loop/backing_file", sysbuf, sizeof(sysbuf)))
return 1;
out:
/* DEV_ID_TYPE_DEVNAME would be used for this dev. */
@@ -867,7 +859,7 @@ struct dev_use *get_du_for_pvid(struct cmd_context *cmd, const char *pvid)
dm_list_iterate_items(du, &cmd->use_devices) {
if (!du->pvid)
continue;
if (!memcmp(du->pvid, pvid, ID_LEN))
if (!strcmp(du->pvid, pvid))
return du;
}
return NULL;
@@ -1138,10 +1130,8 @@ id_done:
du_pvid->dev ? dev_name(du_pvid->dev) : "none", du_pvid->idname,
pvid);
if (!cmd->current_settings.yes &&
yes_no_prompt("Add device with duplicate PV to devices file?") == 'n') {
if (yes_no_prompt("Add device with duplicate PV to devices file?") == 'n') {
log_print("Device not added.");
free((void *)check_idname);
return 1;
}
}
@@ -1191,7 +1181,7 @@ id_done:
if (!label_scan_open(du_devid->dev))
log_warn("Cannot open %s", dev_name(du_devid->dev));
if (dev_is_partitioned(cmd, du_devid->dev)) {
if (dev_is_partitioned(cmd->dev_types, du_devid->dev)) {
/* Check if existing entry is whole device and new entry is a partition of it. */
ret1 = dev_get_primary_dev(cmd->dev_types, dev, &devt1);
if ((ret1 == 2) && (devt1 == du_devid->dev->dev))
@@ -1325,7 +1315,7 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
du->dev = dev;
dev->id = id;
dev->flags |= DEV_MATCHED_USE_ID;
log_debug("Match device_id %s %s to %s",
log_debug("compare match %s %s to %s",
idtype_to_str(du->idtype), du->idname, dev_name(dev));
return 1;
} else {
@@ -1371,7 +1361,7 @@ static int _match_du_to_dev(struct cmd_context *cmd, struct dev_use *du, struct
du->dev = dev;
dev->id = id;
dev->flags |= DEV_MATCHED_USE_ID;
log_debug("Match device_id %s %s to %s",
log_debug("compare match %s %s to %s",
idtype_to_str(du->idtype), du->idname, dev_name(dev));
return 1;
}
@@ -1512,9 +1502,6 @@ void device_ids_match(struct cmd_context *cmd)
dev_iter_destroy(iter);
}
if (!cmd->print_device_id_not_found)
return;
/*
* Look for entries in devices file for which we found no device.
*/
@@ -1640,15 +1627,6 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
}
}
/*
* Avoid thrashing changes to the devices file during
* startup due to device names that are still being
* established. Commands that may run during startup
* should set this flag.
*/
if (cmd->ignore_device_name_mismatch)
continue;
if (!du->devname || strcmp(dev_name(du->dev), du->devname)) {
log_warn("Device %s has updated name (devices file %s)",
dev_name(du->dev), du->devname ?: "none");
@@ -1696,7 +1674,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
/*
* A good match based on pvid.
*/
if (dev->pvid[0] && !memcmp(dev->pvid, du->pvid, ID_LEN)) {
if (dev->pvid[0] && !strcmp(dev->pvid, du->pvid)) {
const char *devname = dev_name(dev);
if (strcmp(devname, du->idname)) {
@@ -2268,7 +2246,7 @@ static int _lock_devices_file(struct cmd_context *cmd, int mode, int nonblock, i
fd = open(_devices_lockfile, O_CREAT|O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0) {
log_debug("lock_devices_file open errno %d", errno);
if (cmd->sysinit || cmd->ignorelockingfailure)
if (cmd->sysinit)
return 1;
return 0;
}
@@ -2284,7 +2262,7 @@ static int _lock_devices_file(struct cmd_context *cmd, int mode, int nonblock, i
if (close(fd))
stack;
if (cmd->sysinit || cmd->ignorelockingfailure)
if (cmd->sysinit)
return 1;
return 0;
}

View File

@@ -52,6 +52,4 @@ void devices_file_exit(struct cmd_context *cmd);
void unlink_searched_devnames(struct cmd_context *cmd);
int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize);
#endif

View File

@@ -21,24 +21,29 @@
static int _and_p(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
struct dev_filter **filters;
int ret = 1;
dev_ext_enable(dev, external_device_info_source());
int ret;
for (filters = (struct dev_filter **) f->private; *filters; ++filters) {
if (use_filter_name && strcmp((*filters)->name, use_filter_name))
continue;
ret = (*filters)->passes_filter(cmd, *filters, dev, use_filter_name);
if (!ret) {
ret = 0; /* No 'stack': a filter, not an error. */
break;
}
if (!ret)
return 0; /* No 'stack': a filter, not an error. */
}
return 1;
}
static int _and_p_with_dev_ext_info(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
int r;
dev_ext_enable(dev, external_device_info_source());
r = _and_p(cmd, f, dev, use_filter_name);
dev_ext_disable(dev);
return ret;
return r;
}
static void _composite_destroy(struct dev_filter *f)
@@ -67,7 +72,7 @@ static void _wipe(struct cmd_context *cmd, struct dev_filter *f, struct device *
}
}
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
struct dev_filter *composite_filter_create(int n, int use_dev_ext_info, struct dev_filter **filters)
{
struct dev_filter **filters_copy, *cft;
@@ -88,7 +93,7 @@ struct dev_filter *composite_filter_create(int n, struct dev_filter **filters)
return NULL;
}
cft->passes_filter = _and_p;
cft->passes_filter = use_dev_ext_info ? _and_p_with_dev_ext_info : _and_p;
cft->destroy = _composite_destroy;
cft->wipe = _wipe;
cft->use_count = 0;

View File

@@ -98,7 +98,7 @@ static int _passes_md_filter(struct cmd_context *cmd, struct dev_filter *f __att
if (!md_filtering())
return 1;
ret = dev_is_md_component(cmd, dev, NULL, cmd->use_full_md_check);
ret = dev_is_md_component(dev, NULL, cmd->use_full_md_check);
if (ret == -EAGAIN) {
/* let pass, call again after scan */

View File

@@ -15,17 +15,335 @@
#include "base/memory/zalloc.h"
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/activate/activate.h"
#include "lib/commands/toolcontext.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "lib/device/dev-ext-udev-constants.h"
#endif
#ifdef __linux__
#include <dirent.h>
#define MPATH_PREFIX "mpath-"
struct mpath_priv {
struct dm_pool *mem;
struct dev_filter f;
struct dev_types *dt;
struct dm_hash_table *hash;
};
/*
* given "/dev/foo" return "foo"
*/
static const char *_get_sysfs_name(struct device *dev)
{
const char *name;
if (!(name = strrchr(dev_name(dev), '/'))) {
log_error("Cannot find '/' in device name.");
return NULL;
}
name++;
if (!*name) {
log_error("Device name is not valid.");
return NULL;
}
return name;
}
/*
* given major:minor
* readlink translates /sys/dev/block/major:minor to /sys/.../foo
* from /sys/.../foo return "foo"
*/
static const char *_get_sysfs_name_by_devt(const char *sysfs_dir, dev_t devno,
char *buf, size_t buf_size)
{
const char *name;
char path[PATH_MAX];
int size;
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d", sysfs_dir,
(int) MAJOR(devno), (int) MINOR(devno)) < 0) {
log_error("Sysfs path string is too long.");
return NULL;
}
if ((size = readlink(path, buf, buf_size - 1)) < 0) {
log_sys_error("readlink", path);
return NULL;
}
buf[size] = '\0';
if (!(name = strrchr(buf, '/'))) {
log_error("Cannot find device name in sysfs path.");
return NULL;
}
name++;
return name;
}
static int _get_sysfs_string(const char *path, char *buffer, int max_size)
{
FILE *fp;
int r = 0;
if (!(fp = fopen(path, "r"))) {
log_sys_error("fopen", path);
return 0;
}
if (!fgets(buffer, max_size, fp))
log_sys_error("fgets", path);
else
r = 1;
if (fclose(fp))
log_sys_error("fclose", path);
return r;
}
static int _get_sysfs_dm_mpath(struct dev_types *dt, const char *sysfs_dir, const char *holder_name)
{
char path[PATH_MAX];
char buffer[128];
if (dm_snprintf(path, sizeof(path), "%sblock/%s/dm/uuid", sysfs_dir, holder_name) < 0) {
log_error("Sysfs path string is too long.");
return 0;
}
buffer[0] = '\0';
if (!_get_sysfs_string(path, buffer, sizeof(buffer)))
return_0;
if (!strncmp(buffer, MPATH_PREFIX, 6))
return 1;
return 0;
}
static int _get_holder_name(const char *dir, char *name, int max_size)
{
struct dirent *d;
DIR *dr;
int r = 0;
if (!(dr = opendir(dir))) {
log_sys_error("opendir", dir);
return 0;
}
*name = '\0';
while ((d = readdir(dr))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
/* There should be only one holder if it is multipath */
if (*name) {
r = 0;
break;
}
strncpy(name, d->d_name, max_size);
r = 1;
}
if (closedir(dr))
log_sys_debug("closedir", dir);
return r;
}
#ifdef UDEV_SYNC_SUPPORT
static int _udev_dev_is_mpath_component(struct device *dev)
{
const char *value;
struct dev_ext *ext;
if (!(ext = dev_ext_get(dev)))
return_0;
value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_BLKID_TYPE);
if (value && !strcmp(value, DEV_EXT_UDEV_BLKID_TYPE_MPATH))
return 1;
value = udev_device_get_property_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_MPATH_DEVICE_PATH);
if (value && !strcmp(value, "1"))
return 1;
return 0;
}
#else
static int _udev_dev_is_mpath_component(struct device *dev)
{
return 0;
}
#endif
static int _native_dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
{
struct mpath_priv *mp = (struct mpath_priv *) f->private;
struct dev_types *dt = mp->dt;
const char *part_name;
const char *name; /* e.g. "sda" for "/dev/sda" */
char link_path[PATH_MAX]; /* some obscure, unpredictable sysfs path */
char holders_path[PATH_MAX]; /* e.g. "/sys/block/sda/holders/" */
char dm_dev_path[PATH_MAX]; /* e.g. "/dev/dm-1" */
char holder_name[256]; /* e.g. "dm-1" */
const char *sysfs_dir = dm_sysfs_dir();
int dev_major = MAJOR(dev->dev);
int dev_minor = MINOR(dev->dev);
int dm_dev_major;
int dm_dev_minor;
struct stat info;
dev_t primary_dev;
long look;
/* Limit this filter to SCSI or NVME devices */
if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
return 0;
switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
case 2: /* The dev is partition. */
part_name = dev_name(dev); /* name of original dev for log_debug msg */
/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
return_0;
log_debug_devs("%s: Device is a partition, using primary "
"device %s for mpath component detection",
part_name, name);
break;
case 1: /* The dev is already a primary dev. Just continue with the dev. */
/* gets "foo" for "/dev/foo" */
if (!(name = _get_sysfs_name(dev)))
return_0;
break;
default: /* 0, error. */
log_warn("Failed to get primary device for %d:%d.", dev_major, dev_minor);
return 0;
}
if (dm_snprintf(holders_path, sizeof(holders_path), "%sblock/%s/holders", sysfs_dir, name) < 0) {
log_warn("Sysfs path to check mpath is too long.");
return 0;
}
/* also will filter out partitions */
if (stat(holders_path, &info))
return 0;
if (!S_ISDIR(info.st_mode)) {
log_warn("Path %s is not a directory.", holders_path);
return 0;
}
/*
* If holders dir contains an entry such as "dm-1", then this sets
* holder_name to "dm-1".
*
* If holders dir is empty, return 0 (this is generally where
* devs that are not mpath components return.)
*/
if (!_get_holder_name(holders_path, holder_name, sizeof(holder_name)))
return 0;
if (dm_snprintf(dm_dev_path, sizeof(dm_dev_path), "%s/%s", cmd->dev_dir, holder_name) < 0) {
log_warn("dm device path to check mpath is too long.");
return 0;
}
/*
* stat "/dev/dm-1" which is the holder of the dev we're checking
* dm_dev_major:dm_dev_minor come from stat("/dev/dm-1")
*/
if (stat(dm_dev_path, &info)) {
log_debug("filter-mpath %s holder %s stat result %d",
dev_name(dev), dm_dev_path, errno);
return 0;
}
dm_dev_major = (int)MAJOR(info.st_rdev);
dm_dev_minor = (int)MINOR(info.st_rdev);
if (dm_dev_major != dt->device_mapper_major) {
log_debug_devs("filter-mpath %s holder %s %d:%d does not have dm major",
dev_name(dev), dm_dev_path, dm_dev_major, dm_dev_minor);
return 0;
}
/*
* Save the result of checking that "/dev/dm-1" is an mpath device
* to avoid repeating it for each path component.
* The minor number of "/dev/dm-1" is added to the hash table with
* const value 2 meaning that dm minor 1 (for /dev/dm-1) is a multipath dev
* and const value 1 meaning that dm minor 1 is not a multipath dev.
*/
look = (long) dm_hash_lookup_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor));
if (look > 0) {
log_debug_devs("filter-mpath %s holder %s %u:%u already checked as %sbeing mpath.",
dev_name(dev), holder_name, dm_dev_major, dm_dev_minor, (look > 1) ? "" : "not ");
return (look > 1) ? 1 : 0;
}
/*
* Returns 1 if /sys/block/<holder_name>/dm/uuid indicates that
* <holder_name> is a dm device with dm uuid prefix mpath-.
* When true, <holder_name> will be something like "dm-1".
*
* (Is a hash table worth it to avoid reading one sysfs file?)
*/
if (_get_sysfs_dm_mpath(dt, sysfs_dir, holder_name)) {
log_debug_devs("filter-mpath %s holder %s %u:%u ignore mpath component",
dev_name(dev), holder_name, dm_dev_major, dm_dev_minor);
(void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)2);
return 1;
}
(void) dm_hash_insert_binary(mp->hash, &dm_dev_minor, sizeof(dm_dev_minor), (void*)1);
return 0;
}
static int _dev_is_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
return _native_dev_is_mpath_component(cmd, f, dev);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_dev_is_mpath_component(dev);
log_error(INTERNAL_ERROR "Missing hook for mpath recognition "
"using external device info source %s", dev_ext_name(dev));
return 0;
}
#define MSG_SKIPPING "%s: Skipping mpath component device"
static int _ignore_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
dev->filtered_flags &= ~DEV_FILTERED_MPATH_COMPONENT;
if (dev_is_mpath_component(cmd, dev)) {
log_debug_devs("%s: Skipping mpath component device", dev_name(dev));
if (_dev_is_mpath_component(cmd, f, dev) == 1) {
if (dev->ext.src == DEV_EXT_NONE)
log_debug_devs(MSG_SKIPPING, dev_name(dev));
else
log_debug_devs(MSG_SKIPPING " [%s:%p]", dev_name(dev),
dev_ext_name(dev), dev->ext.handle);
dev->filtered_flags |= DEV_FILTERED_MPATH_COMPONENT;
return 0;
}
@@ -35,33 +353,59 @@ static int _ignore_mpath_component(struct cmd_context *cmd, struct dev_filter *f
static void _destroy(struct dev_filter *f)
{
struct mpath_priv *mp = (struct mpath_priv*) f->private;
if (f->use_count)
log_error(INTERNAL_ERROR "Destroying mpath filter while in use %u times.", f->use_count);
dm_hash_destroy(mp->hash);
dm_pool_destroy(mp->mem);
}
struct dev_filter *mpath_filter_create(struct dev_types *dt)
{
struct dev_filter *f;
const char *sysfs_dir = dm_sysfs_dir();
struct mpath_priv *mp;
struct dm_pool *mem;
struct dm_hash_table *hash;
if (!*sysfs_dir) {
log_verbose("No proc filesystem found: skipping multipath filter");
return NULL;
}
if (!(f = zalloc(sizeof(*f)))) {
log_error("mpath filter allocation failed");
if (!(hash = dm_hash_create(110))) {
log_error("mpath hash table creation failed.");
return NULL;
}
f->passes_filter = _ignore_mpath_component;
f->destroy = _destroy;
f->use_count = 0;
f->name = "mpath";
if (!(mem = dm_pool_create("mpath", 256))) {
log_error("mpath pool creation failed.");
dm_hash_destroy(hash);
return NULL;
}
if (!(mp = dm_pool_zalloc(mem, sizeof(*mp)))) {
log_error("mpath filter allocation failed.");
goto bad;
}
mp->f.passes_filter = _ignore_mpath_component;
mp->f.destroy = _destroy;
mp->f.use_count = 0;
mp->f.private = mp;
mp->f.name = "mpath";
mp->dt = dt;
mp->mem = mem;
mp->hash = hash;
log_debug_devs("mpath filter initialised.");
return f;
return &mp->f;
bad:
dm_pool_destroy(mem);
dm_hash_destroy(hash);
return NULL;
}
#else

View File

@@ -22,6 +22,7 @@
static int _passes_partitioned_filter(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
struct dev_types *dt = (struct dev_types *) f->private;
int ret;
if (cmd->filter_nodata_only)
@@ -29,7 +30,7 @@ static int _passes_partitioned_filter(struct cmd_context *cmd, struct dev_filter
dev->filtered_flags &= ~DEV_FILTERED_PARTITIONED;
ret = dev_is_partitioned(cmd, dev);
ret = dev_is_partitioned(dt, dev);
if (ret == -EAGAIN) {
/* let pass, call again after scan */
@@ -71,6 +72,7 @@ struct dev_filter *partitioned_filter_create(struct dev_types *dt)
f->passes_filter = _passes_partitioned_filter;
f->destroy = _partitioned_filter_destroy;
f->use_count = 0;
f->private = dt;
f->name = "partitioned";
log_debug_devs("Partitioned filter initialised.");

View File

@@ -16,6 +16,10 @@
#include "lib/misc/lib.h"
#include "lib/filters/filter.h"
#include "lib/activate/activate.h"
#ifdef UDEV_SYNC_SUPPORT
#include <libudev.h>
#include "lib/device/dev-ext-udev-constants.h"
#endif
struct filter_data {
filter_mode_t mode;
@@ -24,7 +28,7 @@ struct filter_data {
static const char *_too_small_to_hold_pv_msg = "Too small to hold a PV";
static int _check_pv_min_size(struct device *dev)
static int _native_check_pv_min_size(struct device *dev)
{
uint64_t size;
int ret = 0;
@@ -46,6 +50,61 @@ out:
return ret;
}
#ifdef UDEV_SYNC_SUPPORT
static int _udev_check_pv_min_size(struct device *dev)
{
struct dev_ext *ext;
const char *size_str;
char *endp;
uint64_t size;
if (!(ext = dev_ext_get(dev)))
return_0;
if (!(size_str = udev_device_get_sysattr_value((struct udev_device *)ext->handle, DEV_EXT_UDEV_SYSFS_ATTR_SIZE))) {
log_debug_devs("%s: Skipping: failed to get size from sysfs [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}
errno = 0;
size = strtoull(size_str, &endp, 10);
if (errno || !endp || *endp) {
log_debug_devs("%s: Skipping: failed to parse size from sysfs [%s:%p]",
dev_name(dev), dev_ext_name(dev), dev->ext.handle);
return 0;
}
if (size < pv_min_size()) {
log_debug_devs("%s: Skipping: %s [%s:%p]", dev_name(dev),
_too_small_to_hold_pv_msg,
dev_ext_name(dev), dev->ext.handle);
return 0;
}
return 1;
}
#else
static int _udev_check_pv_min_size(struct device *dev)
{
return 1;
}
#endif
static int _check_pv_min_size(struct device *dev)
{
if (dev->ext.src == DEV_EXT_NONE)
return _native_check_pv_min_size(dev);
if (dev->ext.src == DEV_EXT_UDEV)
return _udev_check_pv_min_size(dev);
log_error(INTERNAL_ERROR "Missing hook for PV min size check "
"using external device info source %s", dev_ext_name(dev));
return 0;
}
static int _passes_usable_filter(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
{
struct filter_data *data = f->private;
@@ -97,9 +156,19 @@ static int _passes_usable_filter(struct cmd_context *cmd, struct dev_filter *f,
}
if (r) {
r = _check_pv_min_size(dev);
if (!r)
dev->filtered_flags |= DEV_FILTERED_MINSIZE;
/* check if the device is not too small to hold a PV */
switch (mode) {
case FILTER_MODE_NO_LVMETAD:
/* fall through */
case FILTER_MODE_PRE_LVMETAD:
r = _check_pv_min_size(dev);
if (!r)
dev->filtered_flags |= DEV_FILTERED_MINSIZE;
break;
case FILTER_MODE_POST_LVMETAD:
/* nothing to do here */
break;
}
}
return r;

View File

@@ -20,7 +20,7 @@
#include "lib/device/dev-cache.h"
#include "lib/device/dev-type.h"
struct dev_filter *composite_filter_create(int n, struct dev_filter **filters);
struct dev_filter *composite_filter_create(int n, int use_dev_ext_info, struct dev_filter **filters);
struct dev_filter *lvm_type_filter_create(struct dev_types *dt);
struct dev_filter *md_filter_create(struct cmd_context *cmd, struct dev_types *dt);

View File

@@ -413,8 +413,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg,
return 0;
}
pv->vg_name = vg->name;
/* both are struct id */
memcpy(&pv->vg_id, &vg->id, sizeof(struct id));
pv->vgid = vg->id;
if (!(new_pvl = dm_pool_zalloc(vg->vgmem, sizeof(*new_pvl)))) {
log_error("Failed to allocate PV list item for \"%s\".",

View File

@@ -296,24 +296,84 @@ static struct raw_locn *_read_metadata_location_vg(struct cmd_context *cmd,
const char *vgname,
int *precommitted)
{
size_t len;
char vgnamebuf[NAME_LEN + 2] __attribute__((aligned(8)));
struct raw_locn *rlocn, *rlocn_precommitted;
struct lvmcache_info *info;
struct lvmcache_vgsummary vgsummary_orphan = {
.vgname = FMT_TEXT_ORPHAN_VG_NAME,
};
int rlocn_was_ignored;
dm_list_init(&vgsummary_orphan.pvsummaries);
memcpy(&vgsummary_orphan.vgid, FMT_TEXT_ORPHAN_VG_NAME, sizeof(FMT_TEXT_ORPHAN_VG_NAME));
rlocn = mdah->raw_locns; /* Slot 0 */
rlocn_precommitted = rlocn + 1; /* Slot 1 */
rlocn_was_ignored = rlocn_is_ignored(rlocn);
/* Should we use precommitted metadata? */
if (*precommitted && rlocn_precommitted->size &&
(rlocn_precommitted->offset != rlocn->offset)) {
rlocn = rlocn_precommitted;
log_debug_metadata("VG %s metadata check %s mda %llu slot1 offset %llu size %llu",
vgname ?: "",
dev_name(dev_area->dev),
(unsigned long long)dev_area->start,
(unsigned long long)rlocn->offset,
(unsigned long long)rlocn->size);
} else {
*precommitted = 0;
log_debug_metadata("VG %s metadata check %s mda %llu slot0 offset %llu size %llu",
vgname ?: "",
dev_name(dev_area->dev),
(unsigned long long)dev_area->start,
(unsigned long long)rlocn->offset,
(unsigned long long)rlocn->size);
}
/* Do not check non-existent metadata. */
if (!rlocn->offset && !rlocn->size)
return NULL;
return rlocn;
/*
* Don't try to check existing metadata
* if given vgname is an empty string.
*/
if (!vgname || !*vgname)
return rlocn;
/*
* If live rlocn has ignored flag, data will be out-of-date so skip further checks.
*/
if (rlocn_was_ignored)
return rlocn;
/*
* Verify that the VG metadata pointed to by the rlocn
* begins with a valid vgname.
*/
memset(vgnamebuf, 0, sizeof(vgnamebuf));
if (!dev_read_bytes(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, vgnamebuf))
goto fail;
if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
(isspace(vgnamebuf[len]) || vgnamebuf[len] == '{'))
return rlocn;
fail:
log_error("Metadata on %s at %llu has wrong VG name \"%s\" expected %s.",
dev_name(dev_area->dev),
(unsigned long long)(dev_area->start + rlocn->offset),
vgnamebuf, vgname);
if ((info = lvmcache_info_from_pvid(dev_area->dev->pvid, dev_area->dev, 0)) &&
!lvmcache_update_vgname_and_id(cmd, info, &vgsummary_orphan))
stack;
return NULL;
}
/*
@@ -427,23 +487,16 @@ static struct volume_group *_vg_read_raw_area(struct cmd_context *cmd,
rlocn->checksum,
&when, &desc);
if (!vg && !*use_previous_vg) {
log_warn("WARNING: Failed to read metadata text at %llu off %llu size %llu VG %s on %s",
(unsigned long long)(area->start + rlocn->offset),
(unsigned long long)rlocn->offset,
(unsigned long long)rlocn->size,
vgname,
dev_name(area->dev));
return NULL;
if (!vg) {
/* FIXME: detect and handle errors, and distinguish from the optimization
that skips parsing the metadata which also returns NULL. */
}
log_debug_metadata("Found metadata text at %llu off %llu size %llu VG %s on %s",
log_debug_metadata("Found metadata on %s at %llu size %llu for VG %s",
dev_name(area->dev),
(unsigned long long)(area->start + rlocn->offset),
(unsigned long long)rlocn->offset,
(unsigned long long)rlocn->size,
vgname,
dev_name(area->dev));
vgname);
if (vg && precommitted)
vg->status |= PRECOMMITTED;
@@ -1480,6 +1533,8 @@ int read_metadata_location_summary(const struct format_type *fmt,
{
struct raw_locn *rlocn;
uint32_t wrap = 0;
unsigned int len = 0;
char namebuf[NAME_LEN + 1] __attribute__((aligned(8)));
uint64_t max_size;
if (!mdah) {
@@ -1508,6 +1563,28 @@ int read_metadata_location_summary(const struct format_type *fmt,
return 0;
}
memset(namebuf, 0, sizeof(namebuf));
if (!dev_read_bytes(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, namebuf))
stack;
while (namebuf[len] && !isspace(namebuf[len]) && namebuf[len] != '{' &&
len < (NAME_LEN - 1))
len++;
namebuf[len] = '\0';
/*
* Check that the text metadata in the circular buffer begins with a
* valid vg name.
*/
if (!validate_name(namebuf)) {
log_warn("WARNING: Metadata location on %s at %llu begins with invalid VG name.",
dev_name(dev_area->dev),
(unsigned long long)(dev_area->start + rlocn->offset));
return 0;
}
/*
* This function is used to read the vg summary during label scan.
* Save the text start location and checksum during scan. After the VG
@@ -1569,7 +1646,9 @@ int read_metadata_location_summary(const struct format_type *fmt,
vgsummary->mda_size = rlocn->size;
/* Keep track of largest metadata size we find. */
lvmcache_save_metadata_size(rlocn->size);
lvmcache_save_metadata_size_bytes(rlocn->size);
/* Keep track of the most full metadata area. */
lvmcache_save_metadata_size_percent(rlocn->size, mdah->size);
lvmcache_lookup_mda(vgsummary);
@@ -1658,9 +1737,8 @@ static int _set_ext_flags(struct physical_volume *pv, struct lvmcache_info *info
/* Only for orphans - FIXME That's not true any more */
static int _text_pv_write(struct cmd_context *cmd, const struct format_type *fmt, struct physical_volume *pv)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct format_instance *fid = pv->fid;
const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
struct label *label;
struct lvmcache_info *info;
struct mda_context *mdac;
@@ -1668,18 +1746,10 @@ static int _text_pv_write(struct cmd_context *cmd, const struct format_type *fmt
struct _write_single_mda_baton baton;
unsigned mda_index;
if (is_orphan_vg(pv->vg_name))
memcpy(vgid, pv->vg_name, ID_LEN);
else if (pv->vg)
memcpy(vgid, &pv->vg->id.uuid, ID_LEN);
memcpy(pvid, &pv->id.uuid, ID_LEN);
/* Add a new cache entry with PV info or update existing one. */
if (!(info = lvmcache_add(cmd, fmt->labeller, pvid,
if (!(info = lvmcache_add(cmd, fmt->labeller, (const char *) &pv->id,
pv->dev, pv->label_sector, pv->vg_name,
vgid[0] ? vgid : NULL,
0, NULL)))
is_orphan_vg(pv->vg_name) ? pv->vg_name : pv->vg ? (const char *) &pv->vg->id : NULL, 0, NULL)))
return_0;
/* lvmcache_add() creates info and info->label structs for the dev, get info->label. */
@@ -1697,13 +1767,6 @@ static int _text_pv_write(struct cmd_context *cmd, const struct format_type *fmt
* The fid_get_mda_indexed fn can handle that transparently,
* just pass the right format_instance in.
*/
/* FIXME: why is old needed here? */
if (*pv->old_id.uuid)
memcpy(pvid, &pv->old_id.uuid, ID_LEN);
else
memcpy(pvid, &pv->id.uuid, ID_LEN);
for (mda_index = 0; mda_index < FMT_TEXT_MAX_MDAS_PER_PV; mda_index++) {
if (!(mda = fid_get_mda_indexed(fid, pvid, ID_LEN, mda_index)))
continue;
@@ -1782,7 +1845,7 @@ static int _text_pv_needs_rewrite(const struct format_type *fmt, struct physical
if (!pv->dev)
return 1;
if (!(info = lvmcache_info_from_pv_id(&pv->id, pv->dev, 0))) {
if (!(info = lvmcache_info_from_pvid((const char *)&pv->id, pv->dev, 0))) {
log_error("Failed to find cached info for PV %s.", pv_dev_name(pv));
return 0;
}
@@ -2014,8 +2077,8 @@ static int _text_pv_setup(const struct format_type *fmt,
struct physical_volume *pv,
struct volume_group *vg)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct format_instance *fid = pv->fid;
const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
struct lvmcache_info *info;
unsigned mda_index;
struct metadata_area *pv_mda, *pv_mda_copy;
@@ -2023,11 +2086,6 @@ static int _text_pv_setup(const struct format_type *fmt,
uint64_t pe_count;
uint64_t size_reduction = 0;
if (*pv->old_id.uuid)
memcpy(pvid, &pv->old_id.uuid, ID_LEN);
else
memcpy(pvid, &pv->id.uuid, ID_LEN);
/* If PV has its own format instance, add mdas from pv->fid to vg->fid. */
if (pv->fid != vg->fid) {
for (mda_index = 0; mda_index < FMT_TEXT_MAX_MDAS_PER_PV; mda_index++) {
@@ -2193,7 +2251,6 @@ static int _add_metadata_area_to_pv(struct physical_volume *pv,
uint64_t mda_size,
unsigned mda_ignored)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct metadata_area *mda;
struct mda_context *mdac;
struct mda_lists *mda_lists = (struct mda_lists *) pv->fmt->private;
@@ -2228,9 +2285,7 @@ static int _add_metadata_area_to_pv(struct physical_volume *pv,
memset(&mdac->rlocn, 0, sizeof(mdac->rlocn));
mda_set_ignored(mda, mda_ignored);
memcpy(pvid, &pv->id.uuid, ID_LEN);
fid_add_mda(pv->fid, mda, pvid, ID_LEN, mda_index);
fid_add_mda(pv->fid, mda, (char *) &pv->id, ID_LEN, mda_index);
return 1;
}
@@ -2246,8 +2301,8 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
uint64_t mda_size,
unsigned mda_ignored)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct format_instance *fid = pv->fid;
const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
uint64_t ba_size, pe_start, first_unallocated;
uint64_t alignment, alignment_offset;
uint64_t disk_size;
@@ -2261,11 +2316,6 @@ static int _text_pv_add_metadata_area(const struct format_type *fmt,
const char *limit_name;
int limit_applied = 0;
if (*pv->old_id.uuid)
memcpy(pvid, &pv->old_id.uuid, ID_LEN);
else
memcpy(pvid, &pv->id.uuid, ID_LEN);
if (mda_index >= FMT_TEXT_MAX_MDAS_PER_PV) {
log_error(INTERNAL_ERROR "invalid index of value %u used "
"while trying to add metadata area on PV %s. "
@@ -2495,8 +2545,6 @@ bad:
static int _remove_metadata_area_from_pv(struct physical_volume *pv,
unsigned mda_index)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
if (mda_index >= FMT_TEXT_MAX_MDAS_PER_PV) {
log_error(INTERNAL_ERROR "can't remove metadata area with "
"index %u from PV %s. Metadata "
@@ -2506,9 +2554,8 @@ static int _remove_metadata_area_from_pv(struct physical_volume *pv,
return 0;
}
memcpy(pvid, &pv->id.uuid, ID_LEN);
return fid_remove_mda(pv->fid, NULL, pvid, ID_LEN, mda_index);
return fid_remove_mda(pv->fid, NULL, (const char *) &pv->id,
ID_LEN, mda_index);
}
static int _text_pv_remove_metadata_area(const struct format_type *fmt,
@@ -2523,19 +2570,14 @@ static int _text_pv_resize(const struct format_type *fmt,
struct volume_group *vg,
uint64_t size)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct format_instance *fid = pv->fid;
const char *pvid = (const char *) (*pv->old_id.uuid ? &pv->old_id : &pv->id);
struct metadata_area *mda;
struct mda_context *mdac;
uint64_t size_reduction;
uint64_t mda_size;
unsigned mda_ignored;
if (*pv->old_id.uuid)
memcpy(pvid, &pv->old_id.uuid, ID_LEN);
else
memcpy(pvid, &pv->id.uuid, ID_LEN);
/*
* First, set the new size and update the cache and reset pe_count.
* (pe_count must be reset otherwise it would be considered as

View File

@@ -219,8 +219,7 @@ static int _read_pv(struct cmd_context *cmd,
if (!(pv->vg_name = dm_pool_strdup(mem, vg->name)))
return_0;
/* both are struct id */
memcpy(&pv->vg_id, &vg->id, sizeof(struct id));
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
if (!_read_flag_config(pvn, &pv->status, PV_FLAGS)) {
log_error("Couldn't read status flags for physical volume.");
@@ -1303,7 +1302,6 @@ static int _read_vgsummary(const struct format_type *fmt, const struct dm_config
const struct dm_config_node *vgn;
struct dm_pool *mem = fmt->cmd->mem;
const char *str;
struct id id;
if (!dm_config_get_str(cft->root, "creation_host", &str))
str = "";
@@ -1324,13 +1322,11 @@ static int _read_vgsummary(const struct format_type *fmt, const struct dm_config
vgn = vgn->child;
if (!_read_id(&id, vgn, "id")) {
if (!_read_id(&vgsummary->vgid, vgn, "id")) {
log_error("Couldn't read uuid for volume group %s.", vgsummary->vgname);
return 0;
}
memcpy(vgsummary->vgid, &id, ID_LEN);
if (!_read_flag_config(vgn, &vgsummary->vgstatus, VG_FLAGS)) {
log_error("Couldn't find status flags for volume group %s.",
vgsummary->vgname);

View File

@@ -327,9 +327,6 @@ static int _read_mda_header_and_metadata(const struct format_type *fmt,
{
struct mda_context *mdac = (struct mda_context *) mda->metadata_locn;
struct mda_header *mdah;
int retries = 0;
retry:
if (!(mdah = raw_read_mda_header(fmt, &mdac->area, (mda->mda_num == 1), 0, bad_fields))) {
log_warn("WARNING: bad metadata header on %s at %llu.",
@@ -357,38 +354,6 @@ static int _read_mda_header_and_metadata(const struct format_type *fmt,
if (vgsummary->zero_offset)
return 1;
/*
* This code is used by label_scan to get a summary of the
* VG metadata that will be properly read later by vg_read.
* The initial read of this device during label_scan
* populates bcache with the first 128K of data from the
* device. That block of data contains the mda_header
* (at 4k) but will often not include the metadata text,
* which is often located further into the metadata area
* (beyond the 128K block saved in bcache.)
* So read_metadata_location_summary will usually get the
* mda_header from bcache which was read initially, and
* then it will often need to do a new disk read to get
* the actual metadata text that the mda_header points to.
* Since there is no locking around label_scan, it's
* possible (but very rare) that the entire metadata area
* can be rewritten by other commands between the time that
* this command read the mda_header and the time that it
* reads the metadata text. This means the expected metadata
* text isn't found, and an error is returned here.
* To handle this, invalidate all data in bcache for this
* device and reread the mda_header and metadata text back to
* back, so inconsistency is less likely (without locking
* there's no guarantee, e.g. if the command is blocked
* somehow between the two reads.)
*/
if (!retries) {
log_print("Retrying metadata scan.");
retries++;
dev_invalidate(mdac->area.dev);
goto retry;
}
log_warn("WARNING: bad metadata text on %s in mda%d",
dev_name(mdac->area.dev), mda->mda_num);
*bad_fields |= BAD_MDA_TEXT;
@@ -409,7 +374,6 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
uint64_t label_sector, int *is_duplicate)
{
struct lvmcache_vgsummary vgsummary;
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct lvmcache_info *info;
const struct format_type *fmt = labeller->fmt;
struct label_header *lh = (struct label_header *) label_buf;
@@ -432,8 +396,6 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
*/
pvhdr = (struct pv_header *) ((char *) label_buf + xlate32(lh->offset_xl));
memcpy(pvid, &pvhdr->pv_uuid, ID_LEN);
/*
* FIXME: stop adding the device to lvmcache initially as an orphan
* (and then moving it later) and instead just add it when we know the
@@ -448,7 +410,7 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
*
* Other reasons for lvmcache_add to return NULL are internal errors.
*/
if (!(info = lvmcache_add(cmd, labeller, pvid, dev, label_sector,
if (!(info = lvmcache_add(cmd, labeller, (char *)pvhdr->pv_uuid, dev, label_sector,
FMT_TEXT_ORPHAN_VG_NAME,
FMT_TEXT_ORPHAN_VG_NAME, 0, is_duplicate)))
return_0;
@@ -498,9 +460,8 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
if (!(ext_version = xlate32(pvhdr_ext->version)))
goto scan_mdas;
if (ext_version != PV_HEADER_EXTENSION_VSN)
log_debug_metadata("Found pv_header_extension version " FMTu32 " on %s",
ext_version, dev_name(dev));
log_debug_metadata("%s: PV header extension version " FMTu32 " found",
dev_name(dev), ext_version);
/* Extension version */
lvmcache_set_ext_version(info, xlate32(pvhdr_ext->version));
@@ -561,7 +522,7 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
bad_mda_count++;
} else {
/* The normal success path */
log_debug("Found metadata seqno %u in mda1 on %s", vgsummary.seqno, dev_name(dev));
log_debug("Scanned %s mda1 seqno %u", dev_name(dev), vgsummary.seqno);
good_mda_count++;
}
}
@@ -611,7 +572,7 @@ static int _text_read(struct cmd_context *cmd, struct labeller *labeller, struct
bad_mda_count++;
} else {
/* The normal success path */
log_debug("Found metadata seqno %u in mda2 on %s", vgsummary.seqno, dev_name(dev));
log_debug("Scanned %s mda2 seqno %u", dev_name(dev), vgsummary.seqno);
good_mda_count++;
}
}

View File

@@ -1288,12 +1288,14 @@ check:
*/
int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
struct dm_list *devs_in, struct dm_list *devs_out)
struct dm_list *devs_in, struct dm_list *devs_out, char **vgname_out)
{
struct dm_list hints_list;
int needs_refresh = 0;
char *vgname = NULL;
*vgname_out = NULL;
dm_list_init(&hints_list);
/* Decide below if the caller should create new hints. */
@@ -1433,7 +1435,7 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
dm_list_splice(hints_out, &hints_list);
free(vgname);
*vgname_out = vgname;
return 1;
}

View File

@@ -33,7 +33,7 @@ void clear_hint_file(struct cmd_context *cmd);
void invalidate_hints(struct cmd_context *cmd);
int get_hints(struct cmd_context *cmd, struct dm_list *hints, int *newhints,
struct dm_list *devs_in, struct dm_list *devs_out);
struct dm_list *devs_in, struct dm_list *devs_out, char **vgname_out);
int validate_hints(struct cmd_context *cmd, struct dm_list *hints);

View File

@@ -264,8 +264,9 @@ static bool _in_bcache(struct device *dev)
}
static struct labeller *_find_lvm_header(struct device *dev,
char *headers_buf,
int headers_buf_size,
char *scan_buf,
uint32_t scan_buf_sectors,
char *label_buf,
uint64_t *label_sector,
uint64_t block_sector,
uint64_t start_sector)
@@ -276,13 +277,24 @@ static struct labeller *_find_lvm_header(struct device *dev,
uint64_t sector;
int found = 0;
/*
* Find which sector in scan_buf starts with a valid label,
* and copy it into label_buf.
*/
for (sector = start_sector; sector < start_sector + LABEL_SCAN_SECTORS;
sector += LABEL_SIZE >> SECTOR_SHIFT) {
if ((sector * 512) >= headers_buf_size)
/*
* The scan_buf passed in is a bcache block, which is
* BCACHE_BLOCK_SIZE_IN_SECTORS large. So if start_sector is
* one of the last couple sectors in that buffer, we need to
* break early.
*/
if (sector >= scan_buf_sectors)
break;
lh = (struct label_header *) (headers_buf + (sector << SECTOR_SHIFT));
lh = (struct label_header *) (scan_buf + (sector << SECTOR_SHIFT));
if (!memcmp(lh->id, LABEL_ID, sizeof(lh->id))) {
if (found) {
@@ -307,8 +319,9 @@ static struct labeller *_find_lvm_header(struct device *dev,
dm_list_iterate_items(li, &_labellers) {
if (li->l->ops->can_handle(li->l, (char *) lh, block_sector + sector)) {
log_debug("Found label at sector %llu on %s",
(unsigned long long)(block_sector + sector), dev_name(dev));
log_very_verbose("%s: %s label detected at sector %llu",
dev_name(dev), li->name,
(unsigned long long)(block_sector + sector));
if (found) {
log_error("Ignoring additional label on %s at sector %llu",
dev_name(dev),
@@ -319,6 +332,7 @@ static struct labeller *_find_lvm_header(struct device *dev,
labeller_ret = li->l;
found = 1;
memcpy(label_buf, lh, LABEL_SIZE);
if (label_sector)
*label_sector = block_sector + sector;
break;
@@ -340,13 +354,13 @@ static struct labeller *_find_lvm_header(struct device *dev,
* are performed in the processing functions to get that data.
*/
static int _process_block(struct cmd_context *cmd, struct dev_filter *f,
struct device *dev, char *headers_buf, int headers_buf_size,
struct device *dev, struct block *bb,
uint64_t block_sector, uint64_t start_sector,
int *is_lvm_device)
{
char *label_buf;
char label_buf[LABEL_SIZE] __attribute__((aligned(8)));
struct labeller *labeller;
uint64_t label_sector = 0;
uint64_t sector = 0;
int is_duplicate = 0;
int ret = 0;
@@ -382,9 +396,13 @@ static int _process_block(struct cmd_context *cmd, struct dev_filter *f,
}
/*
* Finds the data sector containing the label.
* Finds the data sector containing the label and copies into label_buf.
* label_buf: struct label_header + struct pv_header + struct pv_header_extension
*
* FIXME: we don't need to copy one sector from bb->data into label_buf,
* we can just point label_buf at one sector in ld->buf.
*/
if (!(labeller = _find_lvm_header(dev, headers_buf, headers_buf_size, &label_sector, block_sector, start_sector))) {
if (!(labeller = _find_lvm_header(dev, bb->data, BCACHE_BLOCK_SIZE_IN_SECTORS, label_buf, &sector, block_sector, start_sector))) {
/*
* Non-PVs exit here
@@ -409,7 +427,6 @@ static int _process_block(struct cmd_context *cmd, struct dev_filter *f,
dev->flags |= DEV_SCAN_FOUND_LABEL;
*is_lvm_device = 1;
label_buf = headers_buf + (label_sector * 512);
/*
* This is the point where the scanning code dives into the rest of
@@ -419,7 +436,7 @@ static int _process_block(struct cmd_context *cmd, struct dev_filter *f,
* info/vginfo structs. That lvmcache info is used later when the
* command wants to read the VG to do something to it.
*/
ret = labeller->ops->read(cmd, labeller, dev, label_buf, label_sector, &is_duplicate);
ret = labeller->ops->read(cmd, labeller, dev, label_buf, sector, &is_duplicate);
if (!ret) {
if (is_duplicate) {
@@ -653,12 +670,9 @@ static void _invalidate_di(struct bcache *cache, int di)
* its info is removed from lvmcache.
*/
#define HEADERS_BUF_SIZE 4096
static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
struct dm_list *devs, int want_other_devs, int *failed)
{
char headers_buf[HEADERS_BUF_SIZE];
struct dm_list wait_devs;
struct dm_list done_devs;
struct dm_list reopen_devs;
@@ -724,35 +738,14 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
scan_read_errors++;
scan_failed_count++;
lvmcache_del_dev(devl->dev);
if (bb)
bcache_put(bb);
} else {
/* copy the first 4k from bb that will contain label_header */
memcpy(headers_buf, bb->data, HEADERS_BUF_SIZE);
/*
* "put" the bcache block before process_block because
* processing metadata may need to invalidate and reread
* metadata that's covered by bb. invalidate/reread is
* not allowed while bb is held. The functions for
* filtering and scanning metadata for this device use
* dev_read_bytes(), which will generally grab the
* bcache block/data that we're putting here. Since
* we're doing put, it's possible but not likely that
* bcache could drop the block before dev_read_bytes()
* uses it again, in which case bcache will reread it
* from disk for dev_read_bytes().
*/
bcache_put(bb);
log_debug_devs("Processing data from device %s %d:%d di %d",
log_debug_devs("Processing data from device %s %d:%d di %d block %p",
dev_name(devl->dev),
(int)MAJOR(devl->dev->dev),
(int)MINOR(devl->dev->dev),
devl->dev->bcache_di);
devl->dev->bcache_di, (void *)bb);
ret = _process_block(cmd, f, devl->dev, headers_buf, sizeof(headers_buf), 0, 0, &is_lvm_device);
ret = _process_block(cmd, f, devl->dev, bb, 0, 0, &is_lvm_device);
if (!ret && is_lvm_device) {
log_debug_devs("Scan failed to process %s", dev_name(devl->dev));
@@ -761,6 +754,9 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
}
}
if (bb)
bcache_put(bb);
/*
* Keep the bcache block of lvm devices we have processed so
* that the vg_read phase can reuse it. If bcache failed to
@@ -1036,6 +1032,7 @@ int label_scan(struct cmd_context *cmd)
struct dev_iter *iter;
struct device_list *devl, *devl2;
struct device *dev;
char *vgname_hint = NULL;
uint64_t max_metadata_size_bytes;
int device_ids_invalid = 0;
int using_hints;
@@ -1141,21 +1138,54 @@ int label_scan(struct cmd_context *cmd)
* by using hints which tell us which devices are PVs, which
* are the only devices we actually need to scan. Without
* hints we need to scan all devs to find which are PVs.
*
* TODO: if the command is using hints and a single vgname
*/
if (!get_hints(cmd, &hints_list, &create_hints, &all_devs, &scan_devs, &vgname_hint)) {
dm_list_splice(&scan_devs, &all_devs);
dm_list_init(&hints_list);
using_hints = 0;
} else
using_hints = 1;
/*
* If the command is using hints and a single vgname
* arg, we can also take the vg lock here, prior to scanning.
* This means we would not need to rescan the PVs in the VG
* in vg_read (skip lvmcache_label_rescan_vg) after the
* vg lock is usually taken. (Some commands are already
* able to avoid rescan in vg_read, but locking early would
* apply to more cases.)
*
* TODO: we don't know exactly which vg lock mode (read or write)
* the command will use in vg_read() for the normal lock_vol(),
* but we could make a fairly accurate guess of READ/WRITE based
* on looking at the command name. If we guess wrong we can
* just unlock_vg and lock_vol again with the correct mode in
* vg_read().
*/
if (!get_hints(cmd, &hints_list, &create_hints, &all_devs, &scan_devs)) {
dm_list_splice(&scan_devs, &all_devs);
dm_list_init(&hints_list);
using_hints = 0;
} else
using_hints = 1;
if (vgname_hint) {
uint32_t lck_type = LCK_VG_WRITE;
log_debug("Early lock vg");
/* FIXME: borrowing this lockd flag which should be
quite close to what we want, based on the command name.
Need to do proper mode selection here, and then check
in case the later lock_vol in vg_read wants different. */
if (cmd->lockd_vg_default_sh)
lck_type = LCK_VG_READ;
if (!lock_vol(cmd, vgname_hint, lck_type, NULL)) {
log_warn("Could not pre-lock VG %s.", vgname_hint);
/* not an error since this is just an optimization */
} else {
/* Save some state indicating that the vg lock
is already held so that the normal lock_vol()
will know. */
cmd->early_lock_vg_mode = lck_type;
}
free(vgname_hint);
}
/*
* If the total number of devices exceeds the soft open file
@@ -1191,7 +1221,7 @@ int label_scan(struct cmd_context *cmd)
* If the largest metadata is within 1MB of the bcache size, then start
* warning.
*/
max_metadata_size_bytes = lvmcache_max_metadata_size();
max_metadata_size_bytes = lvmcache_max_metadata_size_bytes();
if (max_metadata_size_bytes + (1024 * 1024) > _current_bcache_size_bytes) {
/* we want bcache to be 1MB larger than the max metadata seen */
@@ -1206,6 +1236,14 @@ int label_scan(struct cmd_context *cmd)
(unsigned long long)want_size_kb);
}
/*
* If vg metadata is using a large percentage of a metadata area, then
* create /run/lvm/scan_lock_global to tell future lvm commands to
* begin doing lock_global() prior to scanning to avoid problems due to
* metadata wrapping between label_scan and vg_read.
*/
set_scan_lock_global(cmd);
dm_list_init(&cmd->hints);
/*
@@ -1703,11 +1741,6 @@ bool dev_invalidate_bytes(struct device *dev, uint64_t start, size_t len)
return bcache_invalidate_bytes(scan_bcache, dev->bcache_di, start, len);
}
void dev_invalidate(struct device *dev)
{
bcache_invalidate_di(scan_bcache, dev->bcache_di);
}
bool dev_write_zeros(struct device *dev, uint64_t start, size_t len)
{
return dev_set_bytes(dev, start, len, 0);

View File

@@ -130,7 +130,6 @@ bool dev_write_bytes(struct device *dev, uint64_t start, size_t len, void *data)
bool dev_write_zeros(struct device *dev, uint64_t start, size_t len);
bool dev_set_bytes(struct device *dev, uint64_t start, size_t len, uint8_t val);
bool dev_invalidate_bytes(struct device *dev, uint64_t start, size_t len);
void dev_invalidate(struct device *dev);
void dev_set_last_byte(struct device *dev, uint64_t offset);
void dev_unset_last_byte(struct device *dev);

View File

@@ -203,6 +203,11 @@ int lock_vol(struct cmd_context *cmd, const char *vol, uint32_t flags, const str
if (is_orphan_vg(vol))
return 1;
if (!is_global && cmd->early_lock_vg_mode && (lck_type != LCK_UNLOCK)) {
log_debug("VG was locked early.");
return 1;
}
if (!_blocking_supported)
flags |= LCK_NONBLOCK;
@@ -354,10 +359,8 @@ static int _lockf_global(struct cmd_context *cmd, const char *mode, int convert,
if (!strcmp(mode, "ex")) {
flags |= LCK_WRITE;
if (cmd->lockf_global_ex) {
log_warn("global flock already held ex");
if (cmd->lockf_global_ex)
return 1;
}
ret = lock_vol(cmd, VG_GLOBAL, flags, NULL);
if (ret)

View File

@@ -23,6 +23,7 @@
#include "lib/metadata/pv_alloc.h"
#include "lib/display/display.h"
#include "lib/metadata/segtype.h"
#include "lib/format_text/archiver.h"
#include "lib/activate/activate.h"
#include "lib/datastruct/str_list.h"
#include "lib/config/defaults.h"
@@ -8738,8 +8739,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
}
if (seg_is_vdo_pool(lp)) {
if (!convert_vdo_pool_lv(lv, &lp->vdo_params, &lp->virtual_extents,
1, lp->vdo_pool_header_size)) {
if (!convert_vdo_pool_lv(lv, &lp->vdo_params, &lp->virtual_extents, 1)) {
stack;
goto deactivate_and_revert_new_lv;
}

View File

@@ -270,10 +270,8 @@ static void _check_raid_seg(struct lv_segment *seg, int *error_count)
if (!seg->area_count)
raid_seg_error("zero area count");
if (!seg->areas) {
if (!seg->areas)
raid_seg_error("zero areas");
return;
}
if (seg->extents_copied > seg->len)
raid_seg_error_val("extents_copied too large", seg->extents_copied);

View File

@@ -1034,7 +1034,6 @@ struct lvcreate_params {
int approx_alloc; /* all */
alloc_policy_t alloc; /* all */
struct dm_vdo_target_params vdo_params; /* vdo */
uint64_t vdo_pool_header_size; /* VDO */
int raidintegrity;
const char *raidintegritymode;
@@ -1369,12 +1368,10 @@ int parse_vdo_pool_status(struct dm_pool *mem, const struct logical_volume *vdo_
struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
const struct dm_vdo_target_params *vtp,
uint32_t *virtual_extents,
int format,
uint64_t vdo_pool_header_size);
int format);
int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy);
int fill_vdo_target_params(struct cmd_context *cmd,
struct dm_vdo_target_params *vtp,
uint64_t *vdo_pool_header_size,
struct profile *profile);
/* -- metadata/vdo_manip.c */

View File

@@ -275,17 +275,15 @@ void add_pvl_to_vgs(struct volume_group *vg, struct pv_list *pvl)
void del_pvl_from_vgs(struct volume_group *vg, struct pv_list *pvl)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct lvmcache_info *info;
vg->pv_count--;
dm_list_del(&pvl->list);
memcpy(pvid, &pvl->pv->id.uuid, ID_LEN);
pvl->pv->vg = vg->fid->fmt->orphan_vg; /* orphan */
if ((info = lvmcache_info_from_pvid(pvid, pvl->pv->dev, 0)))
lvmcache_fid_add_mdas(info, vg->fid->fmt->orphan_vg->fid, pvid, ID_LEN);
if ((info = lvmcache_info_from_pvid((const char *) &pvl->pv->id, pvl->pv->dev, 0)))
lvmcache_fid_add_mdas(info, vg->fid->fmt->orphan_vg->fid,
(const char *) &pvl->pv->id, ID_LEN);
pv_set_fid(pvl->pv, vg->fid->fmt->orphan_vg->fid);
}
@@ -351,8 +349,7 @@ int add_pv_to_vg(struct volume_group *vg, const char *pv_name,
return 0;
}
/* both are struct id */
memcpy(&pv->vg_id, &vg->id, sizeof(struct id));
memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
/* Units of 512-byte sectors */
pv->pe_size = vg->extent_size;
@@ -1665,7 +1662,7 @@ struct logical_volume *find_lv_in_vg_by_lvid(const struct volume_group *vg,
{
struct lv_list *lvl;
if (memcmp(&lvid->id[0], &vg->id, ID_LEN))
if (memcmp(&lvid->id[0], &vg->id, sizeof(vg->id)))
return NULL; /* Check VG does not match */
dm_list_iterate_items(lvl, &vg->lvs)
@@ -2850,7 +2847,6 @@ static int _handle_historical_lvs(struct volume_group *vg)
static void _wipe_outdated_pvs(struct cmd_context *cmd, struct volume_group *vg)
{
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct dm_list devs;
struct dm_list *mdas = NULL;
struct device_list *devl;
@@ -2869,14 +2865,12 @@ static void _wipe_outdated_pvs(struct cmd_context *cmd, struct volume_group *vg)
* vginfo->outdated_infos list. Here we clear the PVs on that list.
*/
memcpy(vgid, &vg->id.uuid, ID_LEN);
lvmcache_get_outdated_devs(cmd, vg->name, vgid, &devs);
lvmcache_get_outdated_devs(cmd, vg->name, (const char *)&vg->id, &devs);
dm_list_iterate_items(devl, &devs) {
dev = devl->dev;
lvmcache_get_outdated_mdas(cmd, vg->name, vgid, dev, &mdas);
lvmcache_get_outdated_mdas(cmd, vg->name, (const char *)&vg->id, dev, &mdas);
if (mdas) {
dm_list_iterate_items(mda, mdas) {
@@ -2911,7 +2905,7 @@ static void _wipe_outdated_pvs(struct cmd_context *cmd, struct volume_group *vg)
* removed) but we only need to wipe pvs once, so clear the outdated
* list so it won't be wiped again.
*/
lvmcache_del_outdated_devs(cmd, vg->name, vgid);
lvmcache_del_outdated_devs(cmd, vg->name, (const char *)&vg->id);
}
/*
@@ -2920,7 +2914,6 @@ static void _wipe_outdated_pvs(struct cmd_context *cmd, struct volume_group *vg)
*/
int vg_write(struct volume_group *vg)
{
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct dm_list *mdah;
struct pv_list *pvl, *pvl_safe, *new_pvl;
struct metadata_area *mda;
@@ -2928,8 +2921,6 @@ int vg_write(struct volume_group *vg)
struct device *mda_dev;
int revert = 0, wrote = 0;
memcpy(vgid, &vg->id.uuid, ID_LEN);
if (vg_is_shared(vg)) {
dm_list_iterate_items(lvl, &vg->lvs) {
if (lvl->lv->lock_args && !strcmp(lvl->lv->lock_args, "pending")) {
@@ -3040,7 +3031,7 @@ int vg_write(struct volume_group *vg)
* dev, and then it's later changed to not ignored, and
* we see the old metadata.
*/
if (lvmcache_has_old_metadata(vg->cmd, vg->name, vgid, mda_dev)) {
if (lvmcache_has_old_metadata(vg->cmd, vg->name, (const char *)&vg->id, mda_dev)) {
log_warn("WARNING: updating old metadata to %u on %s for VG %s.",
vg->seqno, dev_name(mda_dev), vg->name);
}
@@ -3447,14 +3438,15 @@ static int _check_devs_used_correspond_with_lv(struct dm_pool *mem, struct dm_li
static int _check_devs_used_correspond_with_vg(struct volume_group *vg)
{
struct dm_pool *mem;
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
char vgid[ID_LEN + 1];
struct pv_list *pvl;
struct lv_list *lvl;
struct dm_list *list;
struct device_list *dl;
int found_inconsistent = 0;
memcpy(vgid, &vg->id.uuid, ID_LEN);
strncpy(vgid, (const char *) vg->id.uuid, sizeof(vgid));
vgid[ID_LEN] = '\0';
/* Mark all PVs in VG as used. */
dm_list_iterate_items(pvl, &vg->pvs) {
@@ -3513,7 +3505,6 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
struct volume_group *vg,
struct lvmcache_info *info)
{
char pvid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct physical_volume *pv;
struct device *dev = lvmcache_device(info);
@@ -3537,9 +3528,7 @@ static struct physical_volume *_pv_read(struct cmd_context *cmd,
if (!alloc_pv_segment_whole_pv(vg->vgmem, pv))
goto_bad;
memcpy(pvid, &pv->id.uuid, ID_LEN);
lvmcache_fid_add_mdas(info, vg->fid, pvid, ID_LEN);
lvmcache_fid_add_mdas(info, vg->fid, (const char *) &pv->id, ID_LEN);
pv_set_fid(pv, vg->fid);
return pv;
bad:
@@ -3562,7 +3551,7 @@ static void _set_pv_device(struct format_instance *fid,
struct device *dev;
uint64_t size;
if (!(dev = lvmcache_device_from_pv_id(cmd, &pv->id, &pv->label_sector))) {
if (!(dev = lvmcache_device_from_pvid(cmd, &pv->id, &pv->label_sector))) {
if (!id_write_format(&pv->id, buffer, sizeof(buffer)))
buffer[0] = '\0';
@@ -4458,7 +4447,6 @@ int vg_is_foreign(struct volume_group *vg)
void vg_write_commit_bad_mdas(struct cmd_context *cmd, struct volume_group *vg)
{
char vgid[ID_LEN + 1] __attribute__((aligned(8))) = { 0 };
struct dm_list bad_mda_list;
struct mda_list *mdal;
struct metadata_area *mda;
@@ -4466,9 +4454,7 @@ void vg_write_commit_bad_mdas(struct cmd_context *cmd, struct volume_group *vg)
dm_list_init(&bad_mda_list);
memcpy(vgid, &vg->id.uuid, ID_LEN);
lvmcache_get_bad_mdas(cmd, vg->name, vgid, &bad_mda_list);
lvmcache_get_bad_mdas(cmd, vg->name, (const char *)&vg->id, &bad_mda_list);
dm_list_iterate_items(mdal, &bad_mda_list) {
mda = mdal->mda;
@@ -4897,7 +4883,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
*/
if (found_md_component) {
dm_list_iterate_items(pvl, &vg_ret->pvs) {
if (!(dev = lvmcache_device_from_pv_id(cmd, &pvl->pv->id, NULL)))
if (!(dev = lvmcache_device_from_pvid(cmd, &pvl->pv->id, NULL)))
continue;
/* dev_is_md_component set this flag if it was found */
@@ -5146,8 +5132,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const
if (!check_pv_dev_sizes(vg))
log_warn("WARNING: One or more devices used as PVs in VG %s have changed sizes.", vg->name);
if (cmd->check_devs_used)
_check_devs_used_correspond_with_vg(vg);
_check_devs_used_correspond_with_vg(vg);
if (!_access_vg_lock_type(cmd, vg, lockd_state, &failure)) {
/* Either FAILED_LOCK_TYPE or FAILED_LOCK_MODE were set. */

View File

@@ -531,7 +531,7 @@ int update_pool_metadata_min_max(struct cmd_context *cmd,
*/
struct id pv_id(const struct physical_volume *pv);
const struct format_type *pv_format_type(const struct physical_volume *pv);
struct id pv_vg_id(const struct physical_volume *pv);
struct id pv_vgid(const struct physical_volume *pv);
uint64_t find_min_mda_size(struct dm_list *mdas);
char *tags_format_and_copy(struct dm_pool *mem, const struct dm_list *tagsl);

View File

@@ -722,17 +722,6 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
return 1;
}
if (!extents) {
/* pmspare is not needed */
if (lv) {
log_debug_metadata("Dropping unused pool metadata spare LV %s.",
display_lvname(lv));
if (!lv_remove_single(vg->cmd, lv, DONT_PROMPT, 0))
return_0;
}
return 1;
}
if (extents > MAX_SIZE)
extents = MAX_SIZE;

View File

@@ -71,9 +71,9 @@ const struct format_type *pv_format_type(const struct physical_volume *pv)
return pv_field(pv, fmt);
}
struct id pv_vg_id(const struct physical_volume *pv)
struct id pv_vgid(const struct physical_volume *pv)
{
return pv_field(pv, vg_id);
return pv_field(pv, vgid);
}
struct device *pv_dev(const struct physical_volume *pv)
@@ -171,7 +171,7 @@ uint32_t pv_mda_count(const struct physical_volume *pv)
{
struct lvmcache_info *info;
info = lvmcache_info_from_pv_id(&pv->id, pv->dev, 0);
info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, pv->dev, 0);
return info ? lvmcache_mda_count(info) : UINT64_C(0);
}
@@ -191,7 +191,7 @@ uint32_t pv_mda_used_count(const struct physical_volume *pv)
struct lvmcache_info *info;
uint32_t used_count=0;
info = lvmcache_info_from_pv_id(&pv->id, pv->dev, 0);
info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, pv->dev, 0);
if (!info)
return 0;
lvmcache_foreach_mda(info, _count_unignored, &used_count);
@@ -236,7 +236,7 @@ int is_used_pv(const struct physical_volume *pv)
if (!(pv->fmt->features & FMT_PV_FLAGS))
return 0;
if (!(info = lvmcache_info_from_pv_id(&pv->id, pv->dev, 0))) {
if (!(info = lvmcache_info_from_pvid((const char *)&pv->id, pv->dev, 0))) {
log_error("Failed to find cached info for PV %s.", pv_dev_name(pv));
return -1;
}
@@ -279,9 +279,10 @@ uint64_t pv_mda_size(const struct physical_volume *pv)
{
struct lvmcache_info *info;
uint64_t min_mda_size = 0;
const char *pvid = (const char *)(&pv->id.uuid);
/* PVs could have 2 mdas of different sizes (rounding effect) */
if ((info = lvmcache_info_from_pv_id(&pv->id, pv->dev, 0)))
if ((info = lvmcache_info_from_pvid(pvid, pv->dev, 0)))
min_mda_size = lvmcache_smallest_mda_size(info);
return min_mda_size;
}
@@ -316,9 +317,10 @@ uint64_t lvmcache_info_mda_free(struct lvmcache_info *info)
uint64_t pv_mda_free(const struct physical_volume *pv)
{
const char *pvid = (const char *)&pv->id.uuid;
struct lvmcache_info *info;
if ((info = lvmcache_info_from_pv_id(&pv->id, pv->dev, 0)))
if ((info = lvmcache_info_from_pvid(pvid, pv->dev, 0)))
return lvmcache_info_mda_free(info);
return 0;
@@ -371,7 +373,7 @@ unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignor
struct _pv_mda_set_ignored_baton baton;
struct metadata_area *mda;
if (!(info = lvmcache_info_from_pv_id(&pv->id, pv->dev, 0)))
if (!(info = lvmcache_info_from_pvid((const char *)&pv->id.uuid, pv->dev, 0)))
return_0;
baton.mda_ignored = mda_ignored;
@@ -416,7 +418,8 @@ unsigned pv_mda_set_ignored(const struct physical_volume *pv, unsigned mda_ignor
struct label *pv_label(const struct physical_volume *pv)
{
struct lvmcache_info *info = lvmcache_info_from_pv_id(&pv->id, pv->dev, 0);
struct lvmcache_info *info =
lvmcache_info_from_pvid((const char *)&pv->id.uuid, pv->dev, 0);
if (info)
return lvmcache_get_label(info);

View File

@@ -33,11 +33,11 @@ struct physical_volume {
struct format_instance *fid;
/*
* vg_name and vg_id are used before the parent VG struct exists.
* vg_name and vgid are used before the parent VG struct exists.
* FIXME: Investigate removal/substitution with 'vg' fields.
*/
const char *vg_name;
struct id vg_id; /* variables named "vgid" are char ID_LEN+1 */
struct id vgid;
/*
* 'vg' is set and maintained when the PV belongs to a 'pvs'

View File

@@ -20,6 +20,7 @@
#include "lib/locking/locking.h"
#include "lib/config/defaults.h"
#include "lib/display/display.h"
#include "lib/format_text/archiver.h"
static struct pv_segment *_alloc_pv_segment(struct dm_pool *mem,
struct physical_volume *pv,

View File

@@ -356,9 +356,9 @@ static int _format_vdo_pool_data_lv(struct logical_volume *data_lv,
struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
const struct dm_vdo_target_params *vtp,
uint32_t *virtual_extents,
int format,
uint64_t vdo_pool_header_size)
int format)
{
const uint64_t header_size = DEFAULT_VDO_POOL_HEADER_SIZE;
const uint32_t extent_size = data_lv->vg->extent_size;
struct cmd_context *cmd = data_lv->vg->cmd;
struct logical_volume *vdo_pool_lv = data_lv;
@@ -379,7 +379,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
if (*virtual_extents)
vdo_logical_size =
_get_virtual_size(*virtual_extents, extent_size, vdo_pool_header_size);
_get_virtual_size(*virtual_extents, extent_size, header_size);
if (!dm_vdo_validate_target_params(vtp, vdo_logical_size))
return_0;
@@ -393,8 +393,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
} else {
log_verbose("Skiping VDO formating %s.", display_lvname(data_lv));
/* TODO: parse existing VDO data and retrieve vdo_logical_size */
if (!*virtual_extents)
vdo_logical_size = data_lv->size;
vdo_logical_size = data_lv->size;
}
if (!deactivate_lv(data_lv->vg->cmd, data_lv)) {
@@ -403,7 +402,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
return NULL;
}
vdo_logical_size -= 2 * vdo_pool_header_size;
vdo_logical_size -= 2 * header_size;
if (vdo_logical_size < extent_size) {
if (!*virtual_extents)
@@ -426,7 +425,7 @@ struct logical_volume *convert_vdo_pool_lv(struct logical_volume *data_lv,
vdo_pool_seg = first_seg(vdo_pool_lv);
vdo_pool_seg->segtype = vdo_pool_segtype;
vdo_pool_seg->vdo_params = *vtp;
vdo_pool_seg->vdo_pool_header_size = vdo_pool_header_size;
vdo_pool_seg->vdo_pool_header_size = DEFAULT_VDO_POOL_HEADER_SIZE;
vdo_pool_seg->vdo_pool_virtual_extents = *virtual_extents;
vdo_pool_lv->status |= LV_VDO_POOL;
@@ -453,7 +452,6 @@ int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy)
int fill_vdo_target_params(struct cmd_context *cmd,
struct dm_vdo_target_params *vtp,
uint64_t *vdo_pool_header_size,
struct profile *profile)
{
const char *policy;
@@ -502,7 +500,5 @@ int fill_vdo_target_params(struct cmd_context *cmd,
if (!set_vdo_write_policy(&vtp->write_policy, policy))
return_0;
*vdo_pool_header_size = 2 * find_config_tree_int64(cmd, allocation_vdo_pool_header_size_CFG, profile);
return 1;
}

View File

@@ -25,29 +25,19 @@ struct udev *_udev;
int udev_init_library_context(void)
{
if (_udev)
return 1;
if (getenv("DM_DISABLE_UDEV"))
return 0;
udev_unref(_udev);
if (!(_udev = udev_new())) {
log_error("Failed to create udev library context.");
return 0;
}
if (!udev_is_running()) {
udev_unref(_udev);
_udev = NULL;
return 0;
}
return 1;
}
void udev_fin_library_context(void)
{
if (_udev)
udev_unref(_udev);
udev_unref(_udev);
_udev = NULL;
}

View File

@@ -1919,7 +1919,7 @@ static int _sysfs_find_kernel_name(uint32_t major, uint32_t minor, char *buf, si
continue;
if ((sz = dm_snprintf(path, sizeof(path), "%sblock/%s/dev",
_sysfs_dir, name)) < 5) {
_sysfs_dir, name)) == -1) {
log_warn("Couldn't create path for %s.", name);
continue;
}

View File

@@ -23,7 +23,6 @@ else
endif
FSADMMAN = fsadm.8
VDOIMPORTMAN = vdoimport.8
BLKDEACTIVATEMAN = blkdeactivate.8
DMEVENTDMAN = dmeventd.8
DMFILEMAPDMAN = dmfilemapd.8
@@ -51,7 +50,7 @@ MAN8SYSTEMD_GENERATORS=lvm2-activation-generator.8
ifeq (,$(findstring $(MAKECMDGOALS), distclean all_man install_all_man))
MAN7 += lvmcache.7 lvmthin.7 lvmvdo.7
MAN8+=$(FSADMMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN) $(VDOIMPORTMAN)
MAN8+=$(FSADMMAN) $(LVMPOLLDMAN) $(LVMLOCKDMAN) $(LVMDBUSDMAN)
MAN8DM+=$(BLKDEACTIVATEMAN) $(DMEVENTDMAN) $(DMFILEMAPDMAN)
MAN8CLUSTER+=$(CMIRRORDMAN)
else
@@ -59,10 +58,6 @@ else
MAN8+=$(FSADMMAN)
endif
ifeq ("@VDOIMPORT@", "yes")
MAN8+=$(VDOIMPORTMAN)
endif
ifeq ("@BUILD_LVMDBUSD@", "yes")
MAN8+=$(LVMDBUSDMAN)
endif

View File

@@ -670,7 +670,7 @@ Convert LV to type thin-pool.
.RE
.P
.RS 4
LV1 types: linear striped cache raid error zero writecache
LV1 types: linear striped cache raid error zero
.RE
.P
\(em

View File

@@ -27,8 +27,6 @@ lvmdevices \(em Manage the devices file
\fB--deldev\fP \fIPV\fP
.br
\fB--delpvid\fP \fIString\fP
.br
\fB--deviceidtype\fP \fIString\fP
.br
\fB--devices\fP \fIPV\fP
.br
@@ -72,18 +70,18 @@ remove it from the devices file with lvmdevices --deldev. The
vgimportdevices(8) command adds all PVs from a VG to the devices file,
and updates the VG metadata to include device IDs of the PVs.
.P
Commands that add new devices to the devices file necessarily look outside
the existing devices file to find the devices being added. pvcreate,
vgcreate, and vgextend also look outside the devices file to create new
PVs and add those PVs to the devices file.
Commands adding new devices to the devices file necessarily look outside
the existing devices file to find the devices to add. pvcreate, vgcreate,
and vgextend also look outside the devices file to create new PVs and add
them to the devices file.
.P
LVM records devices in the devices file using hardware-specific IDs, such
as the WWID, and attempts to use subsystem-specific IDs for virtual device
types (which also aim to be as unique and stable as possible.) These
device IDs are also written in the VG metadata. When no hardware or
types (which also aim to be as unique and stable as possible.)
These device IDs are also written in the VG metadata. When no hardware or
virtual ID is available, lvm falls back using the unstable device name as
the device ID. When devnames are used as IDs, lvm performs extra scanning
to find devices if their devname changes, e.g. after reboot.
the device ID. When devnames are used, lvm performs extra scanning to
find devices if their devname changes, e.g. after reboot.
.P
When proper device IDs are used, an lvm command will not look at devices
outside the devices file, but when devnames are used as a fallback, lvm
@@ -97,13 +95,12 @@ overriding the devices file. The listed devices act as a sort of devices
file in terms of limiting which devices lvm will see and use. Devices
that are not listed will appear to be missing to the lvm command.
.P
Multiple devices files can be kept \fI#DEFAULT_SYS_DIR#/devices\fP, which
allows lvm to be used with different sets of devices. For example, system
devices do not need to be exposed to a specific application, and the
application can use lvm on its own devices that are not exposed to the
system. The option --devicesfile <filename> is used to select the devices
file to use with the command. Without the option set, the default system
devices file is used.
Multiple devices files can be kept in \fI#DEFAULT_SYS_DIR#/devices\fP, which allows lvm
to be used with different sets of devices, e.g. system devices do not need
to be exposed to a specific application, and the application can use lvm on
its own devices that are not exposed to the system. The option
--devicesfile <filename> is used to select the devices file to use with the
command. Without the option set, the default system devices file is used.
.P
Setting --devicesfile "" causes lvm to not use a devices file.
.P
@@ -123,45 +120,6 @@ if it does not yet exist.
.P
It is recommended to use lvm commands to make changes to the devices file to
ensure proper updates.
.P
The device ID and device ID type are included in the VG metadata and can
be reported with pvs -o deviceid,deviceidtype. (Note that the lvmdevices
command does not update VG metadata, but subsequent lvm commands modifying
the metadata will include the device ID.)
.P
Possible device ID types are:
.br
.IP \[bu] 2
.B sys_wwid
uses the wwid reported by sysfs. This is the first choice for non-virtual
devices.
.IP \[bu] 2
.B sys_serial
uses the serial number reported by sysfs. This is the second choice for
non-virtual devices.
.IP \[bu] 2
.B mpath_uuid
is used for dm multipath devices, reported by sysfs.
.IP \[bu] 2
.B crypt_uuid
is used for dm crypt devices, reported by sysfs.
.IP \[bu] 2
.B md_uuid
is used for md devices, reported by sysfs.
.B lvmlv_uuid
is used if a PV is placed on top of an lvm LV, reported by sysfs.
.IP \[bu] 2
.B loop_file
is used for loop devices, the backing file name repored by sysfs.
.IP \[bu] 2
.B devname
the device name is used if no other type applies.
.P
The default choice for device ID type can be overriden using lvmdevices
--addev --deviceidtype <type>. If the specified type is available for the
device it will be used, otherwise the device will be added using the type
that would otherwise be chosen.
.
.SH USAGE
.
@@ -211,8 +169,6 @@ Add a device to the devices file.
.br
.RS 4
.ad l
[ \fB--deviceidtype\fP \fIString\fP ]
.br
[ COMMON_OPTIONS ]
.ad b
.RE
@@ -258,6 +214,13 @@ Remove the devices file entry for the given PVID.
.P
\(em
.P
Common options for command:
.
.RS 4
.ad l
.ad b
.RE
.P
Common options for lvm:
.
.RS 4
@@ -345,13 +308,6 @@ Remove a device from the devices file.
Remove a device with the PVID from the devices file.
.
.HP
\fB--deviceidtype\fP \fIString\fP
.br
The type of device ID to use for the device.
If the specified type is available for the device,
then it will override the default type that lvm would use.
.
.HP
\fB--devices\fP \fIPV\fP
.br
Devices that the command can use. This option can be repeated

View File

@@ -1,92 +0,0 @@
.TH "FSADM" "8" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
.
.SH "NAME"
.
vdoimport \(em utility to import VDO volumes into a new volume group.
.
.SH SYNOPSIS
.
.PD 0
.ad l
.TP 10
.B vdoimport
.RI [ options ]
.IR device
.
.PD
.
.SH DESCRIPTION
.
vdoimport utility imports VDO volumes created and managed by
.BR vdo (8)
manager into
.BR lvm2 (8)
managed VDO LV. This is realized by moving VDO superblock by 2MiB
and creating lvm2 metadata at the front of this device. The operation is not reversible,
thus after conversion to lvm2 the access to VDO data is only possible with
.BR lvm2 (8)
commands,
.BR vdo (8)
manager no longer control such volume.
.
.SH OPTIONS
.
.TP
.BR -f | --force
Bypass some sanity checks.
.
.TP
.BR -h | --help
Display the help text.
.
.TP
.BR -n | --name
Specifies the name of converted VDO LV. When the name is not specified,
some automatic name is selected. In case the converted VDO volume is
already using LV a backend device, the name of this LV is used for VDO LV.
In this case also the of volume group must stay same.
.
.TP
.BR -v | --verbose
Be more verbose.
.
.TP
.BR -y | --yes
Answer "yes" at any prompts.
.
.TP
.BR --dry-run
Print commands without running them.
.
.
.SH DIAGNOSTICS
.
On successful completion, the status code is 0.
A status code of 1 is used for failure.
.
.SH EXAMPLES
.
Convert VDO volume created by vdo manager into logical volume LV1 with within volume group VG1.
.P
#
.B vdoimport --name VG1/LV1 /dev/mapper/vdo-volume
.
.SH ENVIRONMENT VARIABLES
.
.TP
.B TMPDIR
The temporary directory name for mount points. Defaults to "\fI/tmp\fP".
.TP
.B DM_DEV_DIR
The device directory name.
Defaults to "\fI/dev\fP" and must be an absolute path.
.
.SH SEE ALSO
.
.nh
.ad l
.BR lvm (8),
.BR lvm.conf (5),
.P
.BR vdo (8),
.BR vdo2lvm (8),

View File

@@ -393,6 +393,13 @@ Change the lock type for a shared VG.
.P
\(em
.P
Common options for command:
.
.RS 4
.ad l
.ad b
.RE
.P
Common options for lvm:
.
.RS 4

View File

@@ -46,6 +46,13 @@ Rewrite VG metadata to correct problems.
.ad b
.RE
.P
Common options for command:
.
.RS 4
.ad l
.ad b
.RE
.P
Common options for lvm:
.
.RS 4

View File

@@ -27,8 +27,6 @@ of both VGs fit into the destination VG's limits.
.br
[ \fB-l\fP|\fB--list\fP ]
.br
[ \fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ]
.br
[ COMMON_OPTIONS ]
.ad b
.RE
@@ -149,13 +147,6 @@ Display long help text.
Disable locking.
.
.HP
\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP
.br
Enable or disable the automatic creation and management of a
spare pool metadata LV in the VG. A spare metadata LV is reserved
space that can be used when repairing a pool.
.
.HP
\fB--profile\fP \fIString\fP
.br
An alias for --commandprofile or --metadataprofile, depending

View File

@@ -70,8 +70,6 @@ Common options for command:
.hy
]
.br
[ \fB--poolmetadataspare\fP \fBy\fP|\fBn\fP ]
.br
[ \fB--\fP[\fBvg\fP]\fBmetadatacopies\fP \fBall\fP|\fBunmanaged\fP|\fINumber\fP ]
.ad b
.RE
@@ -237,13 +235,6 @@ Move only PVs used by the named LV.
Disable locking.
.
.HP
\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP
.br
Enable or disable the automatic creation and management of a
spare pool metadata LV in the VG. A spare metadata LV is reserved
space that can be used when repairing a pool.
.
.HP
\fB--profile\fP \fIString\fP
.br
An alias for --commandprofile or --metadataprofile, depending

View File

@@ -31,10 +31,6 @@ ifeq ("@FSADM@", "yes")
LVM_SCRIPTS += fsadm.sh
endif
ifeq ("@VDOIMPORT@", "yes")
LVM_SCRIPTS += vdoimport.sh
endif
ifeq ("@BLKDEACTIVATE@", "yes")
DM_SCRIPTS += blkdeactivate.sh
endif

View File

@@ -1,376 +0,0 @@
#!/bin/bash
#
# Copyright (C) 2021 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU 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
#
# Author: Zdenek Kabelac <zkabelac at redhat.com>
#
# Script for converting VDO volumes to lvm2 VDO LVs
#
# Needed utilities:
# lvm, dmsetup,
# vdo, vdo2lvm,
# grep, awk, sed, blockdev, readlink, mkdir
#
# Conversion is using 'vdo convert' support from VDO manager to move
# existing VDO header by 2M which makes space to place in PV header
# and VG metadata area, and then create VDOPOOL LV and VDO LV in such VG.
#
set -euE -o pipefail
TOOL=vdoimport
_SAVEPATH=$PATH
PATH="/sbin:/usr/sbin:/bin:/usr/sbin:$PATH"
# user may override lvm location by setting LVM_BINARY
LVM=${LVM_BINARY:-lvm}
VDO=${VDO_BINARY:-vdo}
VDOCONF=${VDOCONF:-}
BLOCKDEV="blockdev"
READLINK="readlink"
READLINK_E="-e"
MKDIR="mkdir"
TEMPDIR="${TMPDIR:-/tmp}/${TOOL}_${RANDOM}$$"
DM_DEV_DIR="${DM_DEV_DIR:-/dev}"
DRY=0
VERB=""
FORCE=""
YES=""
# default name for converted VG and its VDO LV
NAME="vdovg/vdolvol"
# help message
tool_usage() {
echo "${TOOL}: Utility to convert VDO volume to VDO LV."
echo
echo " ${TOOL} [options] <vdo_device_path>"
echo
echo " Options:"
echo " -f | --force Bypass sanity checks"
echo " -h | --help Show this help message"
echo " -n | --name Specifies VG/LV name for converted VDO volume"
echo " -v | --verbose Be verbose"
echo " -y | --yes Answer \"yes\" at any prompts"
echo " --dry-run Print commands without running them"
exit
}
verbose() {
test -z "$VERB" || echo "$TOOL:" "$@"
}
# Support multi-line error messages
error() {
for i in "$@" ; do
echo "$TOOL: $i" >&2
done
cleanup 1
}
dry() {
if [ "$DRY" -ne 0 ]; then
verbose "Dry execution" "$@"
return 0
fi
verbose "Executing" "$@"
"$@"
}
cleanup() {
trap '' 2
rm -rf "$TEMPDIR"
# error exit status for break
exit "${1:-1}"
}
get_enabled_value_() {
case "$1" in
enabled) echo "1" ;;
*) echo "0" ;;
esac
}
get_kb_size_with_unit_() {
case "$1" in
*[kK]) echo $(( ${1%[kK]} )) ;;
*[mM]) echo $(( ${1%[mM]} * 1024 )) ;;
*[gG]) echo $(( ${1%[gG]} * 1024 * 1024 )) ;;
*[tT]) echo $(( ${1%[tT]} * 1024 * 1024 * 1024 )) ;;
*[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 * 1024 )) ;;
esac
}
get_mb_size_with_unit_() {
case "$1" in
*[mM]) echo $(( ${1%[mM]} )) ;;
*[gG]) echo $(( ${1%[gG]} * 1024 )) ;;
*[tT]) echo $(( ${1%[tT]} * 1024 * 1024 )) ;;
*[pP]) echo $(( ${1%[pP]} * 1024 * 1024 * 1024 )) ;;
esac
}
# Figure out largest possible extent size usable for VG
# $1 physical size
# $2 logical size
get_largest_extent_size_() {
local max=4
local i
local d
for i in 8 16 32 64 128 256 512 1024 2048 4096 ; do
d=$(( $1 / i ))
test $(( d * i )) -eq "$1" || break
d=$(( $2 / i ))
test $(( d * i )) -eq "$2" || break
max=$i
done
echo "$max"
}
# detect LV on the given device
# dereference device name if it is symbolic link
detect_lv_() {
local DEVICE=$1
local MAJOR
local MINOR
local SYSVOLUME
local MAJORMINOR
DEVICE=${1/#"${DM_DEV_DIR}/"/}
DEVICE=$("$READLINK" $READLINK_E "$DM_DEV_DIR/$DEVICE")
test -n "$DEVICE" || error "Cannot get readlink \"$1\"."
RDEVICE=$DEVICE
case "$RDEVICE" in
# hardcoded /dev since udev does not create these entries elsewhere
/dev/dm-[0-9]*)
read -r <"/sys/block/${RDEVICE#/dev/}/dm/name" SYSVOLUME 2>&1 && DEVICE="$DM_DEV_DIR/mapper/$SYSVOLUME"
read -r <"/sys/block/${RDEVICE#/dev/}/dev" MAJORMINOR 2>&1 || error "Cannot get major:minor for \"$DEVICE\"."
MAJOR=${MAJORMINOR%%:*}
MINOR=${MAJORMINOR##*:}
;;
*)
STAT=$(stat --format "MAJOR=\$((0x%t)) MINOR=\$((0x%T))" "$RDEVICE")
test -n "$STAT" || error "Cannot get major:minor for \"$DEVICE\"."
eval "$STAT"
;;
esac
eval "$(dmsetup info -c -j "$MAJOR" -m "$MINOR" -o uuid,name --noheadings --nameprefixes --separator ' ')"
}
# parse yaml config files into 'prefix_yaml_part_names=("value")' strings
parse_yaml_() {
local yaml_file=$1
local prefix=$2
local s
local w
local fs
s='[[:space:]]*'
w='[a-zA-Z0-9_.-]*'
fs="$(echo @|tr @ '\034')"
(
sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/[[:space:]]*$//g;' \
-e 's/\$/\\\$/g' \
-e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \
-e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
-e "s|^\($s\)\($w\)${s}[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" |
awk -F"$fs" '{
indent = length($1)/2;
if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";}
vname[indent] = $2;
for (i in vname) {if (i > indent) {delete vname[i]}}
if (length($3) > 0) {
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
printf("%s%s%s%s=(\"%s\")\n", "'"$prefix"'",vn, $2, conj[indent-1], $3);
}
}' |
sed -e 's/_=/+=/g' |
awk 'BEGIN {
FS="=";
OFS="="
}
/(-|\.).*=/ {
gsub("-|\\.", "_", $1)
}
{ print }'
) < "$yaml_file"
}
# convert existing VDO volume into lvm2 volume
convert2lvm_() {
local DEVICE=$1
local VGNAME=${NAME%/*}
local LVNAME=${NAME#*/}
local VDONAME
local TRVDONAME
local EXTENTSZ
local IS_LV=1
DM_UUID=""
detect_lv_ "$DEVICE"
case "$DM_UUID" in
LVM-*) eval "$(dmsetup splitname --nameprefixes --noheadings --separator ' ' "$DM_NAME")"
if [ -z "$VGNAME" ] || [ "$VGNAME" = "$LVNAME" ] ; then
VGNAME=$DM_VG_NAME
elif test "$VGNAME" != "$DM_VG_NAME" ; then
error "Volume group name \"$VGNAME\" does not match name \"$DM_VG_NAME\" for device \"$DEVICE\"."
fi
;;
*) IS_LV=0
# Check $VGNANE does not already exists
"$LVM" vgs "$VGNAME" && error "Cannot use already existing volume group name \"$VGNAME\"."
;;
esac
verbose "Checked whether device $1 is already LV ($IS_LV)."
"$MKDIR" -p -m 0000 "$TEMPDIR" || error "Failed to create $TEMPDIR."
verbose "Getting YAML VDO configuration."
"$VDO" printConfigFile $VDOCONF >"$TEMPDIR/vdoconf.yml"
VDONAME=$(awk -v DNAME="$DEVICE" '/.*VDOService$/ {VNAME=substr($1, 0, length($1) - 1)} /[[:space:]]*device:/ { if ($2 ~ DNAME) {print VNAME}}' "$TEMPDIR/vdoconf.yml")
TRVDONAME=$(echo "$VDONAME" | tr '-' '_')
# When VDO volume is 'active', check it's not mounted/being used
eval "$(dmsetup info -c -o open "$VDONAME" --noheadings --nameprefixes || true)"
test "${DM_OPEN:-0}" -eq 0 || error "Cannot converted VDO volume \"$VDONAME\" which is in use!"
#parse_yaml_ "$TEMPDIR/vdoconf.yml" _
eval "$(parse_yaml_ "$TEMPDIR/vdoconf.yml" _ | grep "$TRVDONAME" | sed -e "s/_config_vdos_$TRVDONAME/vdo/g")"
vdo_logicalSize=$(get_kb_size_with_unit_ "$vdo_logicalSize")
vdo_physicalSize=$(get_kb_size_with_unit_ "$vdo_physicalSize")
verbose "Going to convert physical sized VDO device $vdo_physicalSize KiB."
verbose "With logical volume of size $vdo_logicalSize KiB."
PARAMS=$(cat <<EOF
allocation {
vdo_use_compression = $(get_enabled_value_ "$vdo_compression")
vdo_use_deduplication = $(get_enabled_value_ "$vdo_deduplication")
vdo_use_metadata_hints=1
vdo_minimum_io_size = $vdo_logicalBlockSize
vdo_block_map_cache_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
vdo_block_map_period = $vdo_blockMapPeriod
vdo_check_point_frequency = $vdo_indexCfreq
vdo_use_sparse_index = $(get_enabled_value_ "$vdo_indexSparse")
vdo_index_memory_size_mb = $(awk "BEGIN {print $vdo_indexMemory * 1024}")
vdo_slab_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
vdo_ack_threads = $vdo_ackThreads
vdo_bio_threads = $vdo_bioThreads
vdo_bio_rotation = $vdo_bioRotationInterval
vdo_cpu_threads = $vdo_cpuThreads
vdo_hash_zone_threads = $vdo_hashZoneThreads
vdo_logical_threads = $vdo_logicalThreads
vdo_physical_threads = $vdo_physicalThreads
vdo_write_policy = $vdo_writePolicy
vdo_max_discard = $(( $(get_kb_size_with_unit_ "$vdo_maxDiscardSize") * 1024 ))
vdo_pool_header_size = 0
}
EOF
)
verbose "VDO conversion paramaters: $PARAMS"
verbose "Stopping VDO volume."
dry "$VDO" stop $VDOCONF --name "$VDONAME"
if [ "$IS_LV" = "0" ]; then
verbose "Moving VDO header by 2MiB."
dry "$VDO" convert $VDOCONF --force --name "$VDONAME"
dry "$LVM" pvcreate $YES --dataalignment 2M "$DEVICE" || {
error "Creation of PV on \"$DEVICE\" failed, while VDO header has been already moved!"
}
# Obtain free space in this new PV
# after 'vdo convert/vdo2lvm' call there is +2M free space at the front of the device
case "$DRY" in
0) pvfree=$("$LVM" pvs -o devsize --units b --nosuffix --noheadings "$DEVICE") ;;
*) pvfree=$("$BLOCKDEV" --getsize64 "$DEVICE") ;;
esac
pvfree=$(( pvfree / 1024 - 2048 )) # to KiB
else
pvfree=$("$LVM" lvs -o size --units b --nosuffix --noheadings "$VGNAME/$LVNAME")
pvfree=$(( pvfree / 1024 )) # to KiB
fi
# select largest possible extent size that can exactly express both sizes
EXTENTSZ=$(get_largest_extent_size_ "$pvfree" "$vdo_logicalSize")
if [ "$IS_LV" = "0" ]; then
verbose "Creating VG \"${NAME%/*}\" with extent size $EXTENTSZ KiB."
dry "$LVM" vgcreate $YES $VERB -s "${EXTENTSZ}k" "$VGNAME" "$DEVICE" || {
error "Creation of VG \"$VGNAME\" failed, while VDO header has been already moved!"
}
verbose "Creating VDO pool data LV from all extents in volume group $VGNAME."
dry "$LVM" lvcreate -Zn -Wn $YES $VERB -l100%VG -n "${LVNAME}_vpool" "$VGNAME"
else
# validate existing VG extent_size can express virtual VDO size
vg_extent_size=$("$LVM" vgs -o vg_extent_size --units b --nosuffix --noheadings "$VGNAME" || true)
vg_extent_size=$(( vg_extent_size / 1024 ))
test "$vg_extent_size" -le "$EXTENTSZ" || {
error "Please vgchange extent_size to at most $EXTENTSZ KiB or extend and align virtual size on $vg_extent_size KiB."
}
verbose "Renaming existing LV to be used as _vdata volume for VDO pool LV."
dry "$LVM" lvrename $YES $VERB "$VGNAME/$LVNAME" "$VGNAME/${LVNAME}_vpool" || {
error "Rename of LV \"$VGNAME/$LVNAME\" failed, while VDO header has been already moved!"
}
fi
verbose "Converting to VDO pool."
dry "$LVM" lvconvert $YES $VERB $FORCE --config "$PARAMS" -Zn -V "${vdo_logicalSize}k" -n "$LVNAME" --type vdo-pool "$VGNAME/${LVNAME}_vpool"
rm -fr "$TEMPDIR"
}
#############################
# start point of this script
# - parsing parameters
#############################
trap "cleanup 2" 2
test "$#" -eq 0 && tool_usage
while [ "$#" -ne 0 ]
do
case "$1" in
"") ;;
"-f"|"--force" ) FORCE="-f" ;;
"-h"|"--help" ) tool_usage ;;
"-n"|"--name" ) shift; NAME=$1 ;;
"-v"|"--verbose") VERB="-v" ;;
"-y"|"--yes" ) YES="-y" ;;
"--dry-run" ) DRY="1" ;;
"-*") error "Wrong argument \"$1\". (see: $TOOL --help)" ;;
*) DEVICENAME=$1 ;; # device name does not start with '-'
esac
shift
done
# do conversion
convert2lvm_ "$DEVICENAME"

View File

@@ -61,9 +61,6 @@ fi
%{_sbindir}/pvresize
%{_sbindir}/pvs
%{_sbindir}/pvscan
%if %{have_with vdo}
%{_sbindir}/vdoimport
%endif
%{_sbindir}/vgcfgbackup
%{_sbindir}/vgcfgrestore
%{_sbindir}/vgchange
@@ -125,9 +122,6 @@ fi
%{_mandir}/man8/pvresize.8.gz
%{_mandir}/man8/pvs.8.gz
%{_mandir}/man8/pvscan.8.gz
%if %{have_with vdo}
%{_mandir}/man8/vdoimport.8.gz
%endif
%{_mandir}/man8/vgcfgbackup.8.gz
%{_mandir}/man8/vgcfgrestore.8.gz
%{_mandir}/man8/vgchange.8.gz

View File

@@ -171,7 +171,7 @@ check_lvmlockd_dlm: .tests-stamp
endif
ifeq ("@BUILD_LVMLOCKD@", "yes")
check_lvmlockd_idm: .tests-stamp lib/idm_inject_failure
check_lvmlockd_idm: .tests-stamp
$(INSTALL_PROGRAM) lib/idm_inject_failure $(EXECDIR)
VERBOSE=$(VERBOSE) ./lib/runner \
--testdir . --outdir $(LVM_TEST_RESULTS) \
@@ -368,7 +368,6 @@ LIB = $(addprefix lib/, $(LIB_SECURETEST) $(LIB_DMSECURETEST) $(LIB_SHARED) $(LI
$(Q) $(LN_S) -f $(abs_top_srcdir)/conf/lvmdbusd.profile lib/
$(Q) $(LN_S) -f $(abs_top_srcdir)/conf/thin-performance.profile lib/
$(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/fsadm.sh lib/fsadm
$(Q) $(LN_S) -f $(abs_top_srcdir)/scripts/vdoimport.sh lib/vdoimport
@test "$(srcdir)" = . || \
for i in $(LIB_LVMLOCKD_CONF) $(LIB_MKE2FS_CONF); do \
test -n "$(Q)" || echo "$(LN_S) -f $(abs_top_srcdir)/test/lib/$$i lib/"; \

View File

@@ -1023,9 +1023,8 @@ prepare_devs() {
if test -n "$LVM_TEST_DEVICES_FILE"; then
mkdir -p "$TESTDIR/etc/lvm/devices" || true
rm "$TESTDIR/etc/lvm/devices/system.devices" || true
touch "$TESTDIR/etc/lvm/devices/system.devices"
for d in "${DEVICES[@]}"; do
lvmdevices --adddev "$d" || true
lvmdevices --adddev "$dev" || true
done
fi
@@ -1343,19 +1342,9 @@ prepare_vg() {
vgcreate $SHARED -s 512K "$vg" "${DEVICES[@]}"
}
extend_devices() {
test -z "$LVM_TEST_DEVICES_FILE" && return
for dev in "$@"; do
lvmdevices --adddev $dev
done
}
extend_filter() {
local filter
test -n "$LVM_TEST_DEVICES_FILE" && return
filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1)
for rx in "$@"; do
filter=$(echo "$filter" | sed -e "s:\\[:[ \"$rx\", :")
@@ -1366,8 +1355,6 @@ extend_filter() {
extend_filter_md() {
local filter
test -n "$LVM_TEST_DEVICES_FILE" && return
filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1)
for rx in "$@"; do
filter=$(echo "$filter" | sed -e "s:\\[:[ \"$rx\", :")
@@ -1383,33 +1370,21 @@ extend_filter_LVMTEST() {
hide_dev() {
local filter
if test -n "$LVM_TEST_DEVICES_FILE"; then
for dev in "$@"; do
lvmdevices --deldev $dev
done
else
filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1)
for dev in "$@"; do
filter=$(echo "$filter" | sed -e "s:\\[:[ \"r|$dev|\", :")
done
lvmconf "$filter"
fi
filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1)
for dev in "$@"; do
filter=$(echo "$filter" | sed -e "s:\\[:[ \"r|$dev|\", :")
done
lvmconf "$filter"
}
unhide_dev() {
local filter
if test -n "$LVM_TEST_DEVICES_FILE"; then
for dev in "$@"; do
lvmdevices -y --adddev $dev
done
else
filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1)
for dev in "$@"; do
filter=$(echo "$filter" | sed -e "s:\"r|$dev|\", ::")
done
lvmconf "$filter"
fi
filter=$(grep ^devices/global_filter CONFIG_VALUES | tail -n 1)
for dev in "$@"; do
filter=$(echo "$filter" | sed -e "s:\"r|$dev|\", ::")
done
lvmconf "$filter"
}
mkdev_md5sum() {
@@ -1458,13 +1433,13 @@ backup/backup = 0
devices/cache_dir = "$TESTDIR/etc"
devices/default_data_alignment = 1
devices/dir = "$DM_DEV_DIR"
devices/filter = "a|.*|"
devices/global_filter = [ "a|$DM_DEV_DIR/mapper/${PREFIX}.*pv[0-9_]*$|", "r|.*|" ]
devices/md_component_detection = 0
devices/scan = "$DM_DEV_DIR"
devices/sysfs_scan = 1
devices/write_cache_state = 0
devices/use_devicesfile = $LVM_TEST_DEVICES_FILE
devices/filter = "a|.*|"
devices/global_filter = [ "a|$DM_DEV_DIR/mapper/${PREFIX}.*pv[0-9_]*$|", "r|.*|" ]
global/abort_on_internal_errors = 1
global/cache_check_executable = "$LVM_TEST_CACHE_CHECK_CMD"
global/cache_dump_executable = "$LVM_TEST_CACHE_DUMP_CMD"

View File

@@ -63,8 +63,6 @@ test -n "$SKIP_WITH_LVMPOLLD" && test -n "$LVM_TEST_LVMPOLLD" && test -z "$LVM_T
test -n "$SKIP_WITH_LVMLOCKD" && test -n "$LVM_TEST_LVMLOCKD" && initskip
test -n "$SKIP_WITH_DEVICES_FILE" && test -n "$LVM_TEST_DEVICES_FILE" && initskip
unset CDPATH
export LVM_TEST_BACKING_DEVICE LVM_TEST_DEVDIR LVM_TEST_NODEBUG LVM_TEST_FAILURE

View File

@@ -45,7 +45,6 @@ for i in "$LOOP1" "$LOOP2"; do
done
aux extend_filter "a|$dev1|" "a|$dev2|"
aux extend_devices "$dev1" "$dev2"
not vgcreate --config 'devices/allow_mixed_block_sizes=0' $vg "$dev1" "$dev2"
vgcreate --config 'devices/allow_mixed_block_sizes=1' $vg "$dev1" "$dev2"

View File

@@ -287,6 +287,35 @@ pvscan --devices "$dev4" --cache -aay "$dev4"
check lv_field $vg2/$lv2 lv_active "active"
vgchange -an $vg2
# verify --devicesfile and --devices are not affected by a filter
# hide_dev excludes using existing filter
aux hide_dev "$dev2"
aux hide_dev "$dev4"
pvs --devicesfile test.devices "$dev1"
pvs --devicesfile test.devices "$dev2"
not pvs --devicesfile test.devices "$dev3"
not pvs --devicesfile test.devices "$dev4"
pvs --devices "$dev1" "$dev1"
pvs --devices "$dev2" "$dev2"
pvs --devices "$dev3" "$dev3"
pvs --devices "$dev4" "$dev4"
pvs --devices "$dev5" "$dev5"
pvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5" "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" | tee out
grep "$dev1" out
grep "$dev2" out
grep "$dev3" out
grep "$dev4" out
grep "$dev5" out
vgchange --devices "$dev1","$dev2" -ay $vg1
check lv_field $vg1/$lv1 lv_active "active"
lvchange --devices "$dev1","$dev2" -an $vg1/$lv1
vgchange --devices "$dev3","$dev4" -ay $vg2
check lv_field $vg2/$lv2 lv_active "active"
lvchange --devices "$dev3","$dev4" -an $vg2/$lv2
aux unhide_dev "$dev2"
aux unhide_dev "$dev4"
vgchange --devicesfile "" -an
vgremove --devicesfile "" -y $vg1
vgremove --devicesfile "" -y $vg2
@@ -607,61 +636,3 @@ grep "$dev2" "$DFDIR/test.devices"
rm "$DFDIR/test.devices"
vgcreate --devicesfile test.devices $vg3 "$dev3"
grep "$dev3" "$DFDIR/test.devices"
#
# verify --devicesfile and --devices are not affected by a filter
# This is last because it sets lvm.conf filter and
# I haven't found a way of removing the filter from
# the config after setting it.
#
aux lvmconf 'devices/use_devicesfile = 0'
wipe_all
rm -f "$DF"
rm -f "$DFDIR/test.devices"
vgcreate --devicesfile test.devices $vg1 "$dev1" "$dev2"
grep "$dev1" "$DFDIR/test.devices"
grep "$dev2" "$DFDIR/test.devices"
not ls "$DFDIR/system.devices"
# create two VGs outside the special devices file
vgcreate $vg2 "$dev3" "$dev4"
vgcreate $vg3 "$dev5" "$dev6"
not grep "$dev3" "$DFDIR/test.devices"
not grep "$dev5" "$DFDIR/test.devices"
not ls "$DFDIR/system.devices"
lvcreate -l4 -an -i2 -n $lv1 $vg1
lvcreate -l4 -an -i2 -n $lv2 $vg2
lvcreate -l4 -an -i2 -n $lv3 $vg3
aux lvmconf "devices/filter = [ \"r|$dev2|\" \"r|$dev4|\" ]"
pvs --devicesfile test.devices "$dev1"
pvs --devicesfile test.devices "$dev2"
not pvs --devicesfile test.devices "$dev3"
not pvs --devicesfile test.devices "$dev4"
pvs --devices "$dev1" "$dev1"
pvs --devices "$dev2" "$dev2"
pvs --devices "$dev3" "$dev3"
pvs --devices "$dev4" "$dev4"
pvs --devices "$dev5" "$dev5"
pvs --devices "$dev1","$dev2","$dev3","$dev4","$dev5" "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" | tee out
grep "$dev1" out
grep "$dev2" out
grep "$dev3" out
grep "$dev4" out
grep "$dev5" out
vgchange --devices "$dev1","$dev2" -ay $vg1
check lv_field $vg1/$lv1 lv_active "active"
lvchange --devices "$dev1","$dev2" -an $vg1/$lv1
vgchange --devices "$dev3","$dev4" -ay $vg2
check lv_field $vg2/$lv2 lv_active "active"
lvchange --devices "$dev3","$dev4" -an $vg2/$lv2
vgchange -an --devicesfile test.devices $vg1
vgremove -y --devicesfile test.devices $vg1
vgremove -y $vg2
vgremove -y $vg3

View File

@@ -60,7 +60,6 @@ for pass in "auto" "start" ; do
#
aux mdadm_create --metadata=1.0 --level="$MD_LEVEL" --chunk=64 --raid-devices=2 "$dev1" "$dev2"
mddev=$(< MD_DEV)
lvmdevices --adddev $mddev || true
pvcreate "$mddev"
PVIDMD=$(get pv_field "$mddev" uuid | tr -d - )
@@ -119,7 +118,6 @@ check inactive $vg $lv1
vgchange -an $vg
vgremove -f $vg
lvmdevices --deldev $mddev || true
aux cleanup_md_dev
@@ -131,7 +129,6 @@ aux cleanup_md_dev
aux mdadm_create --metadata=1.0 --level="$MD_LEVEL" --chunk=64 --raid-devices=2 "$dev1" "$dev2"
mddev=$(< MD_DEV)
lvmdevices --adddev $mddev || true
pvcreate "$mddev"
PVIDMD=$(get pv_field "$mddev" uuid | tr -d - )
@@ -191,7 +188,6 @@ aux udev_wait
aux mdadm_create --metadata=1.0 --level="$MD_LEVEL" --chunk=64 --raid-devices=2 "$dev1" "$dev2"
mddev=$(< MD_DEV)
lvmdevices --adddev $mddev || true
pvcreate "$mddev"
PVIDMD=$(get pv_field "$mddev" uuid | tr -d - )
@@ -239,7 +235,6 @@ test ! -f "$RUNDIR/lvm/pvs_online/$PVIDMD"
test ! -f "$RUNDIR/lvm/vgs_online/$vg"
aux enable_dev "$dev2"
lvmdevices --deldev $mddev || true
aux cleanup_md_dev
aux wipefs_a "$dev1"
@@ -255,7 +250,6 @@ if [ "$MD_LEVEL" = "1" ] ; then
#
aux mdadm_create --metadata=1.0 --level="$MD_LEVEL" --chunk=64 --raid-devices=3 "$dev1" "$dev2" "$dev4"
mddev=$(< MD_DEV)
lvmdevices --adddev $mddev || true
pvcreate "$mddev"
PVIDMD=$(get pv_field "$mddev" uuid | tr -d - )

View File

@@ -141,12 +141,6 @@ not cat $NEWHINTS
# Test that adding a new device and removing a device
# causes hints to be recreated.
#
# with a devices file the appearance of a new device on
# the system does not disturb lvm, so this test doesn't
# apply
#
if ! lvmdevices; then
not pvs "$dev5"
@@ -189,9 +183,6 @@ grep devs_hash $PREV > devs_hash1
grep devs_hash $HINTS > devs_hash2
not diff devs_hash1 devs_hash2
# end of new device test for non-devicesfile case
fi
#
# Test that hints don't change from a bunch of commands
# that use hints and shouldn't change it.

View File

@@ -72,10 +72,6 @@ aux extend_filter "a|$LOOP1|"
aux extend_filter "a|$LOOP2|"
aux extend_filter "a|$LOOP3|"
aux extend_filter "a|$LOOP4|"
aux extend_devices "$LOOP1"
aux extend_devices "$LOOP2"
aux extend_devices "$LOOP3"
aux extend_devices "$LOOP4"
aux lvmconf 'devices/scan = "/dev"'

View File

@@ -34,7 +34,6 @@ ls -la "${LOOP}"*
test -e "${LOOP}p1"
aux extend_filter "a|$LOOP|"
aux extend_devices "$LOOP"
# creation should fail for 'partitioned' loop device
not pvcreate -y "$LOOP"
@@ -58,7 +57,6 @@ ls -la "${LOOP}"*
test ! -e "${LOOP}p1"
aux extend_filter "a|$LOOP|"
aux extend_devices "$LOOP"
# creation should pass for 'non-partitioned' loop device
pvcreate -y "$LOOP"

View File

@@ -67,26 +67,4 @@ fail lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv
# Thin-pool CAN use cached data LV
lvconvert --yes --thinpool $vg/$lv
lvremove -f $vg
# Check we can active snapshot of cached external origin (BZ: 1967744)
lvcreate -T -L10M $vg/pool "$dev1"
lvcreate -L10M -n origin $vg "$dev1"
lvcreate -H -L4M -n CPOOL $vg/origin "$dev2"
# Use cached origin as external origin
lvconvert -y -T --thinpool $vg/pool --originname extorig origin
# Check we can easily create snapshot of such LV
lvcreate -y -kn -n snap -s $vg/origin
# Deactivate everything and do a component activation of _cmeta volume
lvchange -an $vg
lvchange -ay -y $vg/CPOOL_cpool_cmeta
# Now this must fail since component volume is active
not lvcreate -y -kn -n snap2 -s $vg/origin |& tee err
grep "cmeta is active" err
vgremove -f $vg

View File

@@ -118,14 +118,6 @@ mkdir -p "$mount_dir"
aux prepare_devs 6 70 # want 64M of usable space from each dev
# Tests with fs block sizes require a libblkid version that shows BLOCK_SIZE
vgcreate $vg "$dev1"
lvcreate -n $lv1 -L50 $vg
mkfs.xfs -f "$DM_DEV_DIR/$vg/$lv1"
blkid -c /dev/null "$DM_DEV_DIR/$vg/$lv1" | grep BLOCK_SIZE || skip
lvchange -an $vg
vgremove -ff $vg
# generate random data
dd if=/dev/urandom of=pattern bs=512K count=1

View File

@@ -11,16 +11,6 @@ test_description='Test duplicate PVs'
SKIP_WITH_LVMPOLLD=1
SKIP_WITH_CLVMD=1
# This test should work with real device ids (not devnames).
# When PVs are being overwritten by the test, the devices file is
# excluding them since with idtype=devname the devices file falls
# back to including devs based on PVIDs in the devices file,
# but the 'dd' is clobbering the PVIDs so those devs aren't included
# so the 'pvs' commands below don't report them.
# In general this is better behavior, but needs to be tested
# with proper device ids.
SKIP_WITH_DEVICES_FILE=1
. lib/inittest
aux prepare_devs 6 16

View File

@@ -20,8 +20,8 @@ aux prepare_devs 3
pvcreate "$dev1"
UUID1=$(get pv_field "$dev1" uuid)
pvcreate --devices "$dev2" -u "$UUID1" --norestorefile "$dev2"
pvcreate --devices "$dev3" -u "$UUID1" --norestorefile "$dev3"
pvcreate --config "devices{filter=[\"a|$dev2|\",\"r|.*|\"]}" -u "$UUID1" --norestorefile "$dev2"
pvcreate --config "devices{filter=[\"a|$dev3|\",\"r|.*|\"]}" -u "$UUID1" --norestorefile "$dev3"
pvscan --cache 2>&1 | tee out
@@ -35,7 +35,7 @@ test "$(grep -c $UUID1 main)" -eq 1
COUNT=$(grep --count "Not using device" warn)
[ "$COUNT" -eq 2 ]
pvs -o+uuid --devices $dev2 2>&1 | tee out
pvs -o+uuid --config "devices{filter=[\"a|$dev2|\",\"r|.*|\"]}" 2>&1 | tee out
rm warn main || true
grep WARNING out > warn || true

View File

@@ -64,7 +64,6 @@ dd if=dev1_backup of="$dev1" bs=1M
# prepare a VG with $dev1 and $dev both having 1 MDA
aux enable_dev "$dev2"
vgremove -ff $vg1
pvremove -ff -y "$dev1"
pvcreate --metadatacopies 1 "$dev1"
vgcreate $vg1 "$dev1" "$dev2"
@@ -123,7 +122,6 @@ dd if=dev1_backup of="$dev1" bs=1M
# prepare a VG with $dev1 and $dev both having 1 MDA
aux enable_dev "$dev2"
vgremove -ff $vg1
pvremove -ff -y "$dev1"
pvcreate --metadatacopies 1 "$dev1"
vgcreate $vg1 "$dev1" "$dev2"

View File

@@ -22,10 +22,6 @@ lvcreate --type snapshot -s -L10 -n $lv2 $vg --virtualsize 4T
lvcreate --type snapshot -s -L10 -n $lv3 $vg --virtualsize 4194300M
aux extend_filter_LVMTEST
aux lvmconf "devices/scan_lvs = 1"
aux extend_devices "$DM_DEV_DIR/$vg/$lv1"
aux extend_devices "$DM_DEV_DIR/$vg/$lv2"
aux extend_devices "$DM_DEV_DIR/$vg/$lv3"
vgcreate $vg1 "$DM_DEV_DIR/$vg/$lv2"

View File

@@ -26,9 +26,6 @@ aux extend_filter_LVMTEST
lvcreate -L10 -V10 -n $lv1 -T $vg/pool1
aux extend_devices "$DM_DEV_DIR/$vg/$lv1"
aux lvmconf "devices/scan_lvs = 1"
pvcreate "$DM_DEV_DIR/$vg/$lv1"
pvremove "$DM_DEV_DIR/$vg/$lv1"

View File

@@ -15,8 +15,8 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
# Sets 'scan_lvs = 1'
aux extend_filter_LVMTEST
aux lvmconf "devices/scan_lvs = 1"
aux prepare_pvs 1
@@ -24,7 +24,6 @@ vgcreate $SHARED $vg1 "$dev1"
lvcreate -l1 -n $lv1 $vg1
aux extend_devices "$DM_DEV_DIR/$vg1/$lv1"
pvcreate "$DM_DEV_DIR/$vg1/$lv1"
pvs "$DM_DEV_DIR/$vg1/$lv1"

View File

@@ -23,11 +23,10 @@ aux prepare_vg 5
# Create stacked device
lvcreate --type snapshot -s -L10 -n $lv1 $vg --virtualsize 100M
aux lvmconf "devices/scan_lvs = 1"
aux extend_filter_LVMTEST
aux extend_devices "$DM_DEV_DIR"/$vg/$lv1
vgcreate $vg1 "$DM_DEV_DIR"/$vg/$lv1
lvcreate -L20 -n $lv1 $vg1
lvcreate -L10 -n snap -s $vg1/$lv1

View File

@@ -26,10 +26,7 @@ get_devs
# Prepare large enough backend device
vgcreate -s 4M "$vg" "${DEVICES[@]}"
lvcreate --type snapshot -s -l 100%FREE -n $lv $vg --virtualsize 15P
aux lvmconf "devices/scan_lvs = 1"
aux extend_filter_LVMTEST
aux extend_devices "$DM_DEV_DIR/$vg/$lv"
# Check usability with largest extent size
pvcreate "$DM_DEV_DIR/$vg/$lv"

View File

@@ -77,8 +77,6 @@ lvremove -f $vg
lvcreate --type snapshot -s -l 100%FREE -n $lv $vg --virtualsize $TSIZE
aux extend_filter_LVMTEST
aux extend_devices "$DM_DEV_DIR/$vg/$lv"
aux lvmconf "devices/scan_lvs = 1"
aux lvmconf "activation/snapshot_autoextend_percent = 20" \
"activation/snapshot_autoextend_threshold = 50"

View File

@@ -15,15 +15,13 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip;
aux prepare_devs 6
get_devs
pvcreate -M2 "${DEVICES[@]}"
vgcreate $SHARED -M2 "$vg1" "$dev1" "$dev2" "$dev3"
vgcreate $SHARED -M2 "$vg2" "$dev4" "$dev5" "$dev6"
vgcreate --shared -M2 "$vg1" "$dev1" "$dev2" "$dev3"
vgcreate --shared -M2 "$vg2" "$dev4" "$dev5" "$dev6"
test_vg_thread1()
{

View File

@@ -15,8 +15,6 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip;
aux prepare_devs 8
get_devs
@@ -26,14 +24,14 @@ test_vg_thread1()
{
for i in {1..1000}
do
vgcreate $SHARED -M2 "$vg1" "$dev1" "$dev2" "$dev3"
vgcreate --shared -M2 "$vg1" "$dev1" "$dev2" "$dev3"
vgremove -ff $vg1
done
}
test_vg_thread2()
{
vgcreate $SHARED -M2 "$vg2" "$dev4" "$dev5" "$dev6"
vgcreate --shared -M2 "$vg2" "$dev4" "$dev5" "$dev6"
for i in {1..1000}
do

View File

@@ -15,8 +15,6 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
[ -z "$LVM_TEST_LOCK_TYPE_IDM" ] && skip;
aux prepare_vg 3
for i in {1..1000}

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