mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-16 04:23:50 +03:00
Compare commits
2 Commits
dev-dct-te
...
dev-dct-sc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31e2c4c1a6 | ||
|
|
09b0eea6a0 |
@@ -1 +1 @@
|
||||
1.02.181-git (2021-08-11)
|
||||
1.02.179-git (2021-05-07)
|
||||
|
||||
21
WHATS_NEW
21
WHATS_NEW
@@ -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
|
||||
|
||||
@@ -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
|
||||
================================
|
||||
|
||||
@@ -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
51
configure
vendored
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
15
configure.ac
15
configure.ac
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 '/'
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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 ''
|
||||
|
||||
@@ -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, '/');
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
354
lib/cache/lvmcache.c
vendored
@@ -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
16
lib/cache/lvmcache.h
vendored
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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\".",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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, §or, 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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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/"; \
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 - )
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"'
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user