mirror of
git://sourceware.org/git/lvm2.git
synced 2025-12-01 08:23:49 +03:00
Compare commits
58 Commits
dev-dct-de
...
dev-dct-lv
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f851d5062a | ||
|
|
3a1c12046f | ||
|
|
d0f94e763d | ||
|
|
01ef2f2525 | ||
|
|
0d957dcacc | ||
|
|
73121e3f07 | ||
|
|
8fa8dfdb8c | ||
|
|
55059e002a | ||
|
|
d393436727 | ||
|
|
6914942685 | ||
|
|
eee89a941e | ||
|
|
7a2090655d | ||
|
|
b3d7aff6a3 | ||
|
|
47c61907b4 | ||
|
|
51d9b686c0 | ||
|
|
b3407b16c1 | ||
|
|
58c6c9e9aa | ||
|
|
37733cd4eb | ||
|
|
db5277c971 | ||
|
|
3b0f9cec7e | ||
|
|
2bea95764e | ||
|
|
4a49851207 | ||
|
|
2ecfd503ed | ||
|
|
1b070f366b | ||
|
|
c302903dba | ||
|
|
bfe072e438 | ||
|
|
9dfa6f3879 | ||
|
|
a30013ff4f | ||
|
|
6d1e894a86 | ||
|
|
9aa3ea1c98 | ||
|
|
7ec0726ce3 | ||
|
|
ff6022d400 | ||
|
|
5e060b8fa7 | ||
|
|
dd28460017 | ||
|
|
494372b4ee | ||
|
|
5c50590b22 | ||
|
|
bee575d678 | ||
|
|
d14245c724 | ||
|
|
99f9bb28c9 | ||
|
|
6cb0b44cd2 | ||
|
|
fb7698b0ce | ||
|
|
151ce8b276 | ||
|
|
f840dbb320 | ||
|
|
8db3b11e4e | ||
|
|
23a9bd549a | ||
|
|
6e22be20c6 | ||
|
|
0937113146 | ||
|
|
86a0a652a9 | ||
|
|
f1578b4a5d | ||
|
|
72f0b637d2 | ||
|
|
c7a5b5cca0 | ||
|
|
bef1363c00 | ||
|
|
cc73d99886 | ||
|
|
7b1a857d5a | ||
|
|
4eb04c8c05 | ||
|
|
00c3069872 | ||
|
|
7e70041e32 | ||
|
|
1126be8f8d |
@@ -1 +1 @@
|
||||
1.02.185-git (2022-02-07)
|
||||
1.02.187-git (2022-05-18)
|
||||
|
||||
17
WHATS_NEW
17
WHATS_NEW
@@ -1,5 +1,18 @@
|
||||
Version 2.03.16 -
|
||||
====================================
|
||||
Version 2.03.17 -
|
||||
===============================
|
||||
Fix vdo_slab_size_mb value for converted VDO volume.
|
||||
|
||||
Version 2.03.16 - 18th May 2022
|
||||
===============================
|
||||
Fix segfault when handling selection with historical LVs.
|
||||
Add support --vdosettings with lvcreate, lvconvert, lvchange.
|
||||
Filtering multipath devices respects blacklist setting from multipath
|
||||
configuration.
|
||||
lvmdevices support for removing by device id using --deviceidtype and
|
||||
--deldev.
|
||||
Display writecache block size with lvs -o writecache_block_size.
|
||||
Improve cachesettings description in man lvmcache.
|
||||
Fix lossing of delete message on thin-pool extension.
|
||||
|
||||
Version 2.03.15 - 07th February 2022
|
||||
====================================
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
Version 1.02.185 -
|
||||
=====================================
|
||||
Version 1.02.187 -
|
||||
================================
|
||||
|
||||
Version 1.02.185 - 18th May 2022
|
||||
================================
|
||||
|
||||
Version 1.02.183 - 07th February 2022
|
||||
=====================================
|
||||
|
||||
20
configure.ac
20
configure.ac
@@ -1713,6 +1713,21 @@ AC_DEFINE_UNQUOTED(FSADM_PATH, ["$FSADM_PATH"], [Path to fsadm binary.])
|
||||
LVMIMPORTVDO_PATH="$SBINDIR/lvm_import_vdo"
|
||||
AC_DEFINE_UNQUOTED(LVMIMPORTVDO_PATH, ["$LVMIMPORTVDO_PATH"], [Path to lvm_import_vdo script.])
|
||||
|
||||
MOUNT_PATH="/usr/bin/mount"
|
||||
AC_DEFINE_UNQUOTED(MOUNT_PATH, ["$MOUNT_PATH"], [Path to mount binary.])
|
||||
|
||||
UMOUNT_PATH="/usr/bin/umount"
|
||||
AC_DEFINE_UNQUOTED(UMOUNT_PATH, ["$UMOUNT_PATH"], [Path to umount binary.])
|
||||
|
||||
E2FSCK_PATH="$SBINDIR/e2fsck"
|
||||
AC_DEFINE_UNQUOTED(E2FSCK_PATH, ["$E2FSCK_PATH"], [Path to e2fsck binary.])
|
||||
|
||||
RESIZE2FS_PATH="$SBINDIR/resize2fs"
|
||||
AC_DEFINE_UNQUOTED(RESIZE2FS_PATH, ["$RESIZE2FS_PATH"], [Path to resize2fs binary.])
|
||||
|
||||
XFS_GROWFS_PATH="$SBINDIR/xfs_growfs"
|
||||
AC_DEFINE_UNQUOTED(XFS_GROWFS_PATH, ["$XFS_GROWFS_PATH"], [Path to xfs_growfs binary.])
|
||||
|
||||
################################################################################
|
||||
dnl -- dmeventd pidfile and executable path
|
||||
if test "$BUILD_DMEVENTD" = yes; then
|
||||
@@ -1882,6 +1897,11 @@ AC_SUBST(DM_LIB_PATCHLEVEL)
|
||||
AC_SUBST(ELDFLAGS)
|
||||
AC_SUBST(FSADM)
|
||||
AC_SUBST(FSADM_PATH)
|
||||
AC_SUBST(MOUNT_PATH)
|
||||
AC_SUBST(UMOUNT_PATH)
|
||||
AC_SUBST(E2FSCK_PATH)
|
||||
AC_SUBST(RESIZE2FS_PATH)
|
||||
AC_SUBST(XFS_GROWFS_PATH)
|
||||
AC_SUBST(BLKDEACTIVATE)
|
||||
AC_SUBST(HAVE_LIBDL)
|
||||
AC_SUBST(HAVE_REALTIME)
|
||||
|
||||
@@ -220,38 +220,6 @@ def _dc(cmd, args):
|
||||
return c
|
||||
|
||||
|
||||
def parse(out):
|
||||
rc = []
|
||||
|
||||
for line in out.split('\n'):
|
||||
# This line includes separators, so process them
|
||||
if SEP in line:
|
||||
elem = line.split(SEP)
|
||||
cleaned_elem = []
|
||||
for e in elem:
|
||||
e = e.strip()
|
||||
cleaned_elem.append(e)
|
||||
|
||||
if len(cleaned_elem) > 1:
|
||||
rc.append(cleaned_elem)
|
||||
else:
|
||||
t = line.strip()
|
||||
if len(t) > 0:
|
||||
rc.append(t)
|
||||
return rc
|
||||
|
||||
|
||||
def parse_column_names(out, column_names):
|
||||
lines = parse(out)
|
||||
rc = []
|
||||
|
||||
for i in range(0, len(lines)):
|
||||
d = dict(list(zip(column_names, lines[i])))
|
||||
rc.append(d)
|
||||
|
||||
return rc
|
||||
|
||||
|
||||
def options_to_cli_args(options):
|
||||
rc = []
|
||||
for k, v in list(dict(options).items()):
|
||||
@@ -637,46 +605,6 @@ def lvm_full_report_json():
|
||||
return None
|
||||
|
||||
|
||||
def pv_retrieve_with_segs(device=None):
|
||||
d = []
|
||||
err = ""
|
||||
out = ""
|
||||
rc = 0
|
||||
|
||||
columns = ['pv_name', 'pv_uuid', 'pv_fmt', 'pv_size', 'pv_free',
|
||||
'pv_used', 'dev_size', 'pv_mda_size', 'pv_mda_free',
|
||||
'pv_ba_start', 'pv_ba_size', 'pe_start', 'pv_pe_count',
|
||||
'pv_pe_alloc_count', 'pv_attr', 'pv_tags', 'vg_name',
|
||||
'vg_uuid', 'pvseg_start', 'pvseg_size', 'segtype', 'pv_missing']
|
||||
|
||||
# Lvm has some issues where it returns failure when querying pvs when other
|
||||
# operations are in process, see:
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1274085
|
||||
for i in range(0, 10):
|
||||
cmd = _dc('pvs', ['-o', ','.join(columns)])
|
||||
|
||||
if device:
|
||||
cmd.extend(device)
|
||||
|
||||
rc, out, err = call(cmd)
|
||||
|
||||
if rc == 0:
|
||||
d = parse_column_names(out, columns)
|
||||
break
|
||||
else:
|
||||
time.sleep(0.2)
|
||||
log_debug("LVM Bug workaround, retrying pvs command...")
|
||||
|
||||
if rc != 0:
|
||||
msg = "We were unable to get pvs to return without error after " \
|
||||
"trying 10 times, RC=%d, STDERR=(%s), STDOUT=(%s)" % \
|
||||
(rc, err, out)
|
||||
log_error(msg)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
return d
|
||||
|
||||
|
||||
def pv_resize(device, size_bytes, create_options):
|
||||
cmd = ['pvresize']
|
||||
|
||||
@@ -831,53 +759,6 @@ def activate_deactivate(op, name, activate, control_flags, options):
|
||||
return call(cmd)
|
||||
|
||||
|
||||
def vg_retrieve(vg_specific):
|
||||
if vg_specific:
|
||||
assert isinstance(vg_specific, list)
|
||||
|
||||
columns = ['vg_name', 'vg_uuid', 'vg_fmt', 'vg_size', 'vg_free',
|
||||
'vg_sysid', 'vg_extent_size', 'vg_extent_count',
|
||||
'vg_free_count', 'vg_profile', 'max_lv', 'max_pv',
|
||||
'pv_count', 'lv_count', 'snap_count', 'vg_seqno',
|
||||
'vg_mda_count', 'vg_mda_free', 'vg_mda_size',
|
||||
'vg_mda_used_count', 'vg_attr', 'vg_tags']
|
||||
|
||||
cmd = _dc('vgs', ['-o', ','.join(columns)])
|
||||
|
||||
if vg_specific:
|
||||
cmd.extend(vg_specific)
|
||||
|
||||
d = []
|
||||
rc, out, err = call(cmd)
|
||||
if rc == 0:
|
||||
d = parse_column_names(out, columns)
|
||||
|
||||
return d
|
||||
|
||||
|
||||
def lv_retrieve_with_segments():
|
||||
columns = ['lv_uuid', 'lv_name', 'lv_path', 'lv_size',
|
||||
'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
|
||||
'origin', 'data_percent',
|
||||
'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
|
||||
'metadata_lv', 'seg_pe_ranges', 'segtype', 'lv_parent',
|
||||
'lv_role', 'lv_layout',
|
||||
'snap_percent', 'metadata_percent', 'copy_percent',
|
||||
'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
|
||||
|
||||
cmd = _dc('lvs', ['-a', '-o', ','.join(columns)])
|
||||
rc, out, err = call(cmd)
|
||||
|
||||
d = []
|
||||
|
||||
if rc == 0:
|
||||
d = parse_column_names(out, columns)
|
||||
|
||||
return d
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pv_data = pv_retrieve_with_segs()
|
||||
|
||||
for p in pv_data:
|
||||
print(str(p))
|
||||
# Leave this for future debug as needed
|
||||
pass
|
||||
|
||||
@@ -226,3 +226,21 @@ class Job(AutomatedProperties):
|
||||
def Uuid(self):
|
||||
import uuid
|
||||
return uuid.uuid1()
|
||||
|
||||
# Override the property "getters" implementation for the job interface, so a user can query a job while the queue
|
||||
# is processing items. Originally all the property get methods were this way, but we changed this in
|
||||
# e53454d6de07de56736303dd2157c3859f6fa848
|
||||
|
||||
# Properties
|
||||
# noinspection PyUnusedLocal
|
||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
||||
in_signature='ss', out_signature='v')
|
||||
def Get(self, interface_name, property_name):
|
||||
# Note: If we get an exception in this handler we won't know about it,
|
||||
# only the side effect of no returned value!
|
||||
return AutomatedProperties._get_prop(self, interface_name, property_name)
|
||||
|
||||
@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
|
||||
in_signature='s', out_signature='a{sv}')
|
||||
def GetAll(self, interface_name):
|
||||
return AutomatedProperties._get_all_prop(self, interface_name)
|
||||
|
||||
@@ -19,7 +19,6 @@ import sys
|
||||
import tempfile
|
||||
import time
|
||||
import select
|
||||
import copy
|
||||
|
||||
try:
|
||||
import simplejson as json
|
||||
@@ -31,8 +30,6 @@ from lvmdbusd.cfg import LVM_CMD
|
||||
from lvmdbusd.utils import log_debug, log_error, add_no_notify, make_non_block,\
|
||||
read_decoded
|
||||
|
||||
SHELL_PROMPT = "lvm> "
|
||||
|
||||
|
||||
def _quote_arg(arg):
|
||||
if len(shlex.split(arg)) > 1:
|
||||
@@ -43,10 +40,11 @@ def _quote_arg(arg):
|
||||
|
||||
class LVMShellProxy(object):
|
||||
|
||||
# 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!)
|
||||
def _read_until_prompt(self, no_output=False):
|
||||
# Read REPORT FD until we have a complete and valid JSON record or give
|
||||
# up trying to get one.
|
||||
#
|
||||
# Returns stdout, report (JSON), stderr
|
||||
def _read_response(self):
|
||||
stdout = ""
|
||||
report = ""
|
||||
stderr = ""
|
||||
@@ -58,6 +56,7 @@ class LVMShellProxy(object):
|
||||
# Try reading from all FDs to prevent one from filling up and causing
|
||||
# a hang. Keep reading until we get the prompt back and the report
|
||||
# FD does not contain valid JSON
|
||||
|
||||
while keep_reading:
|
||||
try:
|
||||
rd_fd = [
|
||||
@@ -75,35 +74,36 @@ class LVMShellProxy(object):
|
||||
stderr += read_decoded(self.lvm_shell.stderr)
|
||||
|
||||
# Check to see if the lvm process died on us
|
||||
if self.lvm_shell.poll():
|
||||
if self.lvm_shell.poll() is not None:
|
||||
raise Exception(self.lvm_shell.returncode, "%s" % stderr)
|
||||
|
||||
if stdout.endswith(SHELL_PROMPT):
|
||||
if no_output:
|
||||
keep_reading = False
|
||||
else:
|
||||
cur_report_len = len(report)
|
||||
if cur_report_len != 0:
|
||||
# Only bother to parse if we have more data
|
||||
if prev_report_len != cur_report_len:
|
||||
prev_report_len = cur_report_len
|
||||
# Parse the JSON if it's good we are done,
|
||||
# if not we will try to read some more.
|
||||
try:
|
||||
report_json = json.loads(report)
|
||||
keep_reading = False
|
||||
except ValueError:
|
||||
pass
|
||||
cur_report_len = len(report)
|
||||
if cur_report_len != 0:
|
||||
# Only bother to parse if we have more data and the last 2 characters match expected
|
||||
# complete JSON, prevents excessive JSON parsing attempts
|
||||
if prev_report_len != cur_report_len and report[-2:] == "}\n":
|
||||
prev_report_len = cur_report_len
|
||||
|
||||
if keep_reading:
|
||||
extra_passes -= 1
|
||||
if extra_passes <= 0:
|
||||
if len(report):
|
||||
raise ValueError("Invalid json: %s" %
|
||||
report)
|
||||
else:
|
||||
raise ValueError(
|
||||
"lvm returned no JSON output!")
|
||||
# Parse the JSON if it's good we are done,
|
||||
# if not we will try to read some more.
|
||||
try:
|
||||
report_json = json.loads(report)
|
||||
keep_reading = False
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# As long as lvm is spewing something on one of the FDs we will
|
||||
# keep trying. If we get a few timeouts with no activity, and
|
||||
# we don't have valid JSON, we will raise an error.
|
||||
if len(ready) == 0 and keep_reading:
|
||||
extra_passes -= 1
|
||||
if extra_passes <= 0:
|
||||
if len(report):
|
||||
raise ValueError("Invalid json: %s" %
|
||||
report)
|
||||
else:
|
||||
raise ValueError(
|
||||
"lvm returned no JSON output!")
|
||||
|
||||
except IOError as ioe:
|
||||
log_debug(str(ioe))
|
||||
@@ -118,49 +118,48 @@ class LVMShellProxy(object):
|
||||
self.lvm_shell.stdin.flush()
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Create a temp directory
|
||||
tmp_dir = tempfile.mkdtemp(prefix="lvmdbus_")
|
||||
tmp_file = "%s/lvmdbus_report" % (tmp_dir)
|
||||
|
||||
try:
|
||||
# Lets create fifo for the report output
|
||||
os.mkfifo(tmp_file, 0o600)
|
||||
except FileExistsError:
|
||||
pass
|
||||
# Create a fifo for the report output
|
||||
os.mkfifo(tmp_file, 0o600)
|
||||
|
||||
# We have to open non-blocking as the other side isn't open until
|
||||
# we actually fork the process.
|
||||
# Open the fifo for use to read and for lvm child process to write to.
|
||||
self.report_fd = os.open(tmp_file, os.O_NONBLOCK)
|
||||
self.report_stream = os.fdopen(self.report_fd, 'rb', 0)
|
||||
lvm_fd = os.open(tmp_file, os.O_WRONLY)
|
||||
|
||||
# Setup the environment for using our own socket for reporting
|
||||
local_env = copy.deepcopy(os.environ)
|
||||
local_env["LVM_REPORT_FD"] = "32"
|
||||
local_env["LVM_COMMAND_PROFILE"] = "lvmdbusd"
|
||||
# Set up the environment for using our own socket for reporting and disable the abort
|
||||
# logic if lvm logs too much, which easily happens when utilizing the lvm shell.
|
||||
local_env = {"LC_ALL": "C", "LVM_REPORT_FD": "%s" % lvm_fd, "LVM_COMMAND_PROFILE": "lvmdbusd",
|
||||
"LVM_LOG_FILE_MAX_LINES": "0"}
|
||||
|
||||
# Disable the abort logic if lvm logs too much, which easily happens
|
||||
# when utilizing the lvm shell.
|
||||
local_env["LVM_LOG_FILE_MAX_LINES"] = "0"
|
||||
# If any env variables contain LVM we will propagate them too
|
||||
for k, v in os.environ.items():
|
||||
if "LVM" in k:
|
||||
local_env[k] = v
|
||||
|
||||
# run the lvm shell
|
||||
self.lvm_shell = subprocess.Popen(
|
||||
[LVM_CMD + " 32>%s" % tmp_file],
|
||||
[LVM_CMD],
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=local_env,
|
||||
stderr=subprocess.PIPE, close_fds=True, shell=True)
|
||||
stderr=subprocess.PIPE, close_fds=True, pass_fds=(lvm_fd,), shell=False)
|
||||
|
||||
try:
|
||||
make_non_block(self.lvm_shell.stdout)
|
||||
make_non_block(self.lvm_shell.stderr)
|
||||
|
||||
# wait for the first prompt
|
||||
errors = self._read_until_prompt(no_output=True)[2]
|
||||
if errors and len(errors):
|
||||
raise RuntimeError(errors)
|
||||
# Close our copy of the lvm_fd, child process is open in its process space
|
||||
os.close(lvm_fd)
|
||||
|
||||
# Assume we are ready as we may not get the lvm prompt message depending on
|
||||
# if we are using readline or editline.
|
||||
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
# These will get deleted when the FD count goes to zero so we
|
||||
# These will get deleted when the FD count goes to zero, so we
|
||||
# can be sure to clean up correctly no matter how we finish
|
||||
os.unlink(tmp_file)
|
||||
os.rmdir(tmp_dir)
|
||||
@@ -170,7 +169,7 @@ class LVMShellProxy(object):
|
||||
self._write_cmd('lastlog\n')
|
||||
|
||||
# read everything from the STDOUT to the next prompt
|
||||
stdout, report_json, stderr = self._read_until_prompt()
|
||||
stdout, report_json, stderr = self._read_response()
|
||||
if 'log' in report_json:
|
||||
error_msg = ""
|
||||
# Walk the entire log array and build an error string
|
||||
@@ -204,7 +203,7 @@ class LVMShellProxy(object):
|
||||
self._write_cmd(cmd)
|
||||
|
||||
# read everything from the STDOUT to the next prompt
|
||||
stdout, report_json, stderr = self._read_until_prompt()
|
||||
stdout, report_json, stderr = self._read_response()
|
||||
|
||||
# Parse the report to see what happened
|
||||
if 'log' in report_json:
|
||||
@@ -237,24 +236,34 @@ class LVMShellProxy(object):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
shell = LVMShellProxy()
|
||||
in_line = "start"
|
||||
print("USING LVM BINARY: %s " % LVM_CMD)
|
||||
|
||||
try:
|
||||
while in_line:
|
||||
in_line = input("lvm> ")
|
||||
if in_line:
|
||||
start = time.time()
|
||||
ret, out, err = shell.call_lvm(in_line.split())
|
||||
end = time.time()
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "bisect":
|
||||
shell = LVMShellProxy()
|
||||
shell.exit_shell()
|
||||
else:
|
||||
shell = LVMShellProxy()
|
||||
in_line = "start"
|
||||
try:
|
||||
while in_line:
|
||||
in_line = input("lvm> ")
|
||||
if in_line:
|
||||
start = time.time()
|
||||
ret, out, err = shell.call_lvm(in_line.split())
|
||||
end = time.time()
|
||||
|
||||
print(("RC: %d" % ret))
|
||||
print(("OUT:\n%s" % out))
|
||||
print(("ERR:\n%s" % err))
|
||||
print(("RC: %d" % ret))
|
||||
print(("OUT:\n%s" % out))
|
||||
print(("ERR:\n%s" % err))
|
||||
|
||||
print("Command = %f seconds" % (end - start))
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except EOFError:
|
||||
pass
|
||||
print("Command = %f seconds" % (end - start))
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except EOFError:
|
||||
pass
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
@@ -13,14 +13,13 @@ from collections import OrderedDict
|
||||
|
||||
import pprint as prettyprint
|
||||
import os
|
||||
import sys
|
||||
|
||||
from lvmdbusd import cmdhandler
|
||||
from lvmdbusd.utils import log_debug, log_error
|
||||
|
||||
|
||||
class DataStore(object):
|
||||
def __init__(self, usejson=True, vdo_support=False):
|
||||
def __init__(self, vdo_support=False):
|
||||
self.pvs = {}
|
||||
self.vgs = {}
|
||||
self.lvs = {}
|
||||
@@ -35,41 +34,9 @@ class DataStore(object):
|
||||
self.lvs_in_vgs = {}
|
||||
self.pvs_in_vgs = {}
|
||||
|
||||
# self.refresh()
|
||||
self.num_refreshes = 0
|
||||
|
||||
if usejson:
|
||||
self.json = cmdhandler.supports_json()
|
||||
else:
|
||||
self.json = usejson
|
||||
|
||||
self.vdo_support = vdo_support
|
||||
|
||||
@staticmethod
|
||||
def _insert_record(table, key, record, allowed_multiple):
|
||||
if key in table:
|
||||
existing = table[key]
|
||||
|
||||
for rec_k, rec_v in record.items():
|
||||
if rec_k in allowed_multiple:
|
||||
# This column name allows us to store multiple value for
|
||||
# each type
|
||||
if not isinstance(existing[rec_k], list):
|
||||
existing_value = existing[rec_k]
|
||||
existing[rec_k] = [existing_value, rec_v]
|
||||
else:
|
||||
existing[rec_k].append(rec_v)
|
||||
else:
|
||||
# If something is not expected to have changing values
|
||||
# lets ensure that
|
||||
if existing[rec_k] != rec_v:
|
||||
raise RuntimeError(
|
||||
"existing[%s]=%s != %s" %
|
||||
(rec_k, str(existing[rec_k]),
|
||||
str(rec_v)))
|
||||
else:
|
||||
table[key] = record
|
||||
|
||||
@staticmethod
|
||||
def _pvs_parse_common(c_pvs, c_pvs_in_vgs, c_lookup):
|
||||
for p in c_pvs.values():
|
||||
@@ -84,22 +51,6 @@ class DataStore(object):
|
||||
# Lookup for translating between /dev/<name> and pv uuid
|
||||
c_lookup[p['pv_name']] = p['pv_uuid']
|
||||
|
||||
@staticmethod
|
||||
def _parse_pvs(_pvs):
|
||||
pvs = sorted(_pvs, key=lambda pk: pk['pv_name'])
|
||||
|
||||
c_pvs = OrderedDict()
|
||||
c_lookup = {}
|
||||
c_pvs_in_vgs = {}
|
||||
|
||||
for p in pvs:
|
||||
DataStore._insert_record(
|
||||
c_pvs, p['pv_uuid'], p,
|
||||
['pvseg_start', 'pvseg_size', 'segtype'])
|
||||
|
||||
DataStore._pvs_parse_common(c_pvs, c_pvs_in_vgs, c_lookup)
|
||||
return c_pvs, c_lookup, c_pvs_in_vgs
|
||||
|
||||
@staticmethod
|
||||
def _parse_pvs_json(_all):
|
||||
|
||||
@@ -141,28 +92,6 @@ class DataStore(object):
|
||||
|
||||
return c_pvs, c_lookup, c_pvs_in_vgs
|
||||
|
||||
@staticmethod
|
||||
def _parse_vgs(_vgs):
|
||||
vgs = sorted(_vgs, key=lambda vk: vk['vg_uuid'])
|
||||
|
||||
c_vgs = OrderedDict()
|
||||
c_lookup = {}
|
||||
|
||||
for i in vgs:
|
||||
vg_name = i['vg_name']
|
||||
|
||||
# Lvm allows duplicate vg names. When this occurs, each subsequent
|
||||
# matching VG name will be called vg_name:vg_uuid. Note: ':' is an
|
||||
# invalid character for lvm VG names
|
||||
if vg_name in c_lookup:
|
||||
vg_name = "%s:%s" % (vg_name, i['vg_uuid'])
|
||||
i['vg_name'] = vg_name
|
||||
|
||||
c_lookup[vg_name] = i['vg_uuid']
|
||||
DataStore._insert_record(c_vgs, i['vg_uuid'], i, [])
|
||||
|
||||
return c_vgs, c_lookup
|
||||
|
||||
@staticmethod
|
||||
def _parse_vgs_json(_all):
|
||||
|
||||
@@ -227,22 +156,6 @@ class DataStore(object):
|
||||
|
||||
return c_lvs, c_lvs_in_vgs, c_lvs_hidden, c_lv_full_lookup
|
||||
|
||||
@staticmethod
|
||||
def _parse_lvs(_lvs):
|
||||
lvs = sorted(_lvs, key=lambda vk: vk['lv_name'])
|
||||
|
||||
c_lvs = OrderedDict()
|
||||
c_lv_full_lookup = OrderedDict()
|
||||
|
||||
for i in lvs:
|
||||
full_name = "%s/%s" % (i['vg_name'], i['lv_name'])
|
||||
c_lv_full_lookup[full_name] = i['lv_uuid']
|
||||
DataStore._insert_record(
|
||||
c_lvs, i['lv_uuid'], i,
|
||||
['seg_pe_ranges', 'segtype'])
|
||||
|
||||
return DataStore._parse_lvs_common(c_lvs, c_lv_full_lookup)
|
||||
|
||||
def _parse_lvs_json(self, _all):
|
||||
|
||||
c_lvs = OrderedDict()
|
||||
@@ -401,22 +314,12 @@ class DataStore(object):
|
||||
log_debug("lvmdb - refresh entry")
|
||||
|
||||
# Grab everything first then parse it
|
||||
if self.json:
|
||||
# Do a single lvm retrieve for everything in json
|
||||
a = cmdhandler.lvm_full_report_json()
|
||||
# Do a single lvm retrieve for everything in json
|
||||
a = cmdhandler.lvm_full_report_json()
|
||||
|
||||
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs_json(a)
|
||||
_vgs, _vgs_lookup = self._parse_vgs_json(a)
|
||||
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs_json(a)
|
||||
|
||||
else:
|
||||
_raw_pvs = cmdhandler.pv_retrieve_with_segs()
|
||||
_raw_vgs = cmdhandler.vg_retrieve(None)
|
||||
_raw_lvs = cmdhandler.lv_retrieve_with_segments()
|
||||
|
||||
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs(_raw_pvs)
|
||||
_vgs, _vgs_lookup = self._parse_vgs(_raw_vgs)
|
||||
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs(_raw_lvs)
|
||||
_pvs, _pvs_lookup, _pvs_in_vgs = self._parse_pvs_json(a)
|
||||
_vgs, _vgs_lookup = self._parse_vgs_json(a)
|
||||
_lvs, _lvs_in_vgs, _lvs_hidden, _lvs_lookup = self._parse_lvs_json(a)
|
||||
|
||||
# Set all
|
||||
self.pvs = _pvs
|
||||
@@ -527,13 +430,7 @@ class DataStore(object):
|
||||
if __name__ == "__main__":
|
||||
pp = prettyprint.PrettyPrinter(indent=4)
|
||||
|
||||
use_json = False
|
||||
|
||||
if len(sys.argv) != 1:
|
||||
print(len(sys.argv))
|
||||
use_json = True
|
||||
|
||||
ds = DataStore(use_json)
|
||||
ds = DataStore()
|
||||
ds.refresh()
|
||||
|
||||
print("PVS")
|
||||
|
||||
@@ -29,7 +29,7 @@ from .utils import log_debug, log_error
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from .cmdhandler import LvmFlightRecorder, supports_vdo
|
||||
from .cmdhandler import LvmFlightRecorder, supports_vdo, supports_json
|
||||
from .request import RequestEntry
|
||||
|
||||
|
||||
@@ -116,6 +116,15 @@ def main():
|
||||
os.environ["LC_ALL"] = "C"
|
||||
|
||||
cfg.args = parser.parse_args()
|
||||
|
||||
if not cfg.args.use_json:
|
||||
log_error("Daemon no longer supports lvm without JSON support, exiting!")
|
||||
sys.exit(1)
|
||||
else:
|
||||
if not supports_json():
|
||||
log_error("Un-supported version of LVM, daemon requires JSON output, exiting!")
|
||||
sys.exit(1)
|
||||
|
||||
cfg.create_request_entry = RequestEntry
|
||||
|
||||
# We create a flight recorder in cmdhandler too, but we replace it here
|
||||
@@ -127,6 +136,8 @@ def main():
|
||||
log_error("You cannot specify --lvmshell and --nojson")
|
||||
sys.exit(1)
|
||||
|
||||
log_debug("Using lvm binary: %s" % cfg.LVM_CMD)
|
||||
|
||||
# We will dynamically add interfaces which support vdo if it
|
||||
# exists.
|
||||
cfg.vdo_support = supports_vdo()
|
||||
@@ -155,7 +166,7 @@ def main():
|
||||
cfg.om = Lvm(BASE_OBJ_PATH)
|
||||
cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
|
||||
|
||||
cfg.db = lvmdb.DataStore(cfg.args.use_json, cfg.vdo_support)
|
||||
cfg.db = lvmdb.DataStore(vdo_support=cfg.vdo_support)
|
||||
|
||||
# Using a thread to process requests, we cannot hang the dbus library
|
||||
# thread that is handling the dbus interface
|
||||
|
||||
@@ -684,10 +684,10 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv) {
|
||||
if (rv < 0) {
|
||||
log_error("clear lv resource area %llu error %d",
|
||||
(unsigned long long)offset, rv);
|
||||
break;
|
||||
return rv;
|
||||
}
|
||||
offset += align_size;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,10 @@ enum dm_vdo_write_policy {
|
||||
struct dm_vdo_target_params {
|
||||
uint32_t minimum_io_size; // in sectors
|
||||
uint32_t block_map_cache_size_mb;
|
||||
uint32_t block_map_era_length; // format period
|
||||
|
||||
union {
|
||||
uint32_t block_map_era_length; // format period
|
||||
uint32_t block_map_period; // supported alias
|
||||
};
|
||||
uint32_t check_point_frequency;
|
||||
uint32_t index_memory_size_mb; // format
|
||||
|
||||
|
||||
@@ -132,8 +132,13 @@
|
||||
/* Define to 1 to include the LVM editline shell. */
|
||||
#undef EDITLINE_SUPPORT
|
||||
|
||||
/* Path to fsadm binary. */
|
||||
/* Paths to binaries. */
|
||||
#undef FSADM_PATH
|
||||
#undef MOUNT_PATH
|
||||
#undef UMOUNT_PATH
|
||||
#undef E2FSCK_PATH
|
||||
#undef RESIZE2FS_PATH
|
||||
#undef XFS_GROWFS_PATH
|
||||
|
||||
/* Define to use GNU versioning in the shared library. */
|
||||
#undef GNU_SYMVER
|
||||
|
||||
@@ -40,7 +40,9 @@ SOURCES =\
|
||||
device/dev-luks.c \
|
||||
device/dev-dasd.c \
|
||||
device/dev-lvm1-pool.c \
|
||||
device/filesystem.c \
|
||||
device/online.c \
|
||||
device/parse_vpd.c \
|
||||
display/display.c \
|
||||
error/errseg.c \
|
||||
unknown/unknown.c \
|
||||
@@ -54,7 +56,6 @@ SOURCES =\
|
||||
filters/filter-partitioned.c \
|
||||
filters/filter-type.c \
|
||||
filters/filter-usable.c \
|
||||
filters/filter-internal.c \
|
||||
filters/filter-signature.c \
|
||||
filters/filter-deviceid.c \
|
||||
format_text/archive.c \
|
||||
|
||||
19
lib/commands/cmd_enum.h
Normal file
19
lib/commands/cmd_enum.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef _CMD_ENUM_H
|
||||
#define _CMD_ENUM_H
|
||||
|
||||
/*
|
||||
* tools/cmds.h is generated by the Makefile. For each command definition
|
||||
* in command-lines.in, cmds.h contains:
|
||||
* cmd(foo_CMD, foo)
|
||||
*
|
||||
* This header adds each of the foo_CMD's into an enum, so there's
|
||||
* a unique integer identifier for each command definition.
|
||||
*/
|
||||
|
||||
enum {
|
||||
#define cmd(a, b) a ,
|
||||
#include "../tools/cmds.h"
|
||||
#undef cmd
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1128,7 +1128,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_FILTERS 11
|
||||
#define MAX_FILTERS 10
|
||||
|
||||
static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
|
||||
{
|
||||
@@ -1143,13 +1143,6 @@ static struct dev_filter *_init_filter_chain(struct cmd_context *cmd)
|
||||
* Update MAX_FILTERS definition above when adding new filters.
|
||||
*/
|
||||
|
||||
/* internal filter used by command processing. */
|
||||
if (!(filters[nr_filt] = internal_filter_create())) {
|
||||
log_error("Failed to create internal device filter");
|
||||
goto bad;
|
||||
}
|
||||
nr_filt++;
|
||||
|
||||
/* global regex filter. Optional. */
|
||||
if ((cn = find_config_tree_node(cmd, devices_global_filter_CFG, NULL))) {
|
||||
if (!(filters[nr_filt] = regex_filter_create(cn->v, 0, 1))) {
|
||||
@@ -1912,7 +1905,6 @@ int refresh_toolcontext(struct cmd_context *cmd)
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(cmd, &cmd->formats);
|
||||
|
||||
devices_file_exit(cmd);
|
||||
if (!dev_cache_exit())
|
||||
stack;
|
||||
_destroy_dev_types(cmd);
|
||||
@@ -2041,7 +2033,6 @@ void destroy_toolcontext(struct cmd_context *cmd)
|
||||
_destroy_segtypes(&cmd->segtypes);
|
||||
_destroy_formats(cmd, &cmd->formats);
|
||||
_destroy_filters(cmd);
|
||||
devices_file_exit(cmd);
|
||||
dev_cache_exit();
|
||||
_destroy_dev_types(cmd);
|
||||
_destroy_tags(cmd);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "lib/device/dev-cache.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
#include "lib/commands/cmd_enum.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
@@ -94,6 +95,7 @@ struct cmd_context {
|
||||
const char *name; /* needed before cmd->command is set */
|
||||
struct command_name *cname;
|
||||
struct command *command;
|
||||
int command_enum; /* duplicate from command->command_enum for lib code */
|
||||
char **argv;
|
||||
struct arg_values *opt_arg_values;
|
||||
struct dm_list arg_value_groups;
|
||||
|
||||
@@ -80,6 +80,7 @@ static void _dev_init(struct device *dev)
|
||||
|
||||
dm_list_init(&dev->aliases);
|
||||
dm_list_init(&dev->ids);
|
||||
dm_list_init(&dev->wwids);
|
||||
}
|
||||
|
||||
void dev_destroy_file(struct device *dev)
|
||||
@@ -383,6 +384,22 @@ out:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_sysfs_binary(const char *path, char *buf, size_t buf_size, int *retlen)
|
||||
{
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
ret = read(fd, buf, buf_size);
|
||||
close(fd);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
*retlen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_sysfs_value(const char *path, char *buf, size_t buf_size, int error_if_no_value)
|
||||
{
|
||||
FILE *fp;
|
||||
@@ -1336,6 +1353,7 @@ int dev_cache_exit(void)
|
||||
dm_hash_iterate(n, _cache.names) {
|
||||
dev = (struct device *) dm_hash_get_data(_cache.names, n);
|
||||
free_dids(&dev->ids);
|
||||
free_wwids(&dev->wwids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1410,7 +1428,7 @@ static void _remove_alias(struct device *dev, const char *name)
|
||||
* deactivated LV. Those old paths are all invalid and are dropped here.
|
||||
*/
|
||||
|
||||
static void _verify_aliases(struct device *dev)
|
||||
void dev_cache_verify_aliases(struct device *dev)
|
||||
{
|
||||
struct dm_str_list *strl, *strl2;
|
||||
struct stat st;
|
||||
@@ -1459,7 +1477,7 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
|
||||
_remove_alias(dev, name);
|
||||
|
||||
/* Remove any other names in dev->aliases that are incorrect. */
|
||||
_verify_aliases(dev);
|
||||
dev_cache_verify_aliases(dev);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1606,18 +1624,6 @@ static struct device *_dev_cache_get(struct cmd_context *cmd, const char *name,
|
||||
return dev;
|
||||
|
||||
ret = f->passes_filter(cmd, f, dev, NULL);
|
||||
|
||||
/*
|
||||
* This might happen if this function is called before
|
||||
* filters can do i/o. I don't think this will happen
|
||||
* any longer and this EAGAIN case can be removed.
|
||||
*/
|
||||
if (ret == -EAGAIN) {
|
||||
log_debug_devs("dev_cache_get filter deferred %s", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
log_debug_devs("dev_cache_get filter excludes %s", dev_name(dev));
|
||||
return NULL;
|
||||
@@ -1688,16 +1694,9 @@ struct device *dev_iter_get(struct cmd_context *cmd, struct dev_iter *iter)
|
||||
|
||||
f = iter->filter;
|
||||
|
||||
if (f && !(d->flags & DEV_REGULAR)) {
|
||||
if (f && !(d->flags & DEV_REGULAR))
|
||||
ret = f->passes_filter(cmd, f, d, NULL);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
log_debug_devs("get device by iter defer filter %s", dev_name(d));
|
||||
d->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f || (d->flags & DEV_REGULAR) || ret)
|
||||
return d;
|
||||
}
|
||||
@@ -1882,6 +1881,15 @@ int setup_devices(struct cmd_context *cmd)
|
||||
|
||||
file_exists = devices_file_exists(cmd);
|
||||
|
||||
/*
|
||||
* Fail if user specifies a file name that doesn't exist and
|
||||
* the command is not creating a new devices file.
|
||||
*/
|
||||
if (!file_exists && !cmd->create_edit_devices_file && cmd->devicesfile && strlen(cmd->devicesfile)) {
|
||||
log_error("Devices file not found: %s", cmd->devices_file_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removing the devices file is another way of disabling the use of
|
||||
* a devices file, unless the command creates the devices file.
|
||||
|
||||
@@ -55,6 +55,7 @@ int dev_cache_add_dir(const char *path);
|
||||
struct device *dev_cache_get(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
struct device *dev_cache_get_existing(struct cmd_context *cmd, const char *name, struct dev_filter *f);
|
||||
struct device *dev_cache_get_by_devt(struct cmd_context *cmd, dev_t devt);
|
||||
void dev_cache_verify_aliases(struct device *dev);
|
||||
|
||||
struct device *dev_hash_get(const char *name);
|
||||
|
||||
@@ -73,6 +74,7 @@ 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_sysfs_binary(const char *path, char *buf, size_t buf_size, int *retlen);
|
||||
int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
|
||||
|
||||
int setup_devices_file(struct cmd_context *cmd);
|
||||
|
||||
@@ -23,9 +23,6 @@ int dev_is_luks(struct cmd_context *cmd, struct device *dev, uint64_t *offset_fo
|
||||
char buf[LUKS_SIGNATURE_SIZE];
|
||||
int ret = -1;
|
||||
|
||||
if (!scan_bcache)
|
||||
return -EAGAIN;
|
||||
|
||||
if (offset_found)
|
||||
*offset_found = 0;
|
||||
|
||||
|
||||
@@ -178,12 +178,6 @@ static int _dev_is_md_component_native(struct device *dev, uint64_t *offset_foun
|
||||
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 (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return -1;
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/commands/toolcontext.h"
|
||||
#include "lib/device/device_id.h"
|
||||
#include "lib/datastruct/str_list.h"
|
||||
#ifdef UDEV_SYNC_SUPPORT
|
||||
#include <libudev.h>
|
||||
#include "lib/device/dev-ext-udev-constants.h"
|
||||
#endif
|
||||
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define MPATH_PREFIX "mpath-"
|
||||
|
||||
@@ -35,21 +37,175 @@
|
||||
* 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_pool *_wwid_mem;
|
||||
static struct dm_hash_table *_minor_hash_tab;
|
||||
static struct dm_hash_table *_wwid_hash_tab;
|
||||
static struct dm_list _ignored;
|
||||
static struct dm_list _ignored_exceptions;
|
||||
|
||||
#define MAX_WWID_LINE 512
|
||||
|
||||
/*
|
||||
* do we need to check the multipath.conf blacklist?
|
||||
*/
|
||||
static void _read_blacklist_file(const char *path)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[MAX_WWID_LINE];
|
||||
char wwid[MAX_WWID_LINE];
|
||||
char *word, *p;
|
||||
int section_black = 0;
|
||||
int section_exceptions = 0;
|
||||
int found_quote;
|
||||
int found_type;
|
||||
int i, j;
|
||||
|
||||
static void _read_wwid_file(const char *config_wwids_file)
|
||||
if (!(fp = fopen(path, "r")))
|
||||
return;
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
word = NULL;
|
||||
|
||||
/* skip initial white space on the line */
|
||||
for (i = 0; i < MAX_WWID_LINE; i++) {
|
||||
if ((line[i] == '\n') || (line[i] == '\0'))
|
||||
break;
|
||||
if (isspace(line[i]))
|
||||
continue;
|
||||
word = &line[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!word || word[0] == '#')
|
||||
continue;
|
||||
|
||||
/* identify the start of the section we want to read */
|
||||
if (strchr(word, '{')) {
|
||||
if (!strncmp(word, "blacklist_exceptions", 20))
|
||||
section_exceptions = 1;
|
||||
else if (!strncmp(word, "blacklist", 9))
|
||||
section_black = 1;
|
||||
continue;
|
||||
}
|
||||
/* identify the end of the section we've been reading */
|
||||
if (strchr(word, '}')) {
|
||||
section_exceptions = 0;
|
||||
section_black = 0;
|
||||
continue;
|
||||
}
|
||||
/* skip lines that are not in a section we want */
|
||||
if (!section_black && !section_exceptions)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* read a wwid from the blacklist{_exceptions} section.
|
||||
* does not recognize other non-wwid entries in the
|
||||
* section, and skips those (should the entire mp
|
||||
* config filtering be disabled if non-wwids are seen?
|
||||
*/
|
||||
if (!(p = strstr(word, "wwid")))
|
||||
continue;
|
||||
|
||||
i += 4; /* skip "wwid" */
|
||||
|
||||
/*
|
||||
* copy wwid value from the line.
|
||||
* the wwids copied here need to match the
|
||||
* wwids read from /etc/multipath/wwids,
|
||||
* which are matched to wwids from sysfs.
|
||||
*/
|
||||
|
||||
memset(wwid, 0, sizeof(wwid));
|
||||
found_quote = 0;
|
||||
found_type = 0;
|
||||
j = 0;
|
||||
|
||||
for (; i < MAX_WWID_LINE; i++) {
|
||||
if ((line[i] == '\n') || (line[i] == '\0'))
|
||||
break;
|
||||
if (!j && isspace(line[i]))
|
||||
continue;
|
||||
if (isspace(line[i]))
|
||||
break;
|
||||
/* quotes around wwid are optional */
|
||||
if ((line[i] == '"') && !found_quote) {
|
||||
found_quote = 1;
|
||||
continue;
|
||||
}
|
||||
/* second quote is end of wwid */
|
||||
if ((line[i] == '"') && found_quote)
|
||||
break;
|
||||
/* exclude initial 3/2/1 for naa/eui/t10 */
|
||||
if (!j && !found_type &&
|
||||
((line[i] == '3') || (line[i] == '2') || (line[i] == '1'))) {
|
||||
found_type = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
wwid[j] = line[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
if (j < 8)
|
||||
continue;
|
||||
|
||||
log_debug("multipath wwid %s in %s %s",
|
||||
wwid, section_exceptions ? "blacklist_exceptions" : "blacklist", path);
|
||||
|
||||
if (section_exceptions) {
|
||||
if (!str_list_add(_wwid_mem, &_ignored_exceptions, dm_pool_strdup(_wwid_mem, wwid)))
|
||||
stack;
|
||||
} else {
|
||||
if (!str_list_add(_wwid_mem, &_ignored, dm_pool_strdup(_wwid_mem, wwid)))
|
||||
stack;
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(fp))
|
||||
stack;
|
||||
}
|
||||
|
||||
static void _read_wwid_exclusions(void)
|
||||
{
|
||||
char path[PATH_MAX] = { 0 };
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
struct dm_str_list *sl, *sl2;
|
||||
int rem_count = 0;
|
||||
|
||||
_read_blacklist_file("/etc/multipath.conf");
|
||||
|
||||
if ((dir = opendir("/etc/multipath/conf.d"))) {
|
||||
while ((de = readdir(dir))) {
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
snprintf(path, PATH_MAX-1, "/etc/multipath/conf.d/%s", de->d_name);
|
||||
_read_blacklist_file(path);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
/* for each wwid in ignored_exceptions, remove it from ignored */
|
||||
|
||||
dm_list_iterate_items_safe(sl, sl2, &_ignored) {
|
||||
if (str_list_match_item(&_ignored_exceptions, sl->str))
|
||||
str_list_del(&_ignored, sl->str);
|
||||
}
|
||||
|
||||
/* for each wwid in ignored, remove it from wwid_hash */
|
||||
|
||||
dm_list_iterate_items(sl, &_ignored) {
|
||||
dm_hash_remove_binary(_wwid_hash_tab, sl->str, strlen(sl->str));
|
||||
rem_count++;
|
||||
}
|
||||
|
||||
if (rem_count)
|
||||
log_debug("multipath config ignored %d wwids", rem_count);
|
||||
}
|
||||
|
||||
static void _read_wwid_file(const char *config_wwids_file, int *entries)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[MAX_WWID_LINE];
|
||||
char *wwid, *p;
|
||||
char typestr[2] = { 0 };
|
||||
int count = 0;
|
||||
|
||||
if (config_wwids_file[0] != '/') {
|
||||
@@ -71,8 +227,17 @@ static void _read_wwid_file(const char *config_wwids_file)
|
||||
if (line[0] == '/')
|
||||
wwid++;
|
||||
|
||||
/* skip the initial '3' */
|
||||
wwid++;
|
||||
|
||||
/*
|
||||
* the initial character is the id type,
|
||||
* 1 is t10, 2 is eui, 3 is naa, 8 is scsi name.
|
||||
* wwids are stored in the hash table without the type charater.
|
||||
* It seems that sometimes multipath does not include
|
||||
* the type charater (seen with t10 scsi_debug devs).
|
||||
*/
|
||||
typestr[0] = *wwid;
|
||||
if (typestr[0] == '1' || typestr[0] == '2' || typestr[0] == '3')
|
||||
wwid++;
|
||||
|
||||
if ((p = strchr(wwid, '/')))
|
||||
*p = '\0';
|
||||
@@ -85,6 +250,7 @@ static void _read_wwid_file(const char *config_wwids_file)
|
||||
stack;
|
||||
|
||||
log_debug("multipath wwids read %d from %s", count, config_wwids_file);
|
||||
*entries = count;
|
||||
}
|
||||
|
||||
int dev_mpath_init(const char *config_wwids_file)
|
||||
@@ -92,6 +258,10 @@ 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;
|
||||
int entries = 0;
|
||||
|
||||
dm_list_init(&_ignored);
|
||||
dm_list_init(&_ignored_exceptions);
|
||||
|
||||
if (!(mem = dm_pool_create("mpath", 256))) {
|
||||
log_error("mpath pool creation failed.");
|
||||
@@ -104,7 +274,7 @@ int dev_mpath_init(const char *config_wwids_file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
_hash_mem = mem;
|
||||
_wwid_mem = mem;
|
||||
_minor_hash_tab = minor_tab;
|
||||
|
||||
/* multipath_wwids_file="" disables the use of the file */
|
||||
@@ -116,16 +286,24 @@ int dev_mpath_init(const char *config_wwids_file)
|
||||
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);
|
||||
dm_pool_destroy(_wwid_mem);
|
||||
_minor_hash_tab = NULL;
|
||||
_hash_mem = NULL;
|
||||
_wwid_mem = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_wwid_hash_tab = wwid_tab;
|
||||
|
||||
if (config_wwids_file)
|
||||
_read_wwid_file(config_wwids_file);
|
||||
if (config_wwids_file) {
|
||||
_read_wwid_file(config_wwids_file, &entries);
|
||||
_read_wwid_exclusions();
|
||||
}
|
||||
|
||||
if (!entries) {
|
||||
/* reading dev wwids is skipped with null wwid_hash_tab */
|
||||
dm_hash_destroy(_wwid_hash_tab);
|
||||
_wwid_hash_tab = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -136,12 +314,12 @@ void dev_mpath_exit(void)
|
||||
dm_hash_destroy(_minor_hash_tab);
|
||||
if (_wwid_hash_tab)
|
||||
dm_hash_destroy(_wwid_hash_tab);
|
||||
if (_hash_mem)
|
||||
dm_pool_destroy(_hash_mem);
|
||||
if (_wwid_mem)
|
||||
dm_pool_destroy(_wwid_mem);
|
||||
|
||||
_minor_hash_tab = NULL;
|
||||
_wwid_hash_tab = NULL;
|
||||
_hash_mem = NULL;
|
||||
_wwid_mem = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -272,10 +450,12 @@ static int _dev_is_mpath_component_udev(struct device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev)
|
||||
/* mpath_devno is major:minor of the dm multipath device currently using the component dev. */
|
||||
|
||||
static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *dev,
|
||||
int primary_result, dev_t primary_dev, dev_t *mpath_devno)
|
||||
{
|
||||
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/" */
|
||||
@@ -289,25 +469,15 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
|
||||
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)) {
|
||||
switch (primary_result) {
|
||||
|
||||
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. */
|
||||
@@ -426,50 +596,194 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
|
||||
if (closedir(dr))
|
||||
stack;
|
||||
|
||||
if (is_mpath_component)
|
||||
*mpath_devno = MKDEV(dm_dev_major, dm_dev_minor);
|
||||
return is_mpath_component;
|
||||
}
|
||||
|
||||
static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev)
|
||||
static int _read_sys_wwid(struct cmd_context *cmd, struct device *dev,
|
||||
char *idbuf, int idbufsize)
|
||||
{
|
||||
char sysbuf[PATH_MAX] = { 0 };
|
||||
char idtmp[DEV_WWID_SIZE];
|
||||
|
||||
if (!read_sys_block(cmd, dev, "device/wwid", idbuf, idbufsize)) {
|
||||
/* the wwid file is not under device for nvme devs */
|
||||
if (!read_sys_block(cmd, dev, "wwid", idbuf, idbufsize))
|
||||
return 0;
|
||||
}
|
||||
if (!idbuf[0])
|
||||
return 0;
|
||||
|
||||
/* in t10 id, replace series of spaces with one _ like multipath */
|
||||
if (!strncmp(idbuf, "t10.", 4) && strchr(idbuf, ' ')) {
|
||||
if (idbufsize < DEV_WWID_SIZE)
|
||||
return 0;
|
||||
memcpy(idtmp, idbuf, DEV_WWID_SIZE);
|
||||
memset(idbuf, 0, idbufsize);
|
||||
format_t10_id((const unsigned char *)idtmp, DEV_WWID_SIZE, (unsigned char *)idbuf, idbufsize);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define VPD_SIZE 4096
|
||||
|
||||
static int _read_sys_vpd_wwids(struct cmd_context *cmd, struct device *dev,
|
||||
struct dm_list *ids)
|
||||
{
|
||||
unsigned char vpd_data[VPD_SIZE] = { 0 };
|
||||
int vpd_datalen = 0;
|
||||
|
||||
if (!read_sys_block_binary(cmd, dev, "device/vpd_pg83", (char *)vpd_data, VPD_SIZE, &vpd_datalen))
|
||||
return 0;
|
||||
if (!vpd_datalen)
|
||||
return 0;
|
||||
|
||||
/* adds dev_wwid entry to dev->wwids for each id in vpd data */
|
||||
parse_vpd_ids(vpd_data, vpd_datalen, ids);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void free_wwids(struct dm_list *ids)
|
||||
{
|
||||
struct dev_wwid *dw, *safe;
|
||||
|
||||
dm_list_iterate_items_safe(dw, safe, ids) {
|
||||
dm_list_del(&dw->list);
|
||||
free(dw);
|
||||
}
|
||||
}
|
||||
|
||||
static int _wwid_type_num(char *id)
|
||||
{
|
||||
if (!strncmp(id, "naa.", 4))
|
||||
return 3;
|
||||
else if (!strncmp(id, "eui.", 4))
|
||||
return 2;
|
||||
else if (!strncmp(id, "t10.", 4))
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: if each of the different wwid types (naa/eui/t10) were
|
||||
* represented by different DEV_ID_TYPE_FOO values, and used
|
||||
* as device_id types, then we could drop struct dev_wwid and
|
||||
* drop dev->wwids, and just use dev->ids for each of the
|
||||
* different wwids found in vpd_pg83. This would also require
|
||||
* the ability to handle both the original method of replacing
|
||||
* every space in the id string with _ and the new/multipath
|
||||
* format_t10_id replacing series of spaces with one _.
|
||||
*/
|
||||
struct dev_wwid *add_wwid(char *id, int id_type, struct dm_list *ids)
|
||||
{
|
||||
struct dev_wwid *dw;
|
||||
int len;
|
||||
|
||||
if (!id_type) {
|
||||
id_type = _wwid_type_num(id);
|
||||
if (id_type == -1)
|
||||
log_debug("unknown wwid type %s", id);
|
||||
}
|
||||
|
||||
if (!(dw = zalloc(sizeof(struct dev_wwid))))
|
||||
return NULL;
|
||||
len = strlen(id);
|
||||
if (len >= DEV_WWID_SIZE)
|
||||
len = DEV_WWID_SIZE - 1;
|
||||
memcpy(dw->id, id, len);
|
||||
dw->type = id_type;
|
||||
dm_list_add(ids, &dw->list);
|
||||
return dw;
|
||||
}
|
||||
|
||||
/*
|
||||
* we save ids with format: naa.<value>, eui.<value>, t10.<value>.
|
||||
* multipath wwids file uses format: 3<value>, 2<value>, 1<value>.
|
||||
* The values are saved in wwid_hash_tab without the type prefix.
|
||||
*/
|
||||
|
||||
static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev,
|
||||
int primary_result, dev_t primary_dev)
|
||||
{
|
||||
char idbuf[DEV_WWID_SIZE] = { 0 };
|
||||
struct dev_wwid *dw;
|
||||
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;
|
||||
/*
|
||||
* Check the primary device, not the partition.
|
||||
*/
|
||||
if (primary_result == 2) {
|
||||
if (!(dev = dev_cache_get_by_devt(cmd, primary_dev))) {
|
||||
log_debug("dev_is_mpath_component %s no primary dev", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sysfs prints wwid as <typestr>.<value>
|
||||
* multipath wwid uses '3'<value>
|
||||
* does "<typestr>." always correspond to "3"?
|
||||
* This function may be called multiple times for the same device, in
|
||||
* particular if partitioned for each partition.
|
||||
*/
|
||||
if (!(wwid = strchr(sysbuf, '.')))
|
||||
return 0;
|
||||
if (!dm_list_empty(&dev->wwids))
|
||||
goto lookup;
|
||||
|
||||
/* 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));
|
||||
/*
|
||||
* Get all the ids for the device from vpd_pg83 and check if any of
|
||||
* those are in /etc/multipath/wwids. These ids should include the
|
||||
* value printed from the sysfs wwid file.
|
||||
*/
|
||||
_read_sys_vpd_wwids(cmd, dev, &dev->wwids);
|
||||
if (!dm_list_empty(&dev->wwids))
|
||||
goto lookup;
|
||||
|
||||
if (look) {
|
||||
log_debug_devs("dev_is_mpath_component %s multipath wwid %s", dev_name(dev), wwid);
|
||||
return 1;
|
||||
/*
|
||||
* This will read the sysfs wwid file, nvme devices in particular have
|
||||
* a wwid file but not a vpd_pg83 file.
|
||||
*/
|
||||
if (_read_sys_wwid(cmd, dev, idbuf, sizeof(idbuf)))
|
||||
add_wwid(idbuf, 0, &dev->wwids);
|
||||
|
||||
lookup:
|
||||
dm_list_iterate_items(dw, &dev->wwids) {
|
||||
if (dw->type == 1 || dw->type == 2 || dw->type == 3)
|
||||
wwid = &dw->id[4];
|
||||
else
|
||||
wwid = dw->id;
|
||||
|
||||
if (dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid))) {
|
||||
log_debug_devs("dev_is_mpath_component %s %s in wwids file", dev_name(dev), dw->id);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev)
|
||||
int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *holder_devno)
|
||||
{
|
||||
if (_dev_is_mpath_component_sysfs(cmd, dev) == 1)
|
||||
struct dev_types *dt = cmd->dev_types;
|
||||
int primary_result;
|
||||
dev_t primary_dev;
|
||||
|
||||
/*
|
||||
* multipath only uses SCSI or NVME devices
|
||||
*/
|
||||
if (!major_is_scsi_device(dt, MAJOR(dev->dev)) && !dev_is_nvme(dt, dev))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* primary_result 2: dev is a partition, primary_dev is the whole device
|
||||
* primary_result 1: dev is a whole device
|
||||
*/
|
||||
primary_result = dev_get_primary_dev(dt, dev, &primary_dev);
|
||||
|
||||
if (_dev_is_mpath_component_sysfs(cmd, dev, primary_result, primary_dev, holder_devno) == 1)
|
||||
goto found;
|
||||
|
||||
if (_dev_in_wwid_file(cmd, dev))
|
||||
if (_dev_in_wwid_file(cmd, dev, primary_result, primary_dev))
|
||||
goto found;
|
||||
|
||||
if (external_device_info_source() == DEV_EXT_UDEV) {
|
||||
@@ -477,6 +791,12 @@ int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev)
|
||||
goto found;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: save the result of this function in dev->flags and use those
|
||||
* flags on repeated calls to avoid repeating the work multiple times
|
||||
* for the same device when there are partitions on the device.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
found:
|
||||
return 1;
|
||||
|
||||
@@ -42,9 +42,6 @@ int dev_is_swap(struct cmd_context *cmd, struct device *dev, uint64_t *offset_fo
|
||||
unsigned page;
|
||||
int ret = 0;
|
||||
|
||||
if (!scan_bcache)
|
||||
return -EAGAIN;
|
||||
|
||||
if (!dev_get_size(dev, &size)) {
|
||||
stack;
|
||||
return -1;
|
||||
|
||||
@@ -674,11 +674,6 @@ static int _dev_is_partitioned_native(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;
|
||||
}
|
||||
|
||||
/* Unpartitioned DASD devices are not supported. */
|
||||
if ((MAJOR(dev->dev) == dt->dasd_major) && dasd_is_cdl_formatted(dev))
|
||||
return 1;
|
||||
@@ -843,6 +838,86 @@ int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int fs_get_blkid(const char *pathname, struct fs_info *fsi)
|
||||
{
|
||||
blkid_probe probe = NULL;
|
||||
const char *str;
|
||||
size_t len;
|
||||
uint64_t fslastblock = 0;
|
||||
unsigned int fsblocksize = 0;
|
||||
int no_block_size = 0, no_fslastblock = 0, no_fsblocksize = 0;
|
||||
int rc;
|
||||
|
||||
if (!(probe = blkid_new_probe_from_filename(pathname))) {
|
||||
log_error("Failed libblkid probe setup for %s", pathname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
blkid_probe_enable_superblocks(probe, 1);
|
||||
blkid_probe_set_superblocks_flags(probe,
|
||||
BLKID_SUBLKS_LABEL | BLKID_SUBLKS_LABELRAW |
|
||||
BLKID_SUBLKS_UUID | BLKID_SUBLKS_UUIDRAW |
|
||||
BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE |
|
||||
BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION |
|
||||
BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_FSINFO);
|
||||
rc = blkid_do_safeprobe(probe);
|
||||
if (rc < 0) {
|
||||
log_error("Failed libblkid probe for %s", pathname);
|
||||
blkid_free_probe(probe);
|
||||
return 0;
|
||||
} else if (rc == 1) {
|
||||
/* no file system on the device */
|
||||
log_print("No file system found on %s.", pathname);
|
||||
fsi->nofs = 1;
|
||||
blkid_free_probe(probe);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!blkid_probe_lookup_value(probe, "TYPE", &str, &len) && len)
|
||||
strncpy(fsi->fstype, str, sizeof(fsi->fstype)-1);
|
||||
else {
|
||||
/* any difference from blkid_do_safeprobe rc=1? */
|
||||
log_print("No file system type on %s.", pathname);
|
||||
fsi->nofs = 1;
|
||||
blkid_free_probe(probe);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!blkid_probe_lookup_value(probe, "BLOCK_SIZE", &str, &len) && len)
|
||||
fsi->block_size_bytes = atoi(str);
|
||||
else
|
||||
no_block_size = 1;
|
||||
|
||||
if (!blkid_probe_lookup_value(probe, "FSLASTBLOCK", &str, &len) && len)
|
||||
fslastblock = strtoull(str, NULL, 0);
|
||||
else
|
||||
no_fslastblock = 1;
|
||||
|
||||
if (!blkid_probe_lookup_value(probe, "FSBLOCKSIZE", &str, &len) && len)
|
||||
fsblocksize = (unsigned int)atoi(str);
|
||||
else
|
||||
no_fsblocksize = 1;
|
||||
|
||||
blkid_free_probe(probe);
|
||||
|
||||
if (no_block_size || no_fslastblock || no_fsblocksize) {
|
||||
log_print("Missing libblkid %s%s%sfor %s",
|
||||
no_block_size ? "BLOCK_SIZE " : "",
|
||||
no_fslastblock ? "FSLASTBLOCK " : "",
|
||||
no_fsblocksize ? "FSBLOCKSIZE " : "",
|
||||
pathname);
|
||||
}
|
||||
|
||||
if (fslastblock && fsblocksize)
|
||||
fsi->fs_last_byte = fslastblock * fsblocksize;
|
||||
|
||||
log_debug("libblkid TYPE %s BLOCK_SIZE %d FSLASTBLOCK %llu FSBLOCKSIZE %u fs_last_byte %llu",
|
||||
fsi->fstype, fsi->block_size_bytes, (unsigned long long)fslastblock, fsblocksize,
|
||||
(unsigned long long)fsi->fs_last_byte);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
|
||||
{
|
||||
@@ -850,6 +925,11 @@ int get_fs_block_size(const char *pathname, uint32_t *fs_block_size)
|
||||
*fs_block_size = 0;
|
||||
return 0;
|
||||
}
|
||||
int fs_get_blkid(const char *pathname, struct fs_info *fsi)
|
||||
{
|
||||
log_debug("Disabled blkid for fs info.");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLKID_WIPING_SUPPORT
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "lib/device/device.h"
|
||||
#include "lib/display/display.h"
|
||||
#include "lib/label/label.h"
|
||||
#include "lib/device/filesystem.h"
|
||||
|
||||
#define NUMBER_OF_MAJORS 4096
|
||||
|
||||
@@ -58,7 +59,7 @@ 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_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *mpath_devno);
|
||||
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 dasd_is_cdl_formatted(struct device *dev);
|
||||
@@ -102,6 +103,7 @@ int dev_is_nvme(struct dev_types *dt, struct device *dev);
|
||||
int dev_is_lv(struct device *dev);
|
||||
|
||||
int get_fs_block_size(const char *pathname, uint32_t *fs_block_size);
|
||||
int fs_get_blkid(const char *pathname, struct fs_info *fsi);
|
||||
|
||||
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);
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#define DEV_NOT_O_NOATIME 0x00000400 /* Don't use O_NOATIME */
|
||||
#define DEV_IN_BCACHE 0x00000800 /* dev fd is open and used in bcache */
|
||||
#define DEV_BCACHE_EXCL 0x00001000 /* bcache_fd should be open EXCL */
|
||||
#define DEV_FILTER_AFTER_SCAN 0x00002000 /* apply filter after bcache has data */
|
||||
#define DEV_FILTER_OUT_SCAN 0x00004000 /* filtered out during label scan */
|
||||
/* unused 0x00002000 */
|
||||
/* unused 0x00004000 */
|
||||
#define DEV_BCACHE_WRITE 0x00008000 /* bcache_fd is open with RDWR */
|
||||
#define DEV_SCAN_FOUND_LABEL 0x00010000 /* label scan read dev and found label */
|
||||
#define DEV_IS_MD_COMPONENT 0x00020000 /* device is an md component */
|
||||
@@ -59,6 +59,14 @@ struct dev_ext {
|
||||
void *handle;
|
||||
};
|
||||
|
||||
#define DEV_WWID_SIZE 128
|
||||
|
||||
struct dev_wwid {
|
||||
struct dm_list list;
|
||||
int type;
|
||||
char id[DEV_WWID_SIZE];
|
||||
};
|
||||
|
||||
#define DEV_ID_TYPE_SYS_WWID 0x0001
|
||||
#define DEV_ID_TYPE_SYS_SERIAL 0x0002
|
||||
#define DEV_ID_TYPE_MPATH_UUID 0x0003
|
||||
@@ -105,6 +113,7 @@ struct dev_use {
|
||||
*/
|
||||
struct device {
|
||||
struct dm_list aliases; /* struct dm_str_list */
|
||||
struct dm_list wwids; /* struct dev_wwid, used for multipath component detection */
|
||||
struct dm_list ids; /* struct dev_id, different entries for different idtypes */
|
||||
struct dev_id *id; /* points to the the ids entry being used for this dev */
|
||||
dev_t dev;
|
||||
@@ -206,5 +215,9 @@ void dev_destroy_file(struct device *dev);
|
||||
|
||||
int dev_mpath_init(const char *config_wwids_file);
|
||||
void dev_mpath_exit(void);
|
||||
struct dev_wwid *add_wwid(char *id, int id_type, struct dm_list *ids);
|
||||
void free_wwids(struct dm_list *ids);
|
||||
int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids);
|
||||
int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -182,7 +182,9 @@ 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,
|
||||
int binary, int *retlen)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
dev_t devt = dev->dev;
|
||||
@@ -196,11 +198,17 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_sysfs_value(path, sysbuf, sysbufsize, 0);
|
||||
if (binary) {
|
||||
ret = get_sysfs_binary(path, sysbuf, sysbufsize, retlen);
|
||||
if (ret && !*retlen)
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = get_sysfs_value(path, sysbuf, sysbufsize, 0);
|
||||
if (ret && !sysbuf[0])
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (sysbuf[0]) {
|
||||
if (prim)
|
||||
log_debug("Using primary device_id for partition %s.", dev_name(dev));
|
||||
if (ret) {
|
||||
sysbuf[sysbufsize - 1] = '\0';
|
||||
return 1;
|
||||
}
|
||||
@@ -220,6 +228,19 @@ int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suff
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_sys_block(struct cmd_context *cmd, struct device *dev,
|
||||
const char *suffix, char *sysbuf, int sysbufsize)
|
||||
{
|
||||
return _read_sys_block(cmd, dev, suffix, sysbuf, sysbufsize, 0, NULL);
|
||||
}
|
||||
|
||||
int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
|
||||
const char *suffix, char *sysbuf, int sysbufsize,
|
||||
int *retlen)
|
||||
{
|
||||
return _read_sys_block(cmd, dev, suffix, sysbuf, sysbufsize, 1, retlen);
|
||||
}
|
||||
|
||||
static int _dm_uuid_has_prefix(char *sysbuf, const char *prefix)
|
||||
{
|
||||
if (!strncmp(sysbuf, prefix, strlen(prefix)))
|
||||
@@ -887,6 +908,17 @@ static int _device_ids_use_lvmlv(struct cmd_context *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dev_use *get_du_for_devno(struct cmd_context *cmd, dev_t devno)
|
||||
{
|
||||
struct dev_use *du;
|
||||
|
||||
dm_list_iterate_items(du, &cmd->use_devices) {
|
||||
if (du->dev && du->dev->dev == devno)
|
||||
return du;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dev_use *get_du_for_dev(struct cmd_context *cmd, struct device *dev)
|
||||
{
|
||||
struct dev_use *du;
|
||||
@@ -924,7 +956,7 @@ struct dev_use *get_du_for_devname(struct cmd_context *cmd, const char *devname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct dev_use *_get_du_for_device_id(struct cmd_context *cmd, uint16_t idtype, const char *idname)
|
||||
struct dev_use *get_du_for_device_id(struct cmd_context *cmd, uint16_t idtype, const char *idname)
|
||||
{
|
||||
struct dev_use *du;
|
||||
|
||||
@@ -1117,7 +1149,7 @@ id_done:
|
||||
du_devname = get_du_for_devname(cmd, dev_name(dev));
|
||||
|
||||
/* Is there already an entry using the device_id for this device? */
|
||||
du_devid = _get_du_for_device_id(cmd, id->idtype, id->idname);
|
||||
du_devid = get_du_for_device_id(cmd, id->idtype, id->idname);
|
||||
|
||||
if (du_dev)
|
||||
log_debug("device_id_add %s pvid %s matches entry %p dev %s",
|
||||
@@ -1287,15 +1319,15 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg,
|
||||
int update = 0;
|
||||
|
||||
if (!cmd->enable_devices_file)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
/* Without this setting there is no stacking LVs on PVs. */
|
||||
if (!cmd->scan_lvs)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
/* Check if any devices file entries are stacked on LVs. */
|
||||
if (!_device_ids_use_lvmlv(cmd))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
memcpy(old_vgid, old_vg_id, ID_LEN);
|
||||
memcpy(new_vgid, &vg->id, ID_LEN);
|
||||
@@ -1311,7 +1343,7 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg,
|
||||
memcpy(old_idname+4, old_vgid, ID_LEN);
|
||||
memcpy(old_idname+4+ID_LEN, &lvl->lv->lvid.id[1], ID_LEN);
|
||||
|
||||
if ((du = _get_du_for_device_id(cmd, DEV_ID_TYPE_LVMLV_UUID, old_idname))) {
|
||||
if ((du = get_du_for_device_id(cmd, DEV_ID_TYPE_LVMLV_UUID, old_idname))) {
|
||||
log_debug("device_id update %s pvid %s vgid %s to %s",
|
||||
du->devname ?: ".", du->pvid ?: ".", old_vgid, new_vgid);
|
||||
memcpy(du->idname+4, new_vgid, ID_LEN);
|
||||
@@ -1325,7 +1357,6 @@ void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg,
|
||||
if (update &&
|
||||
!device_ids_write(cmd))
|
||||
stack;
|
||||
out:
|
||||
unlock_devices_file(cmd);
|
||||
}
|
||||
|
||||
@@ -1766,7 +1797,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
* probably wants to do something about it.
|
||||
*/
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
|
||||
log_warn("Devices file %s is excluded by filter: %s.",
|
||||
log_warn("Devices file %s is excluded: %s.",
|
||||
dev_name(dev), dev_filtered_reason(dev));
|
||||
continue;
|
||||
}
|
||||
@@ -1852,7 +1883,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
|
||||
continue;
|
||||
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, "persistent")) {
|
||||
log_warn("Devices file %s is excluded by filter: %s.",
|
||||
log_warn("Devices file %s is excluded: %s.",
|
||||
dev_name(dev), dev_filtered_reason(dev));
|
||||
/* FIXME: what if this dev is wrongly matched and should be checked below? */
|
||||
continue;
|
||||
@@ -2294,7 +2325,7 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
|
||||
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, dev, NULL)) {
|
||||
/* I don't think this would happen */
|
||||
log_warn("WARNING: new device %s for PVID %s does not pass filter %s.",
|
||||
log_warn("WARNING: new device %s for PVID %s is excluded: %s.",
|
||||
dev_name(dev), dil->pvid, dev_filtered_reason(dev));
|
||||
if (du) /* Should not happen 'du' is NULL */
|
||||
du->dev = NULL;
|
||||
|
||||
@@ -39,9 +39,11 @@ void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_l
|
||||
const char *device_id_system_read(struct cmd_context *cmd, struct device *dev, uint16_t idtype);
|
||||
void device_id_update_vg_uuid(struct cmd_context *cmd, struct volume_group *vg, struct id *old_vg_id);
|
||||
|
||||
struct dev_use *get_du_for_devno(struct cmd_context *cmd, dev_t devno);
|
||||
struct dev_use *get_du_for_dev(struct cmd_context *cmd, struct device *dev);
|
||||
struct dev_use *get_du_for_pvid(struct cmd_context *cmd, const char *pvid);
|
||||
struct dev_use *get_du_for_devname(struct cmd_context *cmd, const char *devname);
|
||||
struct dev_use *get_du_for_device_id(struct cmd_context *cmd, uint16_t idtype, const char *idname);
|
||||
|
||||
char *devices_file_version(void);
|
||||
int devices_file_exists(struct cmd_context *cmd);
|
||||
@@ -56,6 +58,8 @@ 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);
|
||||
int read_sys_block_binary(struct cmd_context *cmd, struct device *dev,
|
||||
const char *suffix, char *sysbuf, int sysbufsize, int *retlen);
|
||||
|
||||
int dev_has_mpath_uuid(struct cmd_context *cmd, struct device *dev, const char **idname_out);
|
||||
|
||||
|
||||
284
lib/device/filesystem.c
Normal file
284
lib/device/filesystem.c
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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/commands/toolcontext.h"
|
||||
#include "lib/device/device.h"
|
||||
#include "lib/device/dev-type.h"
|
||||
#include "lib/misc/lvm-exec.h"
|
||||
|
||||
#include <mntent.h>
|
||||
|
||||
static int _get_lv_path(struct logical_volume *lv, char *lv_path)
|
||||
{
|
||||
if (dm_snprintf(lv_path, PATH_MAX, "%s%s/%s", lv->vg->cmd->dev_dir,
|
||||
lv->vg->name, lv->name) < 0) {
|
||||
log_error("Couldn't create LV path for %s.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct fs_info *fsi, int include_mount)
|
||||
{
|
||||
char lv_path[PATH_MAX];
|
||||
FILE *fme = NULL;
|
||||
struct stat stlv;
|
||||
struct stat stme;
|
||||
struct mntent *me;
|
||||
int ret;
|
||||
|
||||
if (!_get_lv_path(lv, lv_path))
|
||||
return_0;
|
||||
|
||||
if (!fs_get_blkid(lv_path, fsi)) {
|
||||
log_error("Missing libblkid file system info for %s", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fsi->nofs)
|
||||
return 1;
|
||||
|
||||
if (!include_mount)
|
||||
return 1;
|
||||
|
||||
if (stat(lv_path, &stlv) < 0)
|
||||
return_0;
|
||||
|
||||
if (!(fme = setmntent("/etc/mtab", "r")))
|
||||
return_0;
|
||||
|
||||
ret = 1;
|
||||
|
||||
while ((me = getmntent(fme))) {
|
||||
if (strcmp(me->mnt_type, fsi->fstype))
|
||||
continue;
|
||||
if (me->mnt_dir[0] != '/')
|
||||
continue;
|
||||
if (me->mnt_fsname[0] != '/')
|
||||
continue;
|
||||
if (stat(me->mnt_dir, &stme) < 0)
|
||||
continue;
|
||||
if (stme.st_dev != stlv.st_rdev)
|
||||
continue;
|
||||
|
||||
log_debug("fs_get_info %s is mounted \"%s\"", lv_path, me->mnt_dir);
|
||||
fsi->mounted = 1;
|
||||
strncpy(fsi->mount_dir, me->mnt_dir, PATH_MAX-1);
|
||||
}
|
||||
endmntent(fme);
|
||||
|
||||
fsi->unmounted = !fsi->mounted;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define FS_CMD_MAX_ARGS 6
|
||||
|
||||
int fs_fsck_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi)
|
||||
{
|
||||
char lv_path[PATH_MAX];
|
||||
const char *argv[FS_CMD_MAX_ARGS + 4];
|
||||
int args = 0;
|
||||
int status;
|
||||
|
||||
if (strncmp(fsi->fstype, "ext", 3)) {
|
||||
log_error("fsck not supported for %s.", fsi->fstype);
|
||||
return_0;
|
||||
}
|
||||
|
||||
if (!_get_lv_path(lv, lv_path))
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* ext234: e2fsck -f -p path
|
||||
* TODO: replace -p with -y based on yes_ARG, or other?
|
||||
*/
|
||||
|
||||
argv[0] = E2FSCK_PATH; /* defined by configure */
|
||||
argv[++args] = "-f";
|
||||
argv[++args] = "-p";
|
||||
argv[++args] = lv_path;
|
||||
argv[++args] = NULL;
|
||||
|
||||
log_print("Checking file system %s with %s on %s...",
|
||||
fsi->fstype, E2FSCK_PATH, display_lvname(lv));
|
||||
|
||||
if (!exec_cmd(cmd, argv, &status, 1)) {
|
||||
log_error("e2fsck failed on %s.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print("Checked file system %s on %s.", fsi->fstype, display_lvname(lv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fs_reduce_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes)
|
||||
{
|
||||
char lv_path[PATH_MAX];
|
||||
char newsize_kb_str[16] = { 0 };
|
||||
const char *argv[FS_CMD_MAX_ARGS + 4];
|
||||
int args = 0;
|
||||
int status;
|
||||
|
||||
if (!_get_lv_path(lv, lv_path))
|
||||
return_0;
|
||||
|
||||
if (!strncmp(fsi->fstype, "ext", 3)) {
|
||||
if (dm_snprintf(newsize_kb_str, 16, "%lluk", (unsigned long long)(newsize_bytes/1024)) < 0)
|
||||
return_0;
|
||||
|
||||
/*
|
||||
* ext234 shrink: resize2fs path newsize
|
||||
*/
|
||||
argv[0] = RESIZE2FS_PATH; /* defined by configure */
|
||||
argv[++args] = lv_path;
|
||||
argv[++args] = newsize_kb_str;
|
||||
argv[++args] = NULL;
|
||||
|
||||
} else {
|
||||
log_error("fs reduce not supported for %s.", fsi->fstype);
|
||||
return_0;
|
||||
}
|
||||
|
||||
log_print("Reducing file system %s on %s...", fsi->fstype, display_lvname(lv));
|
||||
|
||||
if (!exec_cmd(cmd, argv, &status, 1)) {
|
||||
log_error("Failed to reduce %s file system on %s.", fsi->fstype, display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print("Reduced file system %s to %s (%llu bytes) on %s.",
|
||||
fsi->fstype, display_size(cmd, newsize_bytes/512),
|
||||
(unsigned long long)newsize_bytes, display_lvname(lv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fs_extend_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi)
|
||||
{
|
||||
char lv_path[PATH_MAX];
|
||||
const char *argv[FS_CMD_MAX_ARGS + 4];
|
||||
int args = 0;
|
||||
int status;
|
||||
|
||||
if (!_get_lv_path(lv, lv_path))
|
||||
return_0;
|
||||
|
||||
if (!strncmp(fsi->fstype, "ext", 3)) {
|
||||
/* TODO: include -f if lvm command inclues -f ? */
|
||||
argv[0] = RESIZE2FS_PATH; /* defined by configure */
|
||||
argv[++args] = lv_path;
|
||||
argv[++args] = NULL;
|
||||
|
||||
} else if (!strcmp(fsi->fstype, "xfs")) {
|
||||
argv[0] = XFS_GROWFS_PATH; /* defined by configure */
|
||||
argv[++args] = lv_path;
|
||||
argv[++args] = NULL;
|
||||
|
||||
} else {
|
||||
log_error("Extend not supported for %s file system.", fsi->fstype);
|
||||
return_0;
|
||||
}
|
||||
|
||||
log_print("Extending file system %s on %s...", fsi->fstype, display_lvname(lv));
|
||||
|
||||
if (!exec_cmd(cmd, argv, &status, 1)) {
|
||||
log_error("Failed to extend %s file system on %s.", fsi->fstype, display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print("Extended file system %s on %s.", fsi->fstype, display_lvname(lv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fs_mount_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
int reuse_mount_dir)
|
||||
{
|
||||
char lv_path[PATH_MAX];
|
||||
char mountdir[PATH_MAX];
|
||||
const char *argv[FS_CMD_MAX_ARGS + 4];
|
||||
int args = 0;
|
||||
int status;
|
||||
|
||||
if (!_get_lv_path(lv, lv_path))
|
||||
return_0;
|
||||
|
||||
if (reuse_mount_dir) {
|
||||
if (!fsi->mount_dir[0]) {
|
||||
log_error("Cannot remount fs without previous mount dir.");
|
||||
return 0;
|
||||
}
|
||||
memcpy(mountdir, fsi->mount_dir, PATH_MAX);
|
||||
} else {
|
||||
if (dm_snprintf(mountdir, sizeof(mountdir), "/tmp/%s_XXXXXX", cmd->name) < 0)
|
||||
return_0;
|
||||
if (!mkdtemp(mountdir)) {
|
||||
log_error("Failed to create temp dir for mount: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
memcpy(fsi->mount_dir, mountdir, PATH_MAX);
|
||||
fsi->temp_mount_dir = 1;
|
||||
}
|
||||
|
||||
argv[0] = MOUNT_PATH; /* defined by configure */
|
||||
argv[++args] = lv_path;
|
||||
argv[++args] = mountdir;
|
||||
argv[++args] = NULL;
|
||||
|
||||
log_print("Mounting %s.", display_lvname(lv));
|
||||
|
||||
if (!exec_cmd(cmd, argv, &status, 1)) {
|
||||
log_error("Failed to mount file system on %s at %s.", display_lvname(lv), mountdir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print("Mounted %s at %s dir %s.", display_lvname(lv),
|
||||
reuse_mount_dir ? "original" : "temporary", mountdir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fs_unmount_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi)
|
||||
{
|
||||
char lv_path[PATH_MAX];
|
||||
const char *argv[FS_CMD_MAX_ARGS + 4];
|
||||
int args = 0;
|
||||
int status;
|
||||
|
||||
if (!_get_lv_path(lv, lv_path))
|
||||
return_0;
|
||||
|
||||
argv[0] = UMOUNT_PATH; /* defined by configure */
|
||||
argv[++args] = lv_path;
|
||||
argv[++args] = NULL;
|
||||
|
||||
log_print("Unmounting %s.", display_lvname(lv));
|
||||
|
||||
if (!exec_cmd(cmd, argv, &status, 1)) {
|
||||
log_error("Failed to unmount file system on %s.", display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print("Unmounted %s.", display_lvname(lv));
|
||||
|
||||
if (fsi->temp_mount_dir) {
|
||||
if (rmdir(fsi->mount_dir) < 0)
|
||||
log_print("Error removing temp dir %s", fsi->mount_dir);
|
||||
fsi->mount_dir[0] = '\0';
|
||||
fsi->temp_mount_dir = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
46
lib/device/filesystem.h
Normal file
46
lib/device/filesystem.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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
|
||||
*/
|
||||
|
||||
#ifndef _FILESYSTEM_H
|
||||
#define _FILESYSTEM_H
|
||||
|
||||
struct fs_info {
|
||||
char fstype[16];
|
||||
char mount_dir[PATH_MAX];
|
||||
unsigned int block_size_bytes; /* 512 or 4k */
|
||||
uint64_t fs_last_byte; /* last byte on the device used by the fs */
|
||||
|
||||
unsigned nofs:1;
|
||||
unsigned unmounted:1;
|
||||
unsigned mounted:1;
|
||||
unsigned temp_mount_dir:1;
|
||||
/* for resizing */
|
||||
unsigned needs_reduce:1;
|
||||
unsigned needs_extend:1;
|
||||
unsigned needs_fsck:1;
|
||||
unsigned needs_unmount:1;
|
||||
unsigned needs_mount:1;
|
||||
};
|
||||
|
||||
int fs_get_info(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct fs_info *fsi, int include_mount);
|
||||
int fs_fsck_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi);
|
||||
int fs_reduce_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
uint64_t newsize_bytes);
|
||||
int fs_extend_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi);
|
||||
int fs_mount_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi,
|
||||
int reuse_mount_dir);
|
||||
int fs_unmount_command(struct cmd_context *cmd, struct logical_volume *lv, struct fs_info *fsi);
|
||||
|
||||
#endif
|
||||
199
lib/device/parse_vpd.c
Normal file
199
lib/device/parse_vpd.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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/device/device.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Replace series of spaces with a single _.
|
||||
*/
|
||||
int format_t10_id(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes)
|
||||
{
|
||||
int in_space = 0;
|
||||
int retlen = 0;
|
||||
int j = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < in_bytes; i++) {
|
||||
if (!in[i])
|
||||
break;
|
||||
if (j >= (out_bytes - 2))
|
||||
break;
|
||||
/* skip leading spaces */
|
||||
if (!retlen && (in[i] == ' '))
|
||||
continue;
|
||||
/* replace one or more spaces with _ */
|
||||
if (in[i] == ' ') {
|
||||
in_space = 1;
|
||||
continue;
|
||||
}
|
||||
/* spaces are finished so insert _ */
|
||||
if (in_space) {
|
||||
out[j++] = '_';
|
||||
in_space = 0;
|
||||
retlen++;
|
||||
}
|
||||
out[j++] = in[i];
|
||||
retlen++;
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
||||
static int _to_hex(const unsigned char *in, int in_bytes, unsigned char *out, int out_bytes)
|
||||
{
|
||||
int off = 0;
|
||||
int num;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < in_bytes; i++) {
|
||||
num = sprintf((char *)out + off, "%02x", in[i]);
|
||||
if (num < 0)
|
||||
break;
|
||||
off += num;
|
||||
if (off + 2 >= out_bytes)
|
||||
break;
|
||||
}
|
||||
return off;
|
||||
}
|
||||
|
||||
#define ID_BUFSIZE 1024
|
||||
|
||||
/*
|
||||
* based on linux kernel function
|
||||
*/
|
||||
int parse_vpd_ids(const unsigned char *vpd_data, int vpd_datalen, struct dm_list *ids)
|
||||
{
|
||||
char id[ID_BUFSIZE];
|
||||
unsigned char tmp_str[ID_BUFSIZE];
|
||||
const unsigned char *d, *cur_id_str;
|
||||
size_t id_len = ID_BUFSIZE;
|
||||
int id_size = -1;
|
||||
uint8_t cur_id_size = 0;
|
||||
|
||||
memset(id, 0, ID_BUFSIZE);
|
||||
for (d = vpd_data + 4;
|
||||
d < vpd_data + vpd_datalen;
|
||||
d += d[3] + 4) {
|
||||
memset(tmp_str, 0, sizeof(tmp_str));
|
||||
|
||||
switch (d[1] & 0xf) {
|
||||
case 0x1:
|
||||
/* T10 Vendor ID */
|
||||
cur_id_size = d[3];
|
||||
if (cur_id_size + 4 > id_len)
|
||||
cur_id_size = id_len - 4;
|
||||
cur_id_str = d + 4;
|
||||
format_t10_id(cur_id_str, cur_id_size, tmp_str, sizeof(tmp_str));
|
||||
id_size = snprintf(id, ID_BUFSIZE, "t10.%s", tmp_str);
|
||||
if (id_size < 0)
|
||||
break;
|
||||
if (id_size >= ID_BUFSIZE)
|
||||
id_size = ID_BUFSIZE - 1;
|
||||
add_wwid(id, 1, ids);
|
||||
break;
|
||||
case 0x2:
|
||||
/* EUI-64 */
|
||||
cur_id_size = d[3];
|
||||
cur_id_str = d + 4;
|
||||
switch (cur_id_size) {
|
||||
case 8:
|
||||
_to_hex(cur_id_str, 8, tmp_str, sizeof(tmp_str));
|
||||
id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
|
||||
break;
|
||||
case 12:
|
||||
_to_hex(cur_id_str, 12, tmp_str, sizeof(tmp_str));
|
||||
id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
|
||||
break;
|
||||
case 16:
|
||||
_to_hex(cur_id_str, 16, tmp_str, sizeof(tmp_str));
|
||||
id_size = snprintf(id, ID_BUFSIZE, "eui.%s", tmp_str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (id_size < 0)
|
||||
break;
|
||||
if (id_size >= ID_BUFSIZE)
|
||||
id_size = ID_BUFSIZE - 1;
|
||||
add_wwid(id, 2, ids);
|
||||
break;
|
||||
case 0x3:
|
||||
/* NAA */
|
||||
cur_id_size = d[3];
|
||||
cur_id_str = d + 4;
|
||||
switch (cur_id_size) {
|
||||
case 8:
|
||||
_to_hex(cur_id_str, 8, tmp_str, sizeof(tmp_str));
|
||||
id_size = snprintf(id, ID_BUFSIZE, "naa.%s", tmp_str);
|
||||
break;
|
||||
case 16:
|
||||
_to_hex(cur_id_str, 16, tmp_str, sizeof(tmp_str));
|
||||
id_size = snprintf(id, ID_BUFSIZE, "naa.%s", tmp_str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (id_size < 0)
|
||||
break;
|
||||
if (id_size >= ID_BUFSIZE)
|
||||
id_size = ID_BUFSIZE - 1;
|
||||
add_wwid(id, 3, ids);
|
||||
break;
|
||||
case 0x8:
|
||||
/* SCSI name string */
|
||||
cur_id_size = d[3];
|
||||
cur_id_str = d + 4;
|
||||
if (cur_id_size >= id_len)
|
||||
cur_id_size = id_len - 1;
|
||||
memcpy(id, cur_id_str, cur_id_size);
|
||||
id_size = cur_id_size;
|
||||
|
||||
/*
|
||||
* Not in the kernel version, copying multipath code,
|
||||
* which checks if this string begins with naa or eui
|
||||
* and if so does tolower() on the chars.
|
||||
*/
|
||||
if (!strncmp(id, "naa.", 4) || !strncmp(id, "eui.", 4)) {
|
||||
int i;
|
||||
for (i = 0; i < id_size; i++)
|
||||
id[i] = tolower(id[i]);
|
||||
}
|
||||
add_wwid(id, 8, ids);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return id_size;
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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/filters/filter.h"
|
||||
|
||||
static DM_LIST_INIT(_allow_devs);
|
||||
|
||||
int internal_filter_allow(struct dm_pool *mem, struct device *dev)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
if (!(devl = dm_pool_alloc(mem, sizeof(*devl)))) {
|
||||
log_error("device_list element allocation failed");
|
||||
return 0;
|
||||
}
|
||||
devl->dev = dev;
|
||||
|
||||
dm_list_add(&_allow_devs, &devl->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void internal_filter_clear(void)
|
||||
{
|
||||
dm_list_init(&_allow_devs);
|
||||
}
|
||||
|
||||
static int _passes_internal(struct cmd_context *cmd, struct dev_filter *f __attribute__((unused)),
|
||||
struct device *dev, const char *use_filter_name)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
dev->filtered_flags &= ~DEV_FILTERED_INTERNAL;
|
||||
|
||||
if (!internal_filtering())
|
||||
return 1;
|
||||
|
||||
dm_list_iterate_items(devl, &_allow_devs) {
|
||||
if (devl->dev == dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev->filtered_flags |= DEV_FILTERED_INTERNAL;
|
||||
log_debug_devs("%s: Skipping for internal filtering.", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
{
|
||||
if (f->use_count)
|
||||
log_error(INTERNAL_ERROR "Destroying internal filter while in use %u times.", f->use_count);
|
||||
|
||||
free(f);
|
||||
}
|
||||
|
||||
struct dev_filter *internal_filter_create(void)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!(f = zalloc(sizeof(*f)))) {
|
||||
log_error("md filter allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->passes_filter = _passes_internal;
|
||||
f->destroy = _destroy;
|
||||
f->use_count = 0;
|
||||
f->name = "internal";
|
||||
|
||||
log_debug_devs("Internal filter initialised.");
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
@@ -99,14 +99,6 @@ static int _passes_md_filter(struct cmd_context *cmd, struct dev_filter *f __att
|
||||
return 1;
|
||||
|
||||
ret = dev_is_md_component(cmd, dev, NULL, cmd->use_full_md_check);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
/* let pass, call again after scan */
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
log_debug_devs("filter md deferred %s", dev_name(dev));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
return 1;
|
||||
|
||||
|
||||
@@ -15,18 +15,41 @@
|
||||
#include "base/memory/zalloc.h"
|
||||
#include "lib/misc/lib.h"
|
||||
#include "lib/filters/filter.h"
|
||||
#include "lib/device/device_id.h"
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
static int _lvmdevices_update_msg;
|
||||
|
||||
static int _ignore_mpath_component(struct cmd_context *cmd, struct dev_filter *f, struct device *dev, const char *use_filter_name)
|
||||
{
|
||||
dev_t mpath_devno = 0;
|
||||
|
||||
dev->filtered_flags &= ~DEV_FILTERED_MPATH_COMPONENT;
|
||||
|
||||
if (dev_is_mpath_component(cmd, dev)) {
|
||||
if (dev_is_mpath_component(cmd, dev, &mpath_devno)) {
|
||||
log_debug_devs("%s: Skipping mpath component device", dev_name(dev));
|
||||
dev->filtered_flags |= DEV_FILTERED_MPATH_COMPONENT;
|
||||
|
||||
/*
|
||||
* Warn about misconfig where an mpath component is
|
||||
* in the devices file, but its mpath device is not.
|
||||
*/
|
||||
if ((dev->flags & DEV_MATCHED_USE_ID) && mpath_devno) {
|
||||
if (!get_du_for_devno(cmd, mpath_devno)) {
|
||||
struct device *mpath_dev = dev_cache_get_by_devt(cmd, mpath_devno);
|
||||
log_warn("WARNING: devices file is missing %s (%d:%d) using multipath component %s.",
|
||||
mpath_dev ? dev_name(mpath_dev) : "unknown",
|
||||
(int)MAJOR(mpath_devno), (int)MINOR(mpath_devno), dev_name(dev));
|
||||
if (!_lvmdevices_update_msg && strcmp(get_cmd_name(), "lvmdevices")) {
|
||||
log_warn("See lvmdevices --update for devices file update.");
|
||||
_lvmdevices_update_msg = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,14 +30,6 @@ static int _passes_partitioned_filter(struct cmd_context *cmd, struct dev_filter
|
||||
dev->filtered_flags &= ~DEV_FILTERED_PARTITIONED;
|
||||
|
||||
ret = dev_is_partitioned(cmd, dev);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
/* let pass, call again after scan */
|
||||
log_debug_devs("filter partitioned deferred %s", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
if (dev->ext.src == DEV_EXT_NONE)
|
||||
log_debug_devs(MSG_SKIPPING, dev_name(dev));
|
||||
|
||||
@@ -109,8 +109,6 @@ static int _lookup_p(struct cmd_context *cmd, struct dev_filter *f, struct devic
|
||||
|
||||
/* Uncached, check filters and cache the result */
|
||||
if (!l) {
|
||||
dev->flags &= ~DEV_FILTER_AFTER_SCAN;
|
||||
|
||||
pass = pf->real->passes_filter(cmd, pf->real, dev, use_filter_name);
|
||||
|
||||
if (!pass) {
|
||||
@@ -120,21 +118,13 @@ static int _lookup_p(struct cmd_context *cmd, struct dev_filter *f, struct devic
|
||||
* because the deferred result won't change the exclude.
|
||||
*/
|
||||
l = PF_BAD_DEVICE;
|
||||
|
||||
} else if ((pass == -EAGAIN) || (dev->flags & DEV_FILTER_AFTER_SCAN)) {
|
||||
/*
|
||||
* When the filter result is deferred, we let the device
|
||||
* pass for now, but do not cache the result. We need to
|
||||
* rerun the filters later. At that point the final result
|
||||
* will be cached.
|
||||
*/
|
||||
log_debug_devs("filter cache deferred %s", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
pass = 1;
|
||||
goto out;
|
||||
|
||||
} else if (pass) {
|
||||
} else if (pass == 1) {
|
||||
l = PF_GOOD_DEVICE;
|
||||
} else {
|
||||
log_error("Ignore invalid filter result %d %s", pass, dev_name(dev));
|
||||
pass = 1;
|
||||
/* don't cache invalid result */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dev->filtered_flags) /* skipping reason already logged by filter */
|
||||
|
||||
@@ -33,13 +33,6 @@ static int _ignore_signature(struct cmd_context *cmd, struct dev_filter *f __att
|
||||
|
||||
dev->filtered_flags &= ~DEV_FILTERED_SIGNATURE;
|
||||
|
||||
if (!scan_bcache) {
|
||||
/* let pass, call again after scan */
|
||||
log_debug_devs("filter signature deferred %s", dev_name(dev));
|
||||
dev->flags |= DEV_FILTER_AFTER_SCAN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(buf, 0, BUFSIZE);
|
||||
|
||||
if (!dev_read_bytes(dev, 0, BUFSIZE, buf)) {
|
||||
|
||||
@@ -32,10 +32,6 @@ struct dev_filter *sysfs_filter_create(void);
|
||||
struct dev_filter *signature_filter_create(struct dev_types *dt);
|
||||
struct dev_filter *deviceid_filter_create(struct cmd_context *cmd);
|
||||
|
||||
struct dev_filter *internal_filter_create(void);
|
||||
int internal_filter_allow(struct dm_pool *mem, struct device *dev);
|
||||
void internal_filter_clear(void);
|
||||
|
||||
/*
|
||||
* patterns must be an array of strings of the form:
|
||||
* [ra]<sep><regex><sep>, eg,
|
||||
|
||||
@@ -459,7 +459,6 @@ static int _scan_dev_open(struct device *dev)
|
||||
const char *name;
|
||||
const char *modestr;
|
||||
struct stat sbuf;
|
||||
int retried = 0;
|
||||
int flags = 0;
|
||||
int fd, di;
|
||||
|
||||
@@ -479,14 +478,23 @@ static int _scan_dev_open(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
next_name:
|
||||
/*
|
||||
* All the names for this device (major:minor) are kept on
|
||||
* dev->aliases, the first one is the primary/preferred name.
|
||||
*
|
||||
* The default name preferences in dev-cache mean that the first
|
||||
* name in dev->aliases is not a symlink for scsi devices, but is
|
||||
* the /dev/mapper/ symlink for mpath devices.
|
||||
*
|
||||
* If preferred names are set to symlinks, should this
|
||||
* first attempt to open using a non-symlink?
|
||||
*
|
||||
* dm_list_first() returns NULL if the list is empty.
|
||||
*/
|
||||
if (!(name_list = dm_list_first(&dev->aliases))) {
|
||||
/* Shouldn't happen */
|
||||
log_error("Device open %s %d:%d has no path names.",
|
||||
dev_name(dev), (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
log_error("Device open %d:%d has no path names.",
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
return 0;
|
||||
}
|
||||
name_sl = dm_list_item(name_list, struct dm_str_list);
|
||||
@@ -514,50 +522,34 @@ static int _scan_dev_open(struct device *dev)
|
||||
modestr = "ro";
|
||||
}
|
||||
|
||||
retry_open:
|
||||
|
||||
fd = open(name, flags, 0777);
|
||||
|
||||
if (fd < 0) {
|
||||
if ((errno == EBUSY) && (flags & O_EXCL)) {
|
||||
log_error("Can't open %s exclusively. Mounted filesystem?",
|
||||
dev_name(dev));
|
||||
return 0;
|
||||
} else {
|
||||
int major, minor;
|
||||
|
||||
/*
|
||||
* Shouldn't happen, if it does, print stat info to help figure
|
||||
* out what's wrong.
|
||||
* drop name from dev->aliases and use verify_aliases to
|
||||
* drop any other invalid aliases before retrying open with
|
||||
* any remaining valid paths.
|
||||
*/
|
||||
|
||||
major = (int)MAJOR(dev->dev);
|
||||
minor = (int)MINOR(dev->dev);
|
||||
|
||||
log_error("Device open %s %d:%d failed errno %d", name, major, minor, errno);
|
||||
|
||||
if (stat(name, &sbuf)) {
|
||||
log_debug_devs("Device open %s %d:%d stat failed errno %d",
|
||||
name, major, minor, errno);
|
||||
} else if (sbuf.st_rdev != dev->dev) {
|
||||
log_debug_devs("Device open %s %d:%d stat %d:%d does not match.",
|
||||
name, major, minor,
|
||||
(int)MAJOR(sbuf.st_rdev), (int)MINOR(sbuf.st_rdev));
|
||||
}
|
||||
|
||||
if (!retried) {
|
||||
/*
|
||||
* FIXME: remove this, the theory for this retry is that
|
||||
* there may be a udev race that we can sometimes mask by
|
||||
* retrying. This is here until we can figure out if it's
|
||||
* needed and if so fix the real problem.
|
||||
*/
|
||||
usleep(5000);
|
||||
log_debug_devs("Device open %s retry", dev_name(dev));
|
||||
retried = 1;
|
||||
goto retry_open;
|
||||
}
|
||||
log_debug("Drop alias for %d:%d failed open %s (%d)",
|
||||
(int)MAJOR(dev->dev), (int)MINOR(dev->dev), name, errno);
|
||||
dev_cache_failed_path(dev, name);
|
||||
dev_cache_verify_aliases(dev);
|
||||
goto next_name;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Verify that major:minor from the path still match dev. */
|
||||
if ((fstat(fd, &sbuf) < 0) || (sbuf.st_rdev != dev->dev)) {
|
||||
log_warn("Invalid path %s for device %d:%d, trying different path.",
|
||||
name, (int)MAJOR(dev->dev), (int)MINOR(dev->dev));
|
||||
(void)close(fd);
|
||||
dev_cache_failed_path(dev, name);
|
||||
dev_cache_verify_aliases(dev);
|
||||
goto next_name;
|
||||
}
|
||||
|
||||
dev->flags |= DEV_IN_BCACHE;
|
||||
@@ -605,37 +597,6 @@ static int _scan_dev_close(struct device *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _drop_bad_aliases(struct device *dev)
|
||||
{
|
||||
struct dm_str_list *strl, *strl2;
|
||||
const char *name;
|
||||
struct stat sbuf;
|
||||
int major = (int)MAJOR(dev->dev);
|
||||
int minor = (int)MINOR(dev->dev);
|
||||
int bad;
|
||||
|
||||
dm_list_iterate_items_safe(strl, strl2, &dev->aliases) {
|
||||
name = strl->str;
|
||||
bad = 0;
|
||||
|
||||
if (stat(name, &sbuf)) {
|
||||
bad = 1;
|
||||
log_debug_devs("Device path check %d:%d %s stat failed errno %d",
|
||||
major, minor, name, errno);
|
||||
} else if (sbuf.st_rdev != dev->dev) {
|
||||
bad = 1;
|
||||
log_debug_devs("Device path check %d:%d %s stat %d:%d does not match.",
|
||||
major, minor, name,
|
||||
(int)MAJOR(sbuf.st_rdev), (int)MINOR(sbuf.st_rdev));
|
||||
}
|
||||
|
||||
if (bad) {
|
||||
log_debug_devs("Device path check %d:%d dropping path %s.", major, minor, name);
|
||||
dev_cache_failed_path(dev, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Like bcache_invalidate, only it throws any dirty data away if the
|
||||
// write fails.
|
||||
static void _invalidate_di(struct bcache *cache, int di)
|
||||
@@ -663,10 +624,8 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
char headers_buf[HEADERS_BUF_SIZE];
|
||||
struct dm_list wait_devs;
|
||||
struct dm_list done_devs;
|
||||
struct dm_list reopen_devs;
|
||||
struct device_list *devl, *devl2;
|
||||
struct block *bb;
|
||||
int retried_open = 0;
|
||||
int scan_read_errors = 0;
|
||||
int scan_process_errors = 0;
|
||||
int scan_failed_count = 0;
|
||||
@@ -677,7 +636,6 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
|
||||
dm_list_init(&wait_devs);
|
||||
dm_list_init(&done_devs);
|
||||
dm_list_init(&reopen_devs);
|
||||
|
||||
log_debug_devs("Scanning %d devices for VG info", dm_list_size(devs));
|
||||
|
||||
@@ -701,9 +659,9 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
|
||||
if (!_in_bcache(devl->dev)) {
|
||||
if (!_scan_dev_open(devl->dev)) {
|
||||
log_debug_devs("Scan failed to open %s.", dev_name(devl->dev));
|
||||
log_debug_devs("Scan failed to open %d:%d %s.",
|
||||
(int)MAJOR(devl->dev->dev), (int)MINOR(devl->dev->dev), dev_name(devl->dev));
|
||||
dm_list_del(&devl->list);
|
||||
dm_list_add(&reopen_devs, &devl->list);
|
||||
devl->dev->flags |= DEV_SCAN_NOT_READ;
|
||||
continue;
|
||||
}
|
||||
@@ -787,41 +745,6 @@ static int _scan_list(struct cmd_context *cmd, struct dev_filter *f,
|
||||
if (!dm_list_empty(devs))
|
||||
goto scan_more;
|
||||
|
||||
/*
|
||||
* We're done scanning all the devs. If we failed to open any of them
|
||||
* the first time through, refresh device paths and retry. We failed
|
||||
* to open the devs on the reopen_devs list.
|
||||
*
|
||||
* FIXME: it's not clear if or why this helps.
|
||||
*/
|
||||
if (!dm_list_empty(&reopen_devs)) {
|
||||
if (retried_open) {
|
||||
/* Don't try again. */
|
||||
scan_failed_count += dm_list_size(&reopen_devs);
|
||||
dm_list_splice(&done_devs, &reopen_devs);
|
||||
goto out;
|
||||
}
|
||||
retried_open = 1;
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &reopen_devs) {
|
||||
_drop_bad_aliases(devl->dev);
|
||||
|
||||
if (dm_list_empty(&devl->dev->aliases)) {
|
||||
log_warn("WARNING: Scan ignoring device %d:%d with no paths.",
|
||||
(int)MAJOR(devl->dev->dev),
|
||||
(int)MINOR(devl->dev->dev));
|
||||
|
||||
dm_list_del(&devl->list);
|
||||
lvmcache_del_dev(devl->dev);
|
||||
scan_failed_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Put devs that failed to open back on the original list to retry. */
|
||||
dm_list_splice(devs, &reopen_devs);
|
||||
goto scan_more;
|
||||
}
|
||||
out:
|
||||
log_debug_devs("Scanned devices: read errors %d process errors %d failed %d",
|
||||
scan_read_errors, scan_process_errors, scan_failed_count);
|
||||
|
||||
@@ -1180,7 +1103,7 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname,
|
||||
|
||||
dm_list_iterate_items_safe(devl, devl2, &devs) {
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) {
|
||||
log_print("%s excluded by filters: %s.",
|
||||
log_print("%s excluded: %s.",
|
||||
dev_name(devl->dev), dev_filtered_reason(devl->dev));
|
||||
dm_list_del(&devl->list);
|
||||
dm_list_add(&devs_drop, &devl->list);
|
||||
@@ -1246,7 +1169,7 @@ int label_scan_vg_online(struct cmd_context *cmd, const char *vgname,
|
||||
|
||||
/* Applies all filters, including those that need data from dev. */
|
||||
if (!cmd->filter->passes_filter(cmd, cmd->filter, devl->dev, NULL)) {
|
||||
log_print("%s excluded by filters: %s.",
|
||||
log_print("%s excluded: %s.",
|
||||
dev_name(devl->dev), dev_filtered_reason(devl->dev));
|
||||
dm_list_del(&devl->list);
|
||||
dm_list_add(&devs_drop, &devl->list);
|
||||
@@ -1738,9 +1661,11 @@ void label_scan_invalidate_lvs(struct cmd_context *cmd, struct dm_list *lvs)
|
||||
dev_t devt;
|
||||
|
||||
/*
|
||||
* FIXME: this is all unnecessary unless there are PVs stacked on LVs,
|
||||
* so we can skip all of this if scan_lvs=0.
|
||||
* This is only needed when the command sees PVs stacked on LVs which
|
||||
* will only happen with scan_lvs=1.
|
||||
*/
|
||||
if (!cmd->scan_lvs)
|
||||
return;
|
||||
log_debug("invalidating devs for any pvs on lvs");
|
||||
|
||||
if (get_device_list(NULL, &devs, &devs_features)) {
|
||||
|
||||
@@ -577,8 +577,9 @@ static int _extend_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg,
|
||||
(uint32_t)(new_size_sectors * SECTOR_SIZE));
|
||||
|
||||
lp.size = new_size_sectors;
|
||||
lp.pvh = &vg->pvs;
|
||||
|
||||
if (!lv_resize(lv, &lp, &vg->pvs)) {
|
||||
if (!lv_resize(cmd, lv, &lp)) {
|
||||
log_error("Extend sanlock LV %s to size %s failed.",
|
||||
display_lvname(lv), display_size(cmd, lp.size));
|
||||
return 0;
|
||||
@@ -2733,6 +2734,9 @@ int lockd_lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
if (!_lvmlockd_connected)
|
||||
return 0;
|
||||
|
||||
if (lv_is_lockd_sanlock_lv(lv))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* A special case for gfs2 where we want to allow lvextend
|
||||
* of an LV that has an existing shared lock, which is normally
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -297,6 +297,9 @@
|
||||
int lv_layout_and_role(struct dm_pool *mem, const struct logical_volume *lv,
|
||||
struct dm_list **layout, struct dm_list **role);
|
||||
|
||||
int lv_is_linear(struct logical_volume *lv);
|
||||
int lv_is_striped(struct logical_volume *lv);
|
||||
|
||||
/* Ordered list - see lv_manip.c */
|
||||
typedef enum {
|
||||
AREA_UNASSIGNED,
|
||||
@@ -661,50 +664,44 @@ struct pvcreate_params {
|
||||
};
|
||||
|
||||
struct lvresize_params {
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
const char *vg_name; /* only-used when VG is not yet opened (in /tools) */
|
||||
const char *lv_name;
|
||||
|
||||
const struct segment_type *segtype;
|
||||
|
||||
uint64_t poolmetadata_size;
|
||||
sign_t poolmetadata_sign;
|
||||
|
||||
/* Per LV applied parameters */
|
||||
|
||||
enum {
|
||||
LV_ANY = 0,
|
||||
LV_REDUCE = 1,
|
||||
LV_EXTEND = 2
|
||||
} resize;
|
||||
|
||||
int use_policies;
|
||||
|
||||
alloc_policy_t alloc;
|
||||
int yes;
|
||||
int force;
|
||||
int nosync;
|
||||
int nofsck;
|
||||
int resizefs;
|
||||
int use_policies;
|
||||
char fsopt[32]; /* set by --resizefs|--fs, empty for --fs ignore */
|
||||
|
||||
const struct segment_type *segtype;
|
||||
unsigned mirrors;
|
||||
uint32_t stripes;
|
||||
uint64_t stripe_size;
|
||||
|
||||
uint32_t extents;
|
||||
uint64_t size;
|
||||
uint32_t extents;
|
||||
sign_t sign;
|
||||
percent_type_t percent;
|
||||
percent_type_t percent; /* the type of percentage, not a value */
|
||||
uint32_t percent_value; /* 0 - 100 */
|
||||
uint64_t poolmetadata_size;
|
||||
sign_t poolmetadata_sign;
|
||||
uint32_t policy_percent_main;
|
||||
uint32_t policy_percent_meta;
|
||||
|
||||
int approx_alloc;
|
||||
int extents_are_pes; /* Is 'extents' counting PEs or LEs? */
|
||||
int size_changed; /* Was there actually a size change */
|
||||
int extend_fs_error; /* FS extend error after LV extend success */
|
||||
|
||||
const char *lockopt;
|
||||
char *lockd_lv_refresh_path; /* set during resize to use for refresh at the end */
|
||||
char *lockd_lv_refresh_uuid; /* set during resize to use for refresh at the end */
|
||||
|
||||
struct dm_list *pvh; /* list of pvs to use */
|
||||
};
|
||||
|
||||
void pvcreate_params_set_defaults(struct pvcreate_params *pp);
|
||||
@@ -745,9 +742,10 @@ int vgs_are_compatible(struct cmd_context *cmd,
|
||||
struct volume_group *vg_to);
|
||||
uint32_t vg_lock_newname(struct cmd_context *cmd, const char *vgname);
|
||||
|
||||
int lv_resize(struct logical_volume *lv,
|
||||
struct lvresize_params *lp,
|
||||
struct dm_list *pvh);
|
||||
int lv_resize(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct lvresize_params *lp);
|
||||
int lv_extend_policy_calculate_percent(struct logical_volume *lv,
|
||||
uint32_t *amount, uint32_t *meta_amount);
|
||||
|
||||
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const char *vgid,
|
||||
uint32_t read_flags, uint32_t lockd_state,
|
||||
|
||||
@@ -4533,7 +4533,7 @@ void vg_write_commit_bad_mdas(struct cmd_context *cmd, struct volume_group *vg)
|
||||
* reread metadata.
|
||||
*/
|
||||
|
||||
static bool _scan_text_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid)
|
||||
bool scan_text_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid)
|
||||
{
|
||||
DM_LIST_INIT(mda_list);
|
||||
struct mda_list *mdal, *safe;
|
||||
@@ -4706,7 +4706,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
|
||||
* probably unnecessary; all commands could likely just check a single mda.
|
||||
*/
|
||||
|
||||
if (lvmcache_scan_mismatch(cmd, vgname, vgid) || _scan_text_mismatch(cmd, vgname, vgid)) {
|
||||
if (lvmcache_scan_mismatch(cmd, vgname, vgid) || scan_text_mismatch(cmd, vgname, vgid)) {
|
||||
log_debug_metadata("Rescanning devices for %s %s", vgname, writing ? "rw" : "");
|
||||
if (writing)
|
||||
lvmcache_label_rescan_vg_rw(cmd, vgname, vgid);
|
||||
@@ -5302,3 +5302,15 @@ int get_visible_lvs_using_pv(struct cmd_context *cmd, struct volume_group *vg, s
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lv_is_linear(struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
return segtype_is_linear(seg->segtype);
|
||||
}
|
||||
|
||||
int lv_is_striped(struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
return segtype_is_striped(seg->segtype);
|
||||
}
|
||||
|
||||
|
||||
@@ -538,5 +538,7 @@ void set_pv_devices(struct format_instance *fid, struct volume_group *vg);
|
||||
int get_visible_lvs_using_pv(struct cmd_context *cmd, struct volume_group *vg, struct device *dev,
|
||||
struct dm_list *lvs_list);
|
||||
|
||||
bool scan_text_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -737,6 +737,7 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
|
||||
extents = MAX_SIZE;
|
||||
|
||||
if (!lv) {
|
||||
log_debug("Adding new pool metadata spare %u extents.", extents);
|
||||
if (!_alloc_pool_metadata_spare(vg, extents, pvh))
|
||||
return_0;
|
||||
|
||||
@@ -746,6 +747,8 @@ int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
|
||||
seg = last_seg(lv);
|
||||
seg_mirrors = lv_mirror_count(lv);
|
||||
|
||||
log_debug("Extending pool metadata spare from %u to %u extents.",
|
||||
lv->le_count, extents);
|
||||
/* Check spare LV is big enough and preserve segtype */
|
||||
if ((lv->le_count < extents) && seg &&
|
||||
!lv_extend(lv, seg->segtype,
|
||||
|
||||
@@ -126,6 +126,8 @@ lvchange \(em Change the attributes of logical volume(s)
|
||||
\fB--sysinit\fP
|
||||
.br
|
||||
\fB-t\fP|\fB--test\fP
|
||||
.br
|
||||
\fB--vdosettings\fP \fIString\fP
|
||||
.br
|
||||
\fB-v\fP|\fB--verbose\fP
|
||||
.br
|
||||
@@ -202,6 +204,8 @@ required, after which the others are optional.
|
||||
\fB--\fP[\fBraid\fP]\fBminrecoveryrate\fP \fISize\fP[k|UNIT]
|
||||
.br
|
||||
\fB--\fP[\fBraid\fP]\fBmaxrecoveryrate\fP \fISize\fP[k|UNIT]
|
||||
.br
|
||||
\fB--vdosettings\fP \fIString\fP
|
||||
.br
|
||||
\fB--\fP[\fBraid\fP]\fBwritebehind\fP \fINumber\fP
|
||||
.br
|
||||
@@ -545,12 +549,13 @@ See \fBlvmcache\fP(7) for more information.
|
||||
.HP
|
||||
\fB--cachesettings\fP \fIString\fP
|
||||
.br
|
||||
Specifies tunable values for a cache LV in "Key = Value" form.
|
||||
Repeat this option to specify multiple values.
|
||||
(The default values should usually be adequate.)
|
||||
The special string value \fBdefault\fP switches
|
||||
settings back to their default kernel values and removes
|
||||
them from the list of settings stored in LVM metadata.
|
||||
Specifies tunable kernel options for dm-cache or dm-writecache LVs.
|
||||
Use the form 'option=value' or 'option1=value option2=value', or
|
||||
repeat --cachesettings for each option being set.
|
||||
These settings override the default kernel behaviors which are
|
||||
usually adequate. To remove cachesettings and revert to the default
|
||||
kernel behaviors, use --cachesettings 'default' for dm-cache or
|
||||
an empty string --cachesettings '' for dm-writecache.
|
||||
See \fBlvmcache\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
@@ -609,8 +614,9 @@ See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -752,7 +758,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
@@ -927,6 +934,17 @@ error messages in multi-stage operations if a tool relies on reading
|
||||
back metadata it believes has changed but hasn't.
|
||||
.
|
||||
.HP
|
||||
\fB--vdosettings\fP \fIString\fP
|
||||
.br
|
||||
Specifies tunable VDO options for VDO LVs.
|
||||
Use the form 'option=value' or 'option1=value option2=value', or
|
||||
repeat --vdosettings for each option being set.
|
||||
These settings override the default VDO behaviors.
|
||||
To remove vdosettings and revert to the default
|
||||
VDO behaviors, use --vdosettings 'default'.
|
||||
See \fBlvmvdo\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
|
||||
@@ -155,6 +155,8 @@ lvconvert \(em Change logical volume layout
|
||||
\fB--usepolicies\fP
|
||||
.br
|
||||
\fB--vdopool\fP \fILV\fP
|
||||
.br
|
||||
\fB--vdosettings\fP \fIString\fP
|
||||
.br
|
||||
\fB-v\fP|\fB--verbose\fP
|
||||
.br
|
||||
@@ -742,6 +744,8 @@ Convert LV to type vdopool.
|
||||
.br
|
||||
[ \fB--deduplication\fP \fBy\fP|\fBn\fP ]
|
||||
.br
|
||||
[ \fB--vdosettings\fP \fIString\fP ]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.ad b
|
||||
.RE
|
||||
@@ -1064,12 +1068,13 @@ The name of a cache pool.
|
||||
.HP
|
||||
\fB--cachesettings\fP \fIString\fP
|
||||
.br
|
||||
Specifies tunable values for a cache LV in "Key = Value" form.
|
||||
Repeat this option to specify multiple values.
|
||||
(The default values should usually be adequate.)
|
||||
The special string value \fBdefault\fP switches
|
||||
settings back to their default kernel values and removes
|
||||
them from the list of settings stored in LVM metadata.
|
||||
Specifies tunable kernel options for dm-cache or dm-writecache LVs.
|
||||
Use the form 'option=value' or 'option1=value option2=value', or
|
||||
repeat --cachesettings for each option being set.
|
||||
These settings override the default kernel behaviors which are
|
||||
usually adequate. To remove cachesettings and revert to the default
|
||||
kernel behaviors, use --cachesettings 'default' for dm-cache or
|
||||
an empty string --cachesettings '' for dm-writecache.
|
||||
See \fBlvmcache\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
@@ -1131,8 +1136,9 @@ See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -1303,7 +1309,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
@@ -1535,6 +1542,17 @@ The name of a VDO pool LV.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.
|
||||
.HP
|
||||
\fB--vdosettings\fP \fIString\fP
|
||||
.br
|
||||
Specifies tunable VDO options for VDO LVs.
|
||||
Use the form 'option=value' or 'option1=value option2=value', or
|
||||
repeat --vdosettings for each option being set.
|
||||
These settings override the default VDO behaviors.
|
||||
To remove vdosettings and revert to the default
|
||||
VDO behaviors, use --vdosettings 'default'.
|
||||
See \fBlvmvdo\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
@@ -1808,6 +1826,8 @@ Convert LV to type vdopool.
|
||||
.br
|
||||
[ \fB--deduplication\fP \fBy\fP|\fBn\fP ]
|
||||
.br
|
||||
[ \fB--vdosettings\fP \fIString\fP ]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.ad b
|
||||
.RE
|
||||
|
||||
@@ -157,6 +157,8 @@ lvcreate \(em Create a logical volume
|
||||
\fB--vdo\fP
|
||||
.br
|
||||
\fB--vdopool\fP \fILV\fP
|
||||
.br
|
||||
\fB--vdosettings\fP \fIString\fP
|
||||
.br
|
||||
\fB-v\fP|\fB--verbose\fP
|
||||
.br
|
||||
@@ -537,6 +539,8 @@ Create a LV that returns VDO when used.
|
||||
.br
|
||||
[ \fB--deduplication\fP \fBy\fP|\fBn\fP ]
|
||||
.br
|
||||
[ \fB--vdosettings\fP \fIString\fP ]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.ad b
|
||||
.RE
|
||||
@@ -927,12 +931,13 @@ The name of a cache pool.
|
||||
.HP
|
||||
\fB--cachesettings\fP \fIString\fP
|
||||
.br
|
||||
Specifies tunable values for a cache LV in "Key = Value" form.
|
||||
Repeat this option to specify multiple values.
|
||||
(The default values should usually be adequate.)
|
||||
The special string value \fBdefault\fP switches
|
||||
settings back to their default kernel values and removes
|
||||
them from the list of settings stored in LVM metadata.
|
||||
Specifies tunable kernel options for dm-cache or dm-writecache LVs.
|
||||
Use the form 'option=value' or 'option1=value option2=value', or
|
||||
repeat --cachesettings for each option being set.
|
||||
These settings override the default kernel behaviors which are
|
||||
usually adequate. To remove cachesettings and revert to the default
|
||||
kernel behaviors, use --cachesettings 'default' for dm-cache or
|
||||
an empty string --cachesettings '' for dm-writecache.
|
||||
See \fBlvmcache\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
@@ -1003,8 +1008,9 @@ See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -1190,7 +1196,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosync\fP
|
||||
@@ -1438,6 +1445,17 @@ The name of a VDO pool LV.
|
||||
See \fBlvmvdo\fP(7) for more information about VDO usage.
|
||||
.
|
||||
.HP
|
||||
\fB--vdosettings\fP \fIString\fP
|
||||
.br
|
||||
Specifies tunable VDO options for VDO LVs.
|
||||
Use the form 'option=value' or 'option1=value option2=value', or
|
||||
repeat --vdosettings for each option being set.
|
||||
These settings override the default VDO behaviors.
|
||||
To remove vdosettings and revert to the default
|
||||
VDO behaviors, use --vdosettings 'default'.
|
||||
See \fBlvmvdo\fP(7) for more information.
|
||||
.
|
||||
.HP
|
||||
\fB-v\fP|\fB--verbose\fP ...
|
||||
.br
|
||||
Set verbose level. Repeat from 1 to 4 times to increase the detail
|
||||
@@ -1966,6 +1984,8 @@ Create a VDO LV with VDO pool.
|
||||
.br
|
||||
[ \fB--deduplication\fP \fBy\fP|\fBn\fP ]
|
||||
.br
|
||||
[ \fB--vdosettings\fP \fIString\fP ]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.ad b
|
||||
.RE
|
||||
@@ -1996,6 +2016,8 @@ Create a VDO LV with VDO pool.
|
||||
.br
|
||||
[ \fB--deduplication\fP \fBy\fP|\fBn\fP ]
|
||||
.br
|
||||
[ \fB--vdosettings\fP \fIString\fP ]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.ad b
|
||||
.RE
|
||||
|
||||
@@ -186,8 +186,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -278,7 +279,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosuffix\fP
|
||||
|
||||
@@ -328,8 +328,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -423,7 +424,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosync\fP
|
||||
|
||||
@@ -169,8 +169,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -254,7 +255,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosuffix\fP
|
||||
|
||||
@@ -115,8 +115,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -181,7 +182,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--polloperation\fP \fBpvmove\fP|\fBconvert\fP|\fBmerge\fP|\fBmerge_thin\fP
|
||||
|
||||
@@ -156,8 +156,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -261,7 +262,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -85,6 +85,7 @@ is used for dm crypt devices, reported by sysfs.
|
||||
.IP \[bu] 2
|
||||
.B md_uuid
|
||||
is used for md devices, reported by sysfs.
|
||||
.IP \[bu] 2
|
||||
.B lvmlv_uuid
|
||||
is used if a PV is placed on top of an lvm LV, reported by sysfs.
|
||||
.IP \[bu] 2
|
||||
|
||||
@@ -24,7 +24,7 @@ lvmdevices \(em Manage the devices file
|
||||
.br
|
||||
\fB-d\fP|\fB--debug\fP
|
||||
.br
|
||||
\fB--deldev\fP \fIPV\fP
|
||||
\fB--deldev\fP \fIString\fP
|
||||
.br
|
||||
\fB--delpvid\fP \fIString\fP
|
||||
.br
|
||||
@@ -152,6 +152,7 @@ is used for dm crypt devices, reported by sysfs.
|
||||
.IP \[bu] 2
|
||||
.B md_uuid
|
||||
is used for md devices, reported by sysfs.
|
||||
.IP \[bu] 2
|
||||
.B lvmlv_uuid
|
||||
is used if a PV is placed on top of an lvm LV, reported by sysfs.
|
||||
.IP \[bu] 2
|
||||
@@ -226,10 +227,12 @@ Add a device to the devices file.
|
||||
Remove a device from the devices file.
|
||||
.br
|
||||
.P
|
||||
\fBlvmdevices\fP \fB--deldev\fP \fIPV\fP
|
||||
\fBlvmdevices\fP \fB--deldev\fP \fIString\fP|\fIPV\fP
|
||||
.br
|
||||
.RS 4
|
||||
.ad l
|
||||
[ \fB--deviceidtype\fP \fIString\fP ]
|
||||
.br
|
||||
[ COMMON_OPTIONS ]
|
||||
.ad b
|
||||
.RE
|
||||
@@ -346,9 +349,11 @@ Set debug level. Repeat from 1 to 6 times to increase the detail of
|
||||
messages sent to the log file and/or syslog (if configured).
|
||||
.
|
||||
.HP
|
||||
\fB--deldev\fP \fIPV\fP
|
||||
\fB--deldev\fP \fIString\fP
|
||||
.br
|
||||
Remove a device from the devices file.
|
||||
When used alone, --deldev specifies a device name.
|
||||
When used with --deviceidtype, --deldev specifies a device id.
|
||||
.
|
||||
.HP
|
||||
\fB--delpvid\fP \fIString\fP
|
||||
@@ -365,8 +370,9 @@ 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
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -420,7 +426,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -102,8 +102,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -162,7 +163,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -132,6 +132,19 @@ that can keep 100% incompressible data there.
|
||||
# lvconvert --type vdo-pool -n vdo0 -V10G vg/ExistingLV
|
||||
.fi
|
||||
.
|
||||
.SS \n+[step]. Change the compression and deduplication of a VDOPoolLV
|
||||
.
|
||||
Disable or enable the compression and deduplication for VDOPoolLV
|
||||
(the volume that maintains all VDO LV(s) associated with it).
|
||||
.P
|
||||
.B lvchange --compression y|n --deduplication y|n VG/VDOPoolLV
|
||||
.P
|
||||
.I Example
|
||||
.nf
|
||||
# lvchange --compression n vg/vdopool0
|
||||
# lvchange --deduplication y vg/vdopool1
|
||||
.fi
|
||||
.
|
||||
.SS \n+[step]. Change the default settings used for creating a VDOPoolLV
|
||||
.
|
||||
VDO allows to set a large variety of options. Lots of these settings
|
||||
@@ -173,17 +186,27 @@ EOF
|
||||
# lvcreate --vdo -L10G --config 'allocation/vdo_cpu_threads=4' vg/vdopool1
|
||||
.fi
|
||||
.
|
||||
.SS \n+[step]. Change the compression and deduplication of a VDOPoolLV
|
||||
.SS \n+[step]. Set or change VDO settings with option --vdosettings
|
||||
.
|
||||
Disable or enable the compression and deduplication for VDOPoolLV
|
||||
(the volume that maintains all VDO LV(s) associated with it).
|
||||
.P
|
||||
.B lvchange --compression y|n --deduplication y|n VG/VDOPoolLV
|
||||
Use the form 'option=value' or 'option1=value option2=value',
|
||||
or repeat --vdosettings for each option being set.
|
||||
Options are listed in the Example section above, for the full description see
|
||||
.BR lvm.conf (5).
|
||||
Options can omit 'vdo_' and 'vdo_use_' prefixes and all its underscores.
|
||||
So i.e. vdo_use_metadata_hints=1 and metadatahints=1 are equivalent.
|
||||
To change the option for an already existing VDOPoolLV use
|
||||
.BR lvchange (8)
|
||||
command. However not all option can be changed.
|
||||
Only compression and deduplication options can be also changed for an active VDO LV.
|
||||
Lowest priority options are specified with configuration file,
|
||||
then with --vdosettings and highest are expliction option --compression
|
||||
and --deduplication.
|
||||
.P
|
||||
.I Example
|
||||
.P
|
||||
.nf
|
||||
# lvchange --compression n vg/vdopool0
|
||||
# lvchange --deduplication y vg/vdopool1
|
||||
# lvcreate --vdo -L10G --vdosettings 'ack_threads=1 hash_zone_threads=2' vg/vdopool0
|
||||
# lvchange --vdosettings 'bio_threads=2 deduplication=1' vg/vdopool0
|
||||
.fi
|
||||
.
|
||||
.SS \n+[step]. Checking the usage of VDOPoolLV
|
||||
|
||||
@@ -130,8 +130,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -220,7 +221,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
|
||||
@@ -136,8 +136,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -204,7 +205,8 @@ metadata/record_lvs_history is enabled.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
|
||||
@@ -120,8 +120,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -175,7 +176,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
|
||||
@@ -286,8 +286,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -376,7 +377,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosync\fP
|
||||
|
||||
@@ -172,8 +172,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -264,7 +265,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosuffix\fP
|
||||
|
||||
@@ -119,8 +119,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -180,7 +181,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -179,8 +179,9 @@ multiple tags at once. See \fBlvm\fP(8) for information about tags.
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -248,7 +249,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -351,8 +351,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -435,7 +436,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -229,8 +229,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -319,7 +320,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--norestorefile\fP
|
||||
|
||||
@@ -183,8 +183,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -266,7 +267,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosuffix\fP
|
||||
|
||||
@@ -206,8 +206,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -271,7 +272,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
|
||||
@@ -103,8 +103,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -164,7 +165,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -98,8 +98,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -153,7 +154,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -169,8 +169,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -254,7 +255,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosuffix\fP
|
||||
|
||||
@@ -383,8 +383,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -469,7 +470,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
|
||||
@@ -123,8 +123,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -197,7 +198,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -208,8 +208,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -291,7 +292,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -568,8 +568,9 @@ See \fBlvm.conf\fP(5) for more information about profiles.
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -694,7 +695,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
|
||||
@@ -114,8 +114,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -169,7 +170,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -124,8 +124,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -206,7 +207,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -206,8 +206,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -313,7 +314,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB-s\fP|\fB--physicalextentsize\fP \fISize\fP[m|UNIT]
|
||||
|
||||
@@ -180,8 +180,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -258,7 +259,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosuffix\fP
|
||||
|
||||
@@ -139,8 +139,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -194,7 +195,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -147,8 +147,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -237,7 +238,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -128,8 +128,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -189,7 +190,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -113,8 +113,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -179,7 +180,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -132,8 +132,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -193,7 +194,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -107,8 +107,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -167,7 +168,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP
|
||||
|
||||
@@ -108,8 +108,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -169,7 +170,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -199,8 +199,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -265,7 +266,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -109,8 +109,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -170,7 +171,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--noudevsync\fP
|
||||
|
||||
@@ -133,8 +133,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -194,7 +195,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--profile\fP \fIString\fP
|
||||
|
||||
@@ -166,8 +166,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -251,7 +252,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--nosuffix\fP
|
||||
|
||||
@@ -101,8 +101,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -168,7 +169,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--notifydbus\fP
|
||||
|
||||
@@ -175,8 +175,9 @@ messages sent to the log file and/or syslog (if configured).
|
||||
.HP
|
||||
\fB--devices\fP \fIPV\fP
|
||||
.br
|
||||
Devices that the command can use. This option can be repeated
|
||||
or accepts a comma separated list of devices. This overrides
|
||||
Restricts the devices that are visible and accessible to the command.
|
||||
Devices not listed will appear to be missing. This option can be
|
||||
repeated, or accepts a comma separated list of devices. This overrides
|
||||
the devices file.
|
||||
.
|
||||
.HP
|
||||
@@ -255,7 +256,8 @@ perform standard hint file invalidation where appropriate.
|
||||
.HP
|
||||
\fB--nolocking\fP
|
||||
.br
|
||||
Disable locking.
|
||||
Disable locking. Use with caution, concurrent commands may produce
|
||||
incorrect results.
|
||||
.
|
||||
.HP
|
||||
\fB--poolmetadataspare\fP \fBy\fP|\fBn\fP
|
||||
|
||||
@@ -125,15 +125,6 @@ get_kb_size_with_unit_() {
|
||||
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
|
||||
@@ -328,12 +319,12 @@ allocation {
|
||||
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_cache_size_mb = $(( $(get_kb_size_with_unit_ "$vdo_blockMapCacheSize") / 1024 ))
|
||||
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_slab_size_mb = $(( $(get_kb_size_with_unit_ "$vdo_blockMapCacheSize") / 1024 ))
|
||||
vdo_ack_threads = $vdo_ackThreads
|
||||
vdo_bio_threads = $vdo_bioThreads
|
||||
vdo_bio_rotation = $vdo_bioRotationInterval
|
||||
@@ -417,7 +408,7 @@ EOF
|
||||
# Note: that this is spelled OPPOSITE the other $IS_LV checks.
|
||||
if [ "$IS_LV" = "1" ]; then
|
||||
verbose "Removing now-unused VDO entry from VDO config."
|
||||
dry "$VDO" remove $VDOCONF --force --verbose --name "$VDONAME"
|
||||
dry "$VDO" remove $VDOCONF $VERB --force --name "$VDONAME"
|
||||
fi
|
||||
|
||||
rm -fr "$TEMPDIR"
|
||||
|
||||
@@ -369,6 +369,7 @@ LIB = $(addprefix lib/, $(LIB_SECURETEST) $(LIB_DMSECURETEST) $(LIB_SHARED) $(LI
|
||||
$(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/lvm_import_vdo.sh lib/lvm_import_vdo
|
||||
$(Q) which vdo || $(LN_S) -f $(abs_top_srcdir)/test/lib/lvm_vdo_wrapper.sh lib/vdo
|
||||
@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/"; \
|
||||
|
||||
@@ -23,6 +23,9 @@ import os
|
||||
|
||||
g_tmo = 0
|
||||
|
||||
# Approx. min size
|
||||
VDO_MIN_SIZE = mib(8192)
|
||||
|
||||
# Prefix on created objects to enable easier clean-up
|
||||
g_prefix = os.getenv('PREFIX', '')
|
||||
|
||||
@@ -37,9 +40,10 @@ pv_device_list = os.getenv('LVM_DBUSD_PV_DEVICE_LIST', None)
|
||||
|
||||
# Default is to test all modes
|
||||
# 0 == Only test fork & exec mode
|
||||
# 1 == Test both fork & exec & lvm shell mode (default)
|
||||
# 1 == Only test lvm shell mode
|
||||
# 2 == Test both fork & exec & lvm shell mode (default)
|
||||
# Other == Test just lvm shell mode
|
||||
test_shell = os.getenv('LVM_DBUSD_TEST_MODE', 1)
|
||||
test_shell = os.getenv('LVM_DBUSD_TEST_MODE', 2)
|
||||
|
||||
# LVM binary to use
|
||||
LVM_EXECUTABLE = os.getenv('LVM_BINARY', '/usr/sbin/lvm')
|
||||
@@ -149,7 +153,7 @@ def get_objects():
|
||||
rc[interface].append(proxy)
|
||||
|
||||
# At this point we have a full population of everything, we now need to
|
||||
# prune the the objects if we are filtering PVs with a sub selection.
|
||||
# prune the objects if we are filtering PVs with a sub selection.
|
||||
return _prune(rc, pv_device_list), bus
|
||||
|
||||
|
||||
@@ -673,6 +677,20 @@ class TestDbusService(unittest.TestCase):
|
||||
EOD), vg, LV_BASE_INT)
|
||||
self._validate_lookup("%s/%s" % (vg.Name, lv_name), lv.object_path)
|
||||
|
||||
def test_prop_get(self):
|
||||
lv_name = lv_n()
|
||||
vg = self._vg_create().Vg
|
||||
lv = self._test_lv_create(
|
||||
vg.LvCreate,
|
||||
(dbus.String(lv_name), dbus.UInt64(mib(4)),
|
||||
dbus.Array([], signature='(ott)'), dbus.Int32(g_tmo),
|
||||
EOD), vg, LV_BASE_INT)
|
||||
ri = RemoteInterface(lv.dbus_object, interface=LV_COMMON_INT, introspect=False)
|
||||
|
||||
ri.update()
|
||||
for prop_name in ri.get_property_names():
|
||||
self.assertEqual(ri.get_property_value(prop_name), getattr(ri, prop_name))
|
||||
|
||||
def test_lv_create_job(self):
|
||||
lv_name = lv_n()
|
||||
vg = self._vg_create().Vg
|
||||
@@ -882,8 +900,19 @@ class TestDbusService(unittest.TestCase):
|
||||
j.Remove()
|
||||
|
||||
break
|
||||
else:
|
||||
# Most of the time we will get this exception as expected, but there is
|
||||
# a race condition between checking if it's complete and removing it (we want to try to remove while
|
||||
# it's not complete to raise the exception)
|
||||
# Thus, we can't reliably use self.assertRaises.
|
||||
# We have included it here to test this path in the daemon.
|
||||
try:
|
||||
j.Remove()
|
||||
except dbus.exceptions.DBusException:
|
||||
pass
|
||||
|
||||
if j.Wait(1):
|
||||
self.assertTrue(j.Wait(0))
|
||||
j.update()
|
||||
self.assertTrue(j.Complete)
|
||||
|
||||
@@ -1096,7 +1125,7 @@ class TestDbusService(unittest.TestCase):
|
||||
def _test_expired_timer(self, num_lvs):
|
||||
rc = False
|
||||
|
||||
# In small configurations lvm is pretty snappy, so lets create a VG
|
||||
# In small configurations lvm is pretty snappy, so let's create a VG
|
||||
# add a number of LVs and then remove the VG and all the contained
|
||||
# LVs which appears to consistently run a little slow.
|
||||
|
||||
@@ -1155,7 +1184,7 @@ class TestDbusService(unittest.TestCase):
|
||||
return
|
||||
|
||||
# This may not pass
|
||||
for i in [48, 64, 128]:
|
||||
for i in [128, 256]:
|
||||
yes = self._test_expired_timer(i)
|
||||
if yes:
|
||||
break
|
||||
@@ -1766,7 +1795,7 @@ class TestDbusService(unittest.TestCase):
|
||||
self.assertTrue(ec == 0, "%s exit code = %d" % (operation, ec))
|
||||
|
||||
def test_external_vg_create(self):
|
||||
# We need to ensure that if a user creates something outside of lvm
|
||||
# We need to ensure that if a user creates something outside lvm
|
||||
# dbus service that things are sequenced correctly so that if a dbus
|
||||
# user calls into the service they will find the same information.
|
||||
vg_name = vg_n()
|
||||
@@ -1779,8 +1808,8 @@ class TestDbusService(unittest.TestCase):
|
||||
self._verify_existence(cmd, cmd[0], vg_name)
|
||||
|
||||
def test_external_lv_create(self):
|
||||
# Lets create a LV outside of service and see if we correctly handle
|
||||
# it's inclusion
|
||||
# Let's create a LV outside of service and see if we correctly handle
|
||||
# its inclusion
|
||||
vg = self._vg_create().Vg
|
||||
lv_name = lv_n()
|
||||
full_name = "%s/%s" % (vg.Name, lv_name)
|
||||
@@ -1789,8 +1818,8 @@ class TestDbusService(unittest.TestCase):
|
||||
self._verify_existence(cmd, cmd[0], full_name)
|
||||
|
||||
def test_external_pv_create(self):
|
||||
# Lets create a PV outside of service and see if we correctly handle
|
||||
# it's inclusion
|
||||
# Let's create a PV outside of service and see if we correctly handle
|
||||
# its inclusion
|
||||
target = self.objs[PV_INT][0]
|
||||
|
||||
# Remove the PV
|
||||
@@ -1836,7 +1865,7 @@ class TestDbusService(unittest.TestCase):
|
||||
#
|
||||
# NOTE: This needs an equivalent of aux extend_filter_LVMTEST
|
||||
# when run from lvm2 testsuite. See dbustest.sh.
|
||||
# Also if developing locally with actual devices one can achieve this
|
||||
# Also, if developing locally with actual devices one can achieve this
|
||||
# by editing lvm.conf with "devices/scan_lvs = 1" As testing
|
||||
# typically utilizes loopback, this test is skipped in
|
||||
# those environments.
|
||||
@@ -1851,7 +1880,7 @@ class TestDbusService(unittest.TestCase):
|
||||
pv_object_path = self._create_nested(pv_object_path)
|
||||
|
||||
def test_pv_symlinks(self):
|
||||
# Lets take one of our test PVs, pvremove it, find a symlink to it
|
||||
# Let's take one of our test PVs, pvremove it, find a symlink to it
|
||||
# and re-create using the symlink to ensure we return an object
|
||||
# path to it. Additionally, we will take the symlink and do a lookup
|
||||
# (Manager.LookUpByLvmId) using it and the original device path to
|
||||
@@ -1873,7 +1902,7 @@ class TestDbusService(unittest.TestCase):
|
||||
rc = self._lookup(pv_device_path)
|
||||
self.assertEqual(rc, '/')
|
||||
|
||||
# Lets locate a symlink for it
|
||||
# Let's locate a symlink for it
|
||||
devices = glob('/dev/disk/*/*')
|
||||
rp_pv_device_path = os.path.realpath(pv_device_path)
|
||||
for d in devices:
|
||||
@@ -1907,8 +1936,8 @@ class TestDbusService(unittest.TestCase):
|
||||
vdo_pool_object_path = self.handle_return(
|
||||
vg_proxy.VgVdo.CreateVdoPoolandLv(
|
||||
pool_name, lv_name,
|
||||
dbus.UInt64(mib(4096)), # Appears to be minimum size
|
||||
dbus.UInt64(mib(8192)),
|
||||
dbus.UInt64(VDO_MIN_SIZE),
|
||||
dbus.UInt64(VDO_MIN_SIZE * 2),
|
||||
dbus.Int32(g_tmo),
|
||||
EOD))
|
||||
|
||||
@@ -1938,7 +1967,7 @@ class TestDbusService(unittest.TestCase):
|
||||
raise unittest.SkipTest('vdo not supported')
|
||||
|
||||
# Do this twice to ensure we are providing the correct flags to force
|
||||
# the operation when if finds an existing vdo signature, which likely
|
||||
# the operation when it finds an existing vdo signature, which likely
|
||||
# shouldn't exist.
|
||||
for _ in range(0, 2):
|
||||
vg, _, _ = self._create_vdo_pool_and_lv()
|
||||
@@ -1950,7 +1979,7 @@ class TestDbusService(unittest.TestCase):
|
||||
vg_proxy = self._vg_create(vg_prefix="vdo_conv_")
|
||||
lv = self._test_lv_create(
|
||||
vg_proxy.Vg.LvCreate,
|
||||
(dbus.String(pool_name), dbus.UInt64(mib(4096)),
|
||||
(dbus.String(pool_name), dbus.UInt64(VDO_MIN_SIZE),
|
||||
dbus.Array([], signature='(ott)'), dbus.Int32(g_tmo),
|
||||
EOD), vg_proxy.Vg, LV_BASE_INT)
|
||||
lv_obj_path = self._lookup("%s/%s" % (vg_proxy.Vg.Name, pool_name))
|
||||
@@ -1959,7 +1988,7 @@ class TestDbusService(unittest.TestCase):
|
||||
vdo_pool_path = self.handle_return(
|
||||
vg_proxy.VgVdo.CreateVdoPool(
|
||||
dbus.ObjectPath(lv.object_path), lv_name,
|
||||
dbus.UInt64(mib(8192)),
|
||||
dbus.UInt64(VDO_MIN_SIZE),
|
||||
dbus.Int32(g_tmo),
|
||||
EOD))
|
||||
|
||||
@@ -2078,15 +2107,19 @@ if __name__ == '__main__':
|
||||
if mode == 0:
|
||||
std_err_print('\n*** Testing only lvm fork & exec test mode ***\n')
|
||||
elif mode == 1:
|
||||
std_err_print('\n*** Testing only lvm shell mode ***\n')
|
||||
elif mode == 2:
|
||||
std_err_print('\n*** Testing fork & exec & lvm shell mode ***\n')
|
||||
else:
|
||||
std_err_print('\n*** Testing only lvm shell mode ***\n')
|
||||
std_err_print("Unsupported \"LVM_DBUSD_TEST_MODE\"=%d, [0-2] valid" % mode)
|
||||
sys.exit(1)
|
||||
|
||||
for g_tmo in [0, 15]:
|
||||
std_err_print('Testing TMO=%d\n' % g_tmo)
|
||||
if mode == 0:
|
||||
if set_execution(False, r):
|
||||
r.register_result(unittest.main(exit=False))
|
||||
elif mode == 2:
|
||||
elif mode == 1:
|
||||
if set_execution(True, r):
|
||||
r.register_result(unittest.main(exit=False))
|
||||
else:
|
||||
|
||||
@@ -183,6 +183,7 @@ class RemoteInterface(object):
|
||||
verify_type(
|
||||
vl, self.introspect[self.interface]
|
||||
['properties'][kl]['p_type'])
|
||||
self.p_name[kl] = True
|
||||
setattr(self, kl, vl)
|
||||
|
||||
@property
|
||||
@@ -196,6 +197,7 @@ class RemoteInterface(object):
|
||||
self.interface = interface
|
||||
self.introspect = introspect
|
||||
self.tmo = 0
|
||||
self.p_name = {}
|
||||
|
||||
if timelimit >= 0:
|
||||
self.tmo = float(timelimit)
|
||||
@@ -213,7 +215,7 @@ class RemoteInterface(object):
|
||||
|
||||
def _wrapper(self, _method_name, *args, **kwargs):
|
||||
|
||||
# Lets see how long a method takes to execute, in call cases we should
|
||||
# Let's see how long a method takes to execute, in call cases we should
|
||||
# return something when the time limit has been reached.
|
||||
start = time.time()
|
||||
result = getattr(self.dbus_interface, _method_name)(*args, **kwargs)
|
||||
@@ -241,6 +243,14 @@ class RemoteInterface(object):
|
||||
def update(self):
|
||||
self._set_props()
|
||||
|
||||
def get_property_names(self):
|
||||
return self.p_name.keys()
|
||||
|
||||
def get_property_value(self, name):
|
||||
prop_interface = dbus.Interface(
|
||||
self.dbus_object, 'org.freedesktop.DBus.Properties')
|
||||
return prop_interface.Get(self.interface, name)
|
||||
|
||||
|
||||
class ClientProxy(object):
|
||||
|
||||
|
||||
353
test/lib/lvm_vdo_wrapper.sh
Executable file
353
test/lib/lvm_vdo_wrapper.sh
Executable file
@@ -0,0 +1,353 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Wrapper script for 'naive' emulation of vdo manager tool for systems
|
||||
# that no longer have this tool present
|
||||
#
|
||||
|
||||
set -euE -o pipefail
|
||||
|
||||
# tool for formating 'old' VDO metadata format
|
||||
LVM_VDO_FORMAT=${LVM_VDO_FORMAT-"oldvdoformat"}
|
||||
# tool for shifting VDO metadata header by 2MiB
|
||||
LVM_VDO_PREPARE=${LVM_VDO_PREPARE-"oldvdoprepareforlvm"}
|
||||
# default vdo conf file
|
||||
LVM_VDO_DEFAULT_CONF=${LVM_VDO_DEFAULT_CONF-"/tmp/vdoconf.yml"}
|
||||
|
||||
vdo_die_() {
|
||||
echo -e "$@" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
vdo_verbose_() {
|
||||
test -z "$vdo_verbose" || echo "$0:" "$@"
|
||||
}
|
||||
|
||||
vdo_dry_() {
|
||||
if test -n "$vdo_dry"; then
|
||||
vdo_verbose_ "Dry execution" "$@"
|
||||
return 0
|
||||
fi
|
||||
vdo_verbose_ "Executing" "$@"
|
||||
"$@"
|
||||
}
|
||||
|
||||
vdo_get_kb_size_with_unit_() {
|
||||
local sz=${2-1} # 2nd. arg as unit - default 'k'
|
||||
|
||||
case "$sz" in
|
||||
[mM]) sz=1024 ;;
|
||||
esac
|
||||
|
||||
case "$1" in
|
||||
*[mM]) sz=1024 ;;
|
||||
*[gG]) sz=$(( 1024 * 1024 )) ;;
|
||||
*[tT]) sz=$(( 1024 * 1024 * 1024 )) ;;
|
||||
*[pP]) sz=$(( 1024 * 1024 * 1024 * 1024 )) ;;
|
||||
esac
|
||||
|
||||
echo $(( sz * ${1%[kKmMgGtTpP]} ))
|
||||
}
|
||||
|
||||
#
|
||||
# Emulate functionality of deprecated 'vdo create'
|
||||
#
|
||||
vdo_create_() {
|
||||
local cachesize=
|
||||
local devsize=
|
||||
local emulate512=disabled
|
||||
local logicalsize=
|
||||
local maxdiscardsize=
|
||||
local slabbits=0 # 4k
|
||||
local slabsize=
|
||||
local sparse=
|
||||
local table=
|
||||
local vdo_compression_msg=
|
||||
local vdo_dry=
|
||||
local vdo_index_msg=
|
||||
local vdo_logicalBlockSize=
|
||||
local vdo_verbose=
|
||||
|
||||
local vdo_ackThreads=${vdo_ackThreads-1}
|
||||
local vdo_bioRotationInterval=${vdo_bioRotationInterval-64}
|
||||
local vdo_bioThreads=${vdo_bioThreads-4}
|
||||
local vdo_blockMapCacheSize=${vdo_blockMapCacheSize-128M}
|
||||
local vdo_blockMapPeriod=${vdo_blockMapPeriod-16380}
|
||||
local vdo_compression=${vdo_compression-enabled}
|
||||
local vdo_confFile=$LVM_VDO_DEFAULT_CONF # place some file in /tmp
|
||||
local vdo_cpuThreads=${vdo_cpuThreads-2}
|
||||
local vdo_deduplication=${vdo_deduplication-enabled}
|
||||
local vdo_hashZoneThreads=${vdo_hashZoneThreads-1}
|
||||
local vdo_indexCfreq=${vdo_indexCfreq-0}
|
||||
local vdo_indexMemory=${vdo_indexMemory-0.25}
|
||||
local vdo_indexSparse=${vdo_indexSparse-disabled}
|
||||
local vdo_indexThreads=${vdo_indexThreads-0}
|
||||
local vdo_logicalSize=${vdo_logicalSize-0}
|
||||
local vdo_logicalThreads=${vdo_logicalThreads-1}
|
||||
local vdo_maxDiscardSize=${vdo_maxDiscardSize-4K}
|
||||
local vdo_name=${vdo_name-VDONAME}
|
||||
local vdo_physicalThreads=${vdo_physicalThreads-1}
|
||||
local vdo_slabSize=${vdo_slabSize-2G}
|
||||
local vdo_uuid="VDO-$(uuidgen || echo \"f7a3ecdc-40a0-4e43-814c-4a7039a75de4\")"
|
||||
local vdo_writePolicy=${vdo_writePolicy-auto}
|
||||
|
||||
while [ "$#" -ne 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
"--blockMapCacheSize") shift; vdo_blockMapCacheSize=$1 ;;
|
||||
"--blockMapPeriod") shift; vdo_blockMapPeriod=$1 ;;
|
||||
"--compression") shift; vdo_compression=$1 ;;
|
||||
"--confFile"|"-f") shift; vdo_confFile=$1 ;;
|
||||
"--deduplication") shift; vdo_deduplication=$1 ;;
|
||||
"--device") shift; vdo_device=$1 ;;
|
||||
"--emulate512") shift; emulate512=$1 ;;
|
||||
"--indexMem") shift; vdo_indexMemory=$1 ;;
|
||||
"--maxDiscardSize") shift; vdo_maxDiscardSize=$1 ;;
|
||||
"--name"|"-n") shift; vdo_name=$1 ;;
|
||||
"--sparseIndex") shift; vdo_indexSparse=$1 ;;
|
||||
"--uuid") shift ;; # ignored
|
||||
"--vdoAckThreads") shift; vdo_ackThreads=$1 ;;
|
||||
"--vdoBioRotationInterval") shift; vdo_bioRotationInterval=$1 ;;
|
||||
"--vdoBioThreads") shift; vdo_bioThreads=$1 ;;
|
||||
"--vdoCpuThreads") shift; vdo_cpuThreads=$1 ;;
|
||||
"--vdoHashZoneThreads") shift; vdo_hashZoneThreads=$1 ;;
|
||||
"--vdoLogicalSize") shift; vdo_logicalSize=$1 ;;
|
||||
"--vdoLogicalThreads") shift; vdo_logicalThreads=$1 ;;
|
||||
"--vdoLogLevel") shift ;; # ignored
|
||||
"--vdoPhysicalThreads") shift; vdo_physicalSize=$1 ;;
|
||||
"--vdoSlabSize") shift; vdo_slabSize=$1 ;;
|
||||
"--verbose"|"-d"|"--debug") vdo_verbose="-v" ;;
|
||||
"--writePolicy") shift; vdo_writePolicy=$1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Convert when set
|
||||
case "$emulate512" in
|
||||
"enabled") vdo_logicalBlockSize=512 ;;
|
||||
"disabled") vdo_logicalBlockSize=4096 ;;
|
||||
*) vdo_die_ "Invalid emulate512 setting."
|
||||
esac
|
||||
|
||||
case "$vdo_deduplication" in
|
||||
"enabled") vdo_index_msg="index-enable" ;;
|
||||
"disabled") vdo_index_msg="index-disable";;
|
||||
*) vdo_die_ "Invalid deduplication setting."
|
||||
esac
|
||||
|
||||
case "$vdo_compression" in
|
||||
"enabled") vdo_compression_msg="compression on" ;;
|
||||
"disabled") vdo_compression_msg="compression off";;
|
||||
*) vdo_die_ "Invalid compression setting."
|
||||
esac
|
||||
|
||||
test -n "${vdo_device-}" || vdo_die_ "VDO device is missing"
|
||||
|
||||
blkid -s UUID -o value "${vdo_device}" || true
|
||||
|
||||
devsize=$(blockdev --getsize64 "$vdo_device")
|
||||
devsize=$(( devsize / 4096 )) # convert to 4KiB units
|
||||
|
||||
logicalsize=$(vdo_get_kb_size_with_unit_ "$vdo_logicalSize" M)
|
||||
logicalsize=$(( logicalsize * 2 )) # 512B units
|
||||
|
||||
cachesize=$(vdo_get_kb_size_with_unit_ "$vdo_blockMapCacheSize" M)
|
||||
cachesize=$(( cachesize / 4 )) # 4KiB units
|
||||
|
||||
maxdiscardsize=$(vdo_get_kb_size_with_unit_ "$vdo_maxDiscardSize" M)
|
||||
maxdiscardsize=$(( maxdiscardsize / 4 )) # 4KiB units
|
||||
|
||||
test -e "$vdo_confFile" || {
|
||||
cat > "$vdo_confFile" <<EOF
|
||||
####################################################################
|
||||
# THIS FILE IS MACHINE GENERATED. DO NOT EDIT THIS FILE BY HAND.
|
||||
####################################################################
|
||||
config: !Configuration
|
||||
vdos:
|
||||
EOF
|
||||
}
|
||||
|
||||
cat >> "$vdo_confFile" <<EOF
|
||||
$vdo_name: !VDOService
|
||||
_operationState: finished
|
||||
ackThreads: $vdo_ackThreads
|
||||
activated: enabled
|
||||
bioRotationInterval: $vdo_bioRotationInterval
|
||||
bioThreads: $vdo_bioThreads
|
||||
blockMapCacheSize: $(( cachesize * 4 ))K
|
||||
blockMapPeriod: $vdo_blockMapPeriod
|
||||
compression: $vdo_compression
|
||||
cpuThreads: $vdo_cpuThreads
|
||||
deduplication: $vdo_deduplication
|
||||
device: $vdo_device
|
||||
hashZoneThreads: $vdo_hashZoneThreads
|
||||
indexCfreq: $vdo_indexCfreq
|
||||
indexMemory: $vdo_indexMemory
|
||||
indexSparse: $vdo_indexSparse
|
||||
indexThreads: $vdo_indexThreads
|
||||
logicalBlockSize: $vdo_logicalBlockSize
|
||||
logicalSize: $(( logicalsize / 2 ))K
|
||||
logicalThreads: $vdo_logicalThreads
|
||||
maxDiscardSize: $(( maxdiscardsize * 4 ))K
|
||||
name: $vdo_name
|
||||
physicalSize: $(( devsize * 4 ))K
|
||||
physicalThreads: $vdo_physicalThreads
|
||||
slabSize: $vdo_slabSize
|
||||
uuid: $vdo_uuid
|
||||
writePolicy: $vdo_writePolicy
|
||||
version: 538380551
|
||||
EOF
|
||||
|
||||
slabsize=$(vdo_get_kb_size_with_unit_ "$vdo_slabSize")
|
||||
while test "$slabsize" -gt 4 ; do
|
||||
slabbits=$(( slabbits + 1 ))
|
||||
slabsize=$(( slabsize / 2 ))
|
||||
done
|
||||
|
||||
case "$vdo_indexSparse" in
|
||||
"enabled") sparse="--uds-sparse" ;;
|
||||
esac
|
||||
|
||||
vdo_dry_ "$LVM_VDO_FORMAT" $vdo_verbose $sparse\
|
||||
--logical-size "$vdo_logicalSize" --slab-bits "$slabbits"\
|
||||
--uds-checkpoint-frequency "$vdo_indexCfreq"\
|
||||
--uds-memory-size "$vdo_indexMemory" "$vdo_device"
|
||||
|
||||
# V2 format
|
||||
table="0 $logicalsize vdo V2 $vdo_device\
|
||||
$devsize\
|
||||
$vdo_logicalBlockSize\
|
||||
$cachesize\
|
||||
$vdo_blockMapPeriod\
|
||||
on\
|
||||
$vdo_writePolicy\
|
||||
$vdo_name\
|
||||
maxDiscard $maxdiscardsize\
|
||||
ack $vdo_ackThreads\
|
||||
bio $vdo_bioThreads\
|
||||
bioRotationInterval $vdo_bioRotationInterval\
|
||||
cpu $vdo_cpuThreads\
|
||||
hash $vdo_hashZoneThreads\
|
||||
logical $vdo_logicalThreads\
|
||||
physical $vdo_physicalThreads"
|
||||
|
||||
vdo_dry_ dmsetup create "$vdo_name" --uuid "$vdo_uuid" --table "$table"
|
||||
vdo_dry_ dmsetup message "$vdo_name" 0 "$vdo_index_msg"
|
||||
vdo_dry_ dmsetup message "$vdo_name" 0 "$vdo_compression_msg"
|
||||
}
|
||||
|
||||
#
|
||||
# vdo stop
|
||||
#
|
||||
vdo_stop_() {
|
||||
local vdo_confFile=$LVM_VDO_DEFAULT_CONF
|
||||
local vdo_dry=
|
||||
local vdo_force=
|
||||
local vdo_name=
|
||||
local vdo_verbose=
|
||||
|
||||
while [ "$#" -ne 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
"--confFile"|"-f") shift; vdo_confFile=$1 ;;
|
||||
"--name"|"-n") shift; vdo_name=$1 ;;
|
||||
"--verbose"|"-d"|"--debug") vdo_verbose="-v" ;;
|
||||
"--force") vdo_force="--force" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
vdo_dry_ dmsetup status --target vdo "$vdo_name" 2>/dev/null || return 0
|
||||
vdo_dry_ dmsetup remove $vdo_force "$vdo_name" || true
|
||||
}
|
||||
|
||||
#
|
||||
# vdo remove
|
||||
#
|
||||
vdo_remove_() {
|
||||
local vdo_confFile=$LVM_VDO_DEFAULT_CONF
|
||||
local vdo_name=
|
||||
|
||||
vdo_stop_ "$@"
|
||||
while [ "$#" -ne 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
"--confFile"|"-f") shift; vdo_confFile=$1 ;;
|
||||
"--name"|"-n") shift; vdo_name=$1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# remove entry from conf file
|
||||
awk -v vdovolname="$vdo_name" 'BEGIN { have=0 }
|
||||
$0 ~ "!VDOService" { have=0 }
|
||||
$0 ~ vdovolname":" { have=1 }
|
||||
{ if (have==0) { print } ;}
|
||||
' "$vdo_confFile" >"${vdo_confFile}.new"
|
||||
|
||||
mv "${vdo_confFile}.new" "$vdo_confFile"
|
||||
grep "!VDOService" "$vdo_confFile" || rm -f "$vdo_confFile"
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# print_config_file
|
||||
#
|
||||
vdo_print_config_file_() {
|
||||
local vdo_confFile=$LVM_VDO_DEFAULT_CONF
|
||||
|
||||
while [ "$#" -ne 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
"--confFile"|"-f") shift; vdo_confFile=$1 ;;
|
||||
"--verbose"|"-d"|"--debug") ;;
|
||||
"--logfile") shift ;; # ignore
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
cat "$vdo_confFile"
|
||||
}
|
||||
|
||||
#
|
||||
# vdo convert
|
||||
#
|
||||
vdo_convert_() {
|
||||
local vdo_confFile=$LVM_VDO_DEFAULT_CONF
|
||||
local vdo_dry=
|
||||
local vdo_force=
|
||||
local vdo_name=
|
||||
local vdo_verbose=
|
||||
local vdo_device=
|
||||
|
||||
while [ "$#" -ne 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
"--confFile"|"-f") shift; vdo_confFile=$1 ;;
|
||||
"--name"|"-n") shift; vdo_name=$1 ;;
|
||||
"--verbose"|"-d"|"--debug") vdo_verbose="-v" ;;
|
||||
"--force") vdo_force="--force" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
vdo_device=$(awk -v vdovolname="$vdo_name" 'BEGIN { have=0 }
|
||||
$0 ~ "!VDOService" { have=0 }
|
||||
$0 ~ vdovolname":" { have=1 }
|
||||
{ if (have==1 && $0 ~ "device:" ) { print $2 } ;}'\
|
||||
"$vdo_confFile")
|
||||
|
||||
#dmsetup status --target vdo "$vdo_name" || true
|
||||
vdo_dry_ "$LVM_VDO_PREPARE" "$vdo_device"
|
||||
vdo_dry_ vdo_remove_ -f "$vdo_confFile" -n "$vdo_name" || true
|
||||
}
|
||||
|
||||
#
|
||||
# MAIN
|
||||
#
|
||||
case "$1" in
|
||||
"create") shift; vdo_create_ "$@" ;;
|
||||
"remove") shift; vdo_remove_ "$@" ;;
|
||||
"stop") shift; vdo_stop_ "$@" ;;
|
||||
"convert") shift; vdo_convert_ "$@" ;;
|
||||
"printConfigFile") shift; vdo_print_config_file_ "$@" ;;
|
||||
esac
|
||||
@@ -29,6 +29,12 @@
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
|
||||
if (getuid() != 0) {
|
||||
std::cout << "Skipping tests, root is required, current UID: " << getuid() << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
return brick::shelltest::run( argc, argv, "LVM_TEST_FLAVOUR" );
|
||||
} catch (std::exception const& e) {
|
||||
|
||||
@@ -104,6 +104,10 @@ not ls "$DFDIR/system.devices"
|
||||
vgs --devicesfile test.devices $vg1
|
||||
not vgs --devicesfile test.devices $vg2
|
||||
|
||||
# misspelled override name fails
|
||||
not vgs --devicesfile doesnotexist $vg1
|
||||
not vgs --devicesfile doesnotexist $vg2
|
||||
|
||||
# devicesfile and devices cannot be used together
|
||||
not vgs --devicesfile test.devices --devices "$dev1","$dev1" $vg1
|
||||
|
||||
|
||||
@@ -135,6 +135,24 @@ lvmdevices --deldev "$LOOP1"
|
||||
not grep "$LOOP1" $DF
|
||||
lvmdevices --deldev "$LOOP2"
|
||||
not grep "$LOOP2" $DF
|
||||
rm $DF
|
||||
|
||||
# deldev using idname
|
||||
lvmdevices --adddev "$LOOP1"
|
||||
lvmdevices --adddev "$LOOP2"
|
||||
vgcreate $vg "$LOOP1" "$LOOP2"
|
||||
IDNAME1=`pvs "$LOOP1" --noheading -o deviceid | awk '{print $1}'`
|
||||
IDNAME2=`pvs "$LOOP2" --noheading -o deviceid | awk '{print $1}'`
|
||||
lvmdevices --deldev "$IDNAME2" --deviceidtype loop_file
|
||||
not grep "$IDNAME2" $DF
|
||||
not grep "$LOOP2" $DF
|
||||
lvmdevices --deldev "$IDNAME1" --deviceidtype loop_file
|
||||
not grep "$IDNAME1" $DF
|
||||
not grep "$LOOP1" $DF
|
||||
lvmdevices --adddev "$LOOP1"
|
||||
lvmdevices --adddev "$LOOP2"
|
||||
vgremove $vg
|
||||
rm $DF
|
||||
|
||||
# add/delpvid with default idtype loop_file
|
||||
lvmdevices --addpvid "$PVID1"
|
||||
@@ -151,6 +169,7 @@ not grep "$PVID1" $DF
|
||||
lvmdevices --delpvid "$PVID2"
|
||||
not grep "$LOOP2" $DF
|
||||
not grep "$PVID2" $DF
|
||||
rm $DF
|
||||
|
||||
# add/deldev with non-default idtype devname
|
||||
lvmdevices --adddev "$LOOP1" --deviceidtype devname
|
||||
@@ -165,6 +184,7 @@ lvmdevices --deldev "$LOOP1"
|
||||
not grep "$LOOP1" $DF
|
||||
lvmdevices --deldev "$LOOP2"
|
||||
not grep "$LOOP2" $DF
|
||||
rm $DF
|
||||
|
||||
# add/delpvid with non-default idtype devname
|
||||
lvmdevices --addpvid "$PVID1" --deviceidtype devname
|
||||
@@ -179,6 +199,7 @@ lvmdevices --deldev "$LOOP1"
|
||||
not grep "$LOOP1" $DF
|
||||
lvmdevices --deldev "$LOOP2"
|
||||
not grep "$LOOP2" $DF
|
||||
rm $DF
|
||||
|
||||
# add/deldev when dev is missing, using default idtype
|
||||
lvmdevices --adddev "$LOOP1"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user