1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-30 17:44:21 +03:00

Compare commits

..

3 Commits

Author SHA1 Message Date
Marian Csontos
09fc3a985d spec: Use libedit for newer distributions 2022-07-27 18:03:34 +02:00
Marian Csontos
c30881fd95 test: Print running test to console and syslog 2022-06-09 14:37:48 +02:00
Marian Csontos
64ba9e4eca test: Add __FILE__ and __LINE__ to T_ASSERT macro 2022-06-08 18:02:08 +02:00
52 changed files with 1051 additions and 3094 deletions

View File

@@ -1,6 +1,5 @@
Version 2.03.17 -
===============================
Fix vdo_slab_size_mb value for converted VDO volume.
Version 2.03.16 - 18th May 2022
===============================

View File

@@ -1713,21 +1713,6 @@ 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
@@ -1897,11 +1882,6 @@ 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)

View File

@@ -220,6 +220,38 @@ 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()):
@@ -605,6 +637,46 @@ 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']
@@ -759,6 +831,53 @@ 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__':
# Leave this for future debug as needed
pass
pv_data = pv_retrieve_with_segs()
for p in pv_data:
print(str(p))

View File

@@ -226,21 +226,3 @@ 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)

View File

@@ -19,6 +19,7 @@ import sys
import tempfile
import time
import select
import copy
try:
import simplejson as json
@@ -30,6 +31,8 @@ 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:
@@ -40,11 +43,10 @@ def _quote_arg(arg):
class LVMShellProxy(object):
# 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):
# 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):
stdout = ""
report = ""
stderr = ""
@@ -56,7 +58,6 @@ 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 = [
@@ -74,36 +75,35 @@ 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() is not None:
if self.lvm_shell.poll():
raise Exception(self.lvm_shell.returncode, "%s" % stderr)
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 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
# 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!")
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!")
except IOError as ioe:
log_debug(str(ioe))
@@ -118,48 +118,49 @@ 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)
# Create a fifo for the report output
os.mkfifo(tmp_file, 0o600)
try:
# Lets create fifo for the report output
os.mkfifo(tmp_file, 0o600)
except FileExistsError:
pass
# Open the fifo for use to read and for lvm child process to write to.
# We have to open non-blocking as the other side isn't open until
# we actually fork the process.
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)
# 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"}
# 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"
# 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
# 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"
# run the lvm shell
self.lvm_shell = subprocess.Popen(
[LVM_CMD],
[LVM_CMD + " 32>%s" % tmp_file],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=local_env,
stderr=subprocess.PIPE, close_fds=True, pass_fds=(lvm_fd,), shell=False)
stderr=subprocess.PIPE, close_fds=True, shell=True)
try:
make_non_block(self.lvm_shell.stdout)
make_non_block(self.lvm_shell.stderr)
# 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.
# wait for the first prompt
errors = self._read_until_prompt(no_output=True)[2]
if errors and len(errors):
raise RuntimeError(errors)
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)
@@ -169,7 +170,7 @@ class LVMShellProxy(object):
self._write_cmd('lastlog\n')
# read everything from the STDOUT to the next prompt
stdout, report_json, stderr = self._read_response()
stdout, report_json, stderr = self._read_until_prompt()
if 'log' in report_json:
error_msg = ""
# Walk the entire log array and build an error string
@@ -203,7 +204,7 @@ class LVMShellProxy(object):
self._write_cmd(cmd)
# read everything from the STDOUT to the next prompt
stdout, report_json, stderr = self._read_response()
stdout, report_json, stderr = self._read_until_prompt()
# Parse the report to see what happened
if 'log' in report_json:
@@ -236,34 +237,24 @@ class LVMShellProxy(object):
if __name__ == "__main__":
print("USING LVM BINARY: %s " % LVM_CMD)
shell = LVMShellProxy()
in_line = "start"
try:
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()
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)

View File

@@ -13,13 +13,14 @@ 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, vdo_support=False):
def __init__(self, usejson=True, vdo_support=False):
self.pvs = {}
self.vgs = {}
self.lvs = {}
@@ -34,9 +35,41 @@ 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():
@@ -51,6 +84,22 @@ 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):
@@ -92,6 +141,28 @@ 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):
@@ -156,6 +227,22 @@ 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()
@@ -314,12 +401,22 @@ class DataStore(object):
log_debug("lvmdb - refresh entry")
# Grab everything first then parse it
# Do a single lvm retrieve for everything in json
a = cmdhandler.lvm_full_report_json()
if self.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)
_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)
# Set all
self.pvs = _pvs
@@ -430,7 +527,13 @@ class DataStore(object):
if __name__ == "__main__":
pp = prettyprint.PrettyPrinter(indent=4)
ds = DataStore()
use_json = False
if len(sys.argv) != 1:
print(len(sys.argv))
use_json = True
ds = DataStore(use_json)
ds.refresh()
print("PVS")

View File

@@ -29,7 +29,7 @@ from .utils import log_debug, log_error
import argparse
import os
import sys
from .cmdhandler import LvmFlightRecorder, supports_vdo, supports_json
from .cmdhandler import LvmFlightRecorder, supports_vdo
from .request import RequestEntry
@@ -116,15 +116,6 @@ 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
@@ -136,8 +127,6 @@ 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()
@@ -166,7 +155,7 @@ def main():
cfg.om = Lvm(BASE_OBJ_PATH)
cfg.om.register_object(Manager(MANAGER_OBJ_PATH))
cfg.db = lvmdb.DataStore(vdo_support=cfg.vdo_support)
cfg.db = lvmdb.DataStore(cfg.args.use_json, cfg.vdo_support)
# Using a thread to process requests, we cannot hang the dbus library
# thread that is handling the dbus interface

View File

@@ -132,13 +132,8 @@
/* Define to 1 to include the LVM editline shell. */
#undef EDITLINE_SUPPORT
/* Paths to binaries. */
/* Path to fsadm binary. */
#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

View File

@@ -40,9 +40,7 @@ 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 \

View File

@@ -1,19 +0,0 @@
#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

View File

@@ -1905,6 +1905,7 @@ 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);
@@ -2033,6 +2034,7 @@ 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);

View File

@@ -18,7 +18,6 @@
#include "lib/device/dev-cache.h"
#include "lib/device/dev-type.h"
#include "lib/commands/cmd_enum.h"
#include <limits.h>
@@ -95,7 +94,6 @@ 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;

View File

@@ -80,7 +80,6 @@ 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)
@@ -384,22 +383,6 @@ 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;
@@ -1353,7 +1336,6 @@ 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);
}
}
@@ -1881,15 +1863,6 @@ 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.

View File

@@ -74,7 +74,6 @@ 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);

View File

@@ -54,7 +54,7 @@ static void _read_blacklist_file(const char *path)
int section_black = 0;
int section_exceptions = 0;
int found_quote;
int found_type;
int found_three;
int i, j;
if (!(fp = fopen(path, "r")))
@@ -114,7 +114,7 @@ static void _read_blacklist_file(const char *path)
memset(wwid, 0, sizeof(wwid));
found_quote = 0;
found_type = 0;
found_three = 0;
j = 0;
for (; i < MAX_WWID_LINE; i++) {
@@ -132,10 +132,9 @@ static void _read_blacklist_file(const char *path)
/* 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;
/* ignore first "3" in wwid */
if ((line[i] == '3') && !found_three) {
found_three = 1;
continue;
}
@@ -200,12 +199,11 @@ static void _read_wwid_exclusions(void)
log_debug("multipath config ignored %d wwids", rem_count);
}
static void _read_wwid_file(const char *config_wwids_file, int *entries)
static void _read_wwid_file(const char *config_wwids_file)
{
FILE *fp;
char line[MAX_WWID_LINE];
char *wwid, *p;
char typestr[2] = { 0 };
int count = 0;
if (config_wwids_file[0] != '/') {
@@ -227,17 +225,8 @@ static void _read_wwid_file(const char *config_wwids_file, int *entries)
if (line[0] == '/')
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++;
/* skip the initial '3' */
wwid++;
if ((p = strchr(wwid, '/')))
*p = '\0';
@@ -250,7 +239,6 @@ static void _read_wwid_file(const char *config_wwids_file, int *entries)
stack;
log_debug("multipath wwids read %d from %s", count, config_wwids_file);
*entries = count;
}
int dev_mpath_init(const char *config_wwids_file)
@@ -258,7 +246,6 @@ 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);
@@ -295,16 +282,10 @@ int dev_mpath_init(const char *config_wwids_file)
_wwid_hash_tab = wwid_tab;
if (config_wwids_file) {
_read_wwid_file(config_wwids_file, &entries);
_read_wwid_file(config_wwids_file);
_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;
}
@@ -452,10 +433,10 @@ static int _dev_is_mpath_component_udev(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)
static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device *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/" */
@@ -469,15 +450,25 @@ 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;
switch (primary_result) {
/* multipathing is only known to exist for SCSI or NVME devices */
if (!major_is_scsi_device(dt, dev_major) && !dev_is_nvme(dt, dev))
return 0;
switch (dev_get_primary_dev(dt, dev, &primary_dev)) {
case 2: /* The dev is partition. */
part_name = dev_name(dev); /* name of original dev for log_debug msg */
/* gets "foo" for "/dev/foo" where "/dev/foo" comes from major:minor */
if (!(name = _get_sysfs_name_by_devt(sysfs_dir, primary_dev, link_path, sizeof(link_path))))
return_0;
log_debug_devs("%s: Device is a partition, using primary "
"device %s for mpath component detection",
part_name, name);
break;
case 1: /* The dev is already a primary dev. Just continue with the dev. */
@@ -601,189 +592,47 @@ static int _dev_is_mpath_component_sysfs(struct cmd_context *cmd, struct device
return is_mpath_component;
}
static int _read_sys_wwid(struct cmd_context *cmd, struct device *dev,
char *idbuf, int idbufsize)
static int _dev_in_wwid_file(struct cmd_context *cmd, struct device *dev)
{
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 sysbuf[PATH_MAX] = { 0 };
char *wwid;
long look;
if (!_wwid_hash_tab)
return 0;
if (!read_sys_block(cmd, dev, "device/wwid", sysbuf, sizeof(sysbuf)))
return 0;
if (!sysbuf[0])
return 0;
/*
* Check the primary device, not the partition.
* sysfs prints wwid as <typestr>.<value>
* multipath wwid uses '3'<value>
* does "<typestr>." always correspond to "3"?
*/
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;
}
if (!(wwid = strchr(sysbuf, '.')))
return 0;
/* skip the type and dot, just as '3' was skipped from wwids entry */
wwid++;
look = (long) dm_hash_lookup_binary(_wwid_hash_tab, wwid, strlen(wwid));
if (look) {
log_debug_devs("dev_is_mpath_component %s multipath wwid %s", dev_name(dev), wwid);
return 1;
}
/*
* This function may be called multiple times for the same device, in
* particular if partitioned for each partition.
*/
if (!dm_list_empty(&dev->wwids))
goto lookup;
/*
* 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;
/*
* 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, dev_t *holder_devno)
{
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)
if (_dev_is_mpath_component_sysfs(cmd, dev, holder_devno) == 1)
goto found;
if (_dev_in_wwid_file(cmd, dev, primary_result, primary_dev))
if (_dev_in_wwid_file(cmd, dev))
goto found;
if (external_device_info_source() == DEV_EXT_UDEV) {
@@ -791,12 +640,6 @@ int dev_is_mpath_component(struct cmd_context *cmd, struct device *dev, dev_t *h
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;

View File

@@ -838,86 +838,6 @@ 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)
{
@@ -925,11 +845,6 @@ 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

View File

@@ -18,7 +18,6 @@
#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
@@ -103,7 +102,6 @@ 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);

View File

@@ -59,14 +59,6 @@ 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
@@ -113,7 +105,6 @@ 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;
@@ -215,9 +206,5 @@ 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

View File

@@ -182,9 +182,7 @@ void free_dids(struct dm_list *ids)
}
}
static int _read_sys_block(struct cmd_context *cmd, struct device *dev,
const char *suffix, char *sysbuf, int sysbufsize,
int binary, int *retlen)
int read_sys_block(struct cmd_context *cmd, struct device *dev, const char *suffix, char *sysbuf, int sysbufsize)
{
char path[PATH_MAX];
dev_t devt = dev->dev;
@@ -198,17 +196,11 @@ static int _read_sys_block(struct cmd_context *cmd, struct device *dev,
return 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;
}
get_sysfs_value(path, sysbuf, sysbufsize, 0);
if (ret) {
if (sysbuf[0]) {
if (prim)
log_debug("Using primary device_id for partition %s.", dev_name(dev));
sysbuf[sysbufsize - 1] = '\0';
return 1;
}
@@ -228,19 +220,6 @@ static int _read_sys_block(struct cmd_context *cmd, struct device *dev,
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)))

View File

@@ -58,8 +58,6 @@ 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);

View File

@@ -1,284 +0,0 @@
/*
* 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;
}

View File

@@ -1,46 +0,0 @@
/*
* 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

View File

@@ -1,199 +0,0 @@
/*
* 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;
}

View File

@@ -577,9 +577,8 @@ 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(cmd, lv, &lp)) {
if (!lv_resize(lv, &lp, &vg->pvs)) {
log_error("Extend sanlock LV %s to size %s failed.",
display_lvname(lv), display_size(cmd, lp.size));
return 0;
@@ -2734,9 +2733,6 @@ 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

View File

@@ -297,9 +297,6 @@
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,
@@ -664,44 +661,50 @@ 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 use_policies;
char fsopt[32]; /* set by --resizefs|--fs, empty for --fs ignore */
int resizefs;
const struct segment_type *segtype;
unsigned mirrors;
uint32_t stripes;
uint64_t stripe_size;
uint64_t size;
uint32_t extents;
uint64_t size;
sign_t sign;
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;
percent_type_t percent;
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);
@@ -742,10 +745,9 @@ 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 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);
int lv_resize(struct logical_volume *lv,
struct lvresize_params *lp,
struct dm_list *pvh);
struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const char *vgid,
uint32_t read_flags, uint32_t lockd_state,

View File

@@ -4533,7 +4533,7 @@ void vg_write_commit_bad_mdas(struct cmd_context *cmd, struct volume_group *vg)
* reread metadata.
*/
bool scan_text_mismatch(struct cmd_context *cmd, const char *vgname, const char *vgid)
static 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,15 +5302,3 @@ 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);
}

View File

@@ -538,7 +538,5 @@ 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

View File

@@ -737,7 +737,6 @@ 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;
@@ -747,8 +746,6 @@ 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,

View File

@@ -125,6 +125,15 @@ 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
@@ -319,12 +328,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_kb_size_with_unit_ "$vdo_blockMapCacheSize") / 1024 ))
vdo_block_map_cache_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
vdo_block_map_period = $vdo_blockMapPeriod
vdo_check_point_frequency = $vdo_indexCfreq
vdo_use_sparse_index = $(get_enabled_value_ "$vdo_indexSparse")
vdo_index_memory_size_mb = $(awk "BEGIN {print $vdo_indexMemory * 1024}")
vdo_slab_size_mb = $(( $(get_kb_size_with_unit_ "$vdo_blockMapCacheSize") / 1024 ))
vdo_slab_size_mb = $(get_mb_size_with_unit_ "$vdo_blockMapCacheSize")
vdo_ack_threads = $vdo_ackThreads
vdo_bio_threads = $vdo_bioThreads
vdo_bio_rotation = $vdo_bioRotationInterval
@@ -408,7 +417,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 $VERB --force --name "$VDONAME"
dry "$VDO" remove $VDOCONF --force --verbose --name "$VDONAME"
fi
rm -fr "$TEMPDIR"

View File

@@ -28,6 +28,8 @@
%enableif %{enable_dbusd} dbus-service
%enableif %{enable_dbusd} notify-dbus
%enableif %{enable_dmfilemapd} dmfilemapd
%enableif %{enable_readline} readline
%enableif %{enable_editline} editline
%build

View File

@@ -47,6 +47,14 @@
%global req_udev udev >= 181-1
%if %{fedora} >= 35 || %{rhel} >= 9
%global enable_readline 0
%global enable_editline 1
%else
%global enable_readline 1
%global enable_editline 0
%endif
%if %{fedora} >= 24 || %{rhel} >= 7
%service lvmlockd 1
%global sanlock_version 3.3.0-1
@@ -154,7 +162,12 @@ Source94: macros.inc
BuildRequires: libselinux-devel >= 1.30.19-4, libsepol-devel
BuildRequires: ncurses-devel
%if %{enable_readline}
BuildRequires: readline-devel
%endif
%if %{enable_editline}
BuildRequires: libedit-devel
%endif
BuildRequires: module-init-tools
BuildRequires: pkgconfig

View File

@@ -369,7 +369,6 @@ 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/"; \

View File

@@ -23,9 +23,6 @@ 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', '')
@@ -40,10 +37,9 @@ pv_device_list = os.getenv('LVM_DBUSD_PV_DEVICE_LIST', None)
# Default is to test all modes
# 0 == Only test fork & exec mode
# 1 == Only test lvm shell mode
# 2 == Test both fork & exec & lvm shell mode (default)
# 1 == Test both fork & exec & lvm shell mode (default)
# Other == Test just lvm shell mode
test_shell = os.getenv('LVM_DBUSD_TEST_MODE', 2)
test_shell = os.getenv('LVM_DBUSD_TEST_MODE', 1)
# LVM binary to use
LVM_EXECUTABLE = os.getenv('LVM_BINARY', '/usr/sbin/lvm')
@@ -153,7 +149,7 @@ def get_objects():
rc[interface].append(proxy)
# At this point we have a full population of everything, we now need to
# prune the objects if we are filtering PVs with a sub selection.
# prune the the objects if we are filtering PVs with a sub selection.
return _prune(rc, pv_device_list), bus
@@ -677,20 +673,6 @@ 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
@@ -900,19 +882,8 @@ 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)
@@ -1125,7 +1096,7 @@ class TestDbusService(unittest.TestCase):
def _test_expired_timer(self, num_lvs):
rc = False
# In small configurations lvm is pretty snappy, so let's create a VG
# In small configurations lvm is pretty snappy, so lets 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.
@@ -1184,7 +1155,7 @@ class TestDbusService(unittest.TestCase):
return
# This may not pass
for i in [128, 256]:
for i in [48, 64, 128]:
yes = self._test_expired_timer(i)
if yes:
break
@@ -1795,7 +1766,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 lvm
# We need to ensure that if a user creates something outside of 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()
@@ -1808,8 +1779,8 @@ class TestDbusService(unittest.TestCase):
self._verify_existence(cmd, cmd[0], vg_name)
def test_external_lv_create(self):
# Let's create a LV outside of service and see if we correctly handle
# its inclusion
# Lets create a LV outside of service and see if we correctly handle
# it's inclusion
vg = self._vg_create().Vg
lv_name = lv_n()
full_name = "%s/%s" % (vg.Name, lv_name)
@@ -1818,8 +1789,8 @@ class TestDbusService(unittest.TestCase):
self._verify_existence(cmd, cmd[0], full_name)
def test_external_pv_create(self):
# Let's create a PV outside of service and see if we correctly handle
# its inclusion
# Lets create a PV outside of service and see if we correctly handle
# it's inclusion
target = self.objs[PV_INT][0]
# Remove the PV
@@ -1865,7 +1836,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.
@@ -1880,7 +1851,7 @@ class TestDbusService(unittest.TestCase):
pv_object_path = self._create_nested(pv_object_path)
def test_pv_symlinks(self):
# Let's take one of our test PVs, pvremove it, find a symlink to it
# Lets 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
@@ -1902,7 +1873,7 @@ class TestDbusService(unittest.TestCase):
rc = self._lookup(pv_device_path)
self.assertEqual(rc, '/')
# Let's locate a symlink for it
# Lets locate a symlink for it
devices = glob('/dev/disk/*/*')
rp_pv_device_path = os.path.realpath(pv_device_path)
for d in devices:
@@ -1936,8 +1907,8 @@ class TestDbusService(unittest.TestCase):
vdo_pool_object_path = self.handle_return(
vg_proxy.VgVdo.CreateVdoPoolandLv(
pool_name, lv_name,
dbus.UInt64(VDO_MIN_SIZE),
dbus.UInt64(VDO_MIN_SIZE * 2),
dbus.UInt64(mib(4096)), # Appears to be minimum size
dbus.UInt64(mib(8192)),
dbus.Int32(g_tmo),
EOD))
@@ -1967,7 +1938,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 it finds an existing vdo signature, which likely
# the operation when if finds an existing vdo signature, which likely
# shouldn't exist.
for _ in range(0, 2):
vg, _, _ = self._create_vdo_pool_and_lv()
@@ -1979,7 +1950,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(VDO_MIN_SIZE),
(dbus.String(pool_name), dbus.UInt64(mib(4096)),
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))
@@ -1988,7 +1959,7 @@ class TestDbusService(unittest.TestCase):
vdo_pool_path = self.handle_return(
vg_proxy.VgVdo.CreateVdoPool(
dbus.ObjectPath(lv.object_path), lv_name,
dbus.UInt64(VDO_MIN_SIZE),
dbus.UInt64(mib(8192)),
dbus.Int32(g_tmo),
EOD))
@@ -2107,19 +2078,15 @@ 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("Unsupported \"LVM_DBUSD_TEST_MODE\"=%d, [0-2] valid" % mode)
sys.exit(1)
std_err_print('\n*** Testing only lvm shell mode ***\n')
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 == 1:
elif mode == 2:
if set_execution(True, r):
r.register_result(unittest.main(exit=False))
else:

View File

@@ -183,7 +183,6 @@ class RemoteInterface(object):
verify_type(
vl, self.introspect[self.interface]
['properties'][kl]['p_type'])
self.p_name[kl] = True
setattr(self, kl, vl)
@property
@@ -197,7 +196,6 @@ class RemoteInterface(object):
self.interface = interface
self.introspect = introspect
self.tmo = 0
self.p_name = {}
if timelimit >= 0:
self.tmo = float(timelimit)
@@ -215,7 +213,7 @@ class RemoteInterface(object):
def _wrapper(self, _method_name, *args, **kwargs):
# Let's see how long a method takes to execute, in call cases we should
# Lets 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)
@@ -243,14 +241,6 @@ 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):

View File

@@ -188,6 +188,12 @@ if test -n "$LVM_TEST_LVMLOCKD_TEST" ; then
aux prepare_lvmlockd
fi
echo "<======== Processing test: \"$TESTNAME\" ========>"
(
MSG="<======== Processing test: \"$TESTNAME\" ========>"
echo "$MSG"
echo "$MSG" > /dev/console 2>/dev/null
logger -p user.notice "$MSG" 2>/dev/null
true
)
set -vx

View File

@@ -1,353 +0,0 @@
#!/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

View File

@@ -29,12 +29,6 @@
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) {

View File

@@ -104,10 +104,6 @@ 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

View File

@@ -41,15 +41,16 @@ lvcreate -L2M -n $lv1 $vg
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
# active thin pool is needed to use policy
not lvextend --use-policies $vg/pool 2>&1 | tee err
lvchange -ay $vg
# Cannot resize if set to 0%
not lvextend --use-policies --config 'activation{thin_pool_autoextend_percent = 0}' $vg/pool 2>&1 | tee err
grep "0%" err
# Locally active LV is needed
not lvextend --use-policies $vg/pool 2>&1 | tee err
grep "locally" err
lvchange -ay $vg
# Creation of new LV is not allowed when thinpool is over threshold
not lvcreate -V10 $vg/pool

View File

@@ -37,18 +37,15 @@ lvs -a $vg
"$MKFS" "$lvdev"
# this should resolve to resize to same actual size
not lvreduce -l-100%FREE $vg/$lv1
not lvreduce -r -f -l-100%FREE $vg/$lv1
lvreduce -r -f -l-100%FREE $vg/$lv1
"$FSCK" -n "$lvdev"
# size should remain the same
not lvextend -l+100%FREE $vg/$lv1
not lvextend -r -f -l+100%FREE $vg/$lv1
lvextend -r -f -l+100%FREE $vg/$lv1
"$FSCK" -n "$lvdev"
#lvchange -an $vg/$lv1
not lvresize -l+100%FREE $vg/$lv1
not lvresize -r -f -l+100%FREE $vg/$lv1
lvresize -r -f -l+100%FREE $vg/$lv1
"$FSCK" -n "$lvdev"
# Check there is really file system resize happening
@@ -58,8 +55,7 @@ not lvresize -r -f -l+100%FREE $vg/$lv1
grep "20000 blocks" out
SIZE=$(get lv_field $vg/$lv1 size)
not lvresize -l-100%FREE $vg/$lv1
not lvresize -r -f -l-100%FREE $vg/$lv1
lvresize -r -f -l-100%FREE $vg/$lv1
test "$SIZE" = "$(get lv_field $vg/$lv1 size)"
"$FSCK" -n "$lvdev" | tee out
@@ -68,10 +64,7 @@ grep -v "20000 blocks" out
# Also check it fails when the user 'resize' volume without
# resizing fs and then retries with '-r'.
# The first lvreduce intentionally ignores the fs and intentionally
# corrupts the fs so that the second lvresize will fail when it runs
# fsck.
lvreduce -f --fs ignore -l50%VG $vg/$lv1
fail lvresize -r -f -l20%VG $vg/$lv1
lvreduce -f -l50%VG $vg/$lv1
fail lvresize -r -f -l50%VG $vg/$lv1
lvremove -ff $vg

View File

@@ -29,7 +29,7 @@ for deactivate in true false; do
check mirror_images_contiguous $vg $lv1
# reduce 2-way mirror
lvreduce -f --fs ignore -l-2 $vg/$lv1
lvreduce -f -l-2 $vg/$lv1
check mirror $vg $lv1 "$dev3"
# extend 2-way mirror (cling if not contiguous)

View File

@@ -52,7 +52,7 @@ lvcreate -an -Zn -l1 -n $lv1 -i3 $vg
lvextend -l+100%FREE -i3 $vg/$lv1
check vg_field $vg vg_free_count 2
lvreduce -f --fs ignore -l50%LV $vg/$lv1
lvreduce -f -l50%LV $vg/$lv1
vgremove -f $vg
vgcreate $SHARED -s 4M $vg "$dev1" "$dev2" "$dev3"
@@ -72,21 +72,21 @@ lvextend -l+100%FREE $vg/lv
check vg_field $vg vg_free_count 0
# Rounds up and should reduce just by 3 extents
lvreduce -f --fs ignore -l-4 $vg/lv
lvreduce -f -l-4 $vg/lv
check vg_field $vg vg_free_count 3
# Should round up to 15 extents
lvextend -f -l+1 $vg/lv
check vg_field $vg vg_free_count 0
lvreduce -f --fs ignore -l-4 $vg/lv
lvreduce -f -l-4 $vg/lv
check vg_field $vg vg_free_count 3
lvextend -l90%VG $vg/lv
check vg_field $vg vg_free_count 0
not lvreduce -f --fs ignore -l-10%LV $vg/lv
not lvreduce -f -l-10%LV $vg/lv
check vg_field $vg vg_free_count 0
lvreduce -f --fs ignore -l-20%LV $vg/lv
lvreduce -f -l-20%LV $vg/lv
check vg_field $vg vg_free_count 3

View File

@@ -54,7 +54,7 @@ vgcreate $vg "$dev1"
lvcreate -L5G -n $lv1 $vg
vdo create $VDOCONF --name "$VDONAME" --device "$DM_DEV_DIR/$vg/$lv1" --vdoSlabSize 128M --vdoLogicalSize 10G
vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogicalSize=10G
mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
@@ -75,7 +75,7 @@ lvremove -f $vg
# Test user can specify different VDO LV name (so the original LV is renamed)
lvcreate -y -L5G -n $lv1 $vg
vdo create $VDOCONF --name "$VDONAME" --device "$DM_DEV_DIR/$vg/$lv1" --vdoSlabSize 128M --vdoLogicalSize 10G
vdo create $VDOCONF --name "$VDONAME" --device="$DM_DEV_DIR/$vg/$lv1" --vdoLogicalSize=10G
lvm_import_vdo -y --name $vg/$lv2 "$DM_DEV_DIR/$vg/$lv1"
@@ -95,7 +95,7 @@ vgcreate $vg2 "$dev2"
#
# Check conversion of VDO volume on non-LV device and with >2T size
#
vdo create $VDOCONF --name "$VDONAME" --device "$dev1" --vdoSlabSize 128M --vdoLogicalSize 3T
vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=3T
# Fail with an already existing volume group $vg2
not lvm_import_vdo --dry-run -y -v --name $vg2/$lv1 "$dev1" |& tee err
@@ -117,7 +117,7 @@ vgremove -f $vg
aux teardown_devs
aux prepare_devs 1 23456
vdo create $VDOCONF --name "$VDONAME" --device "$dev1" --vdoSlabSize 128M --vdoLogicalSize 23G
vdo create $VDOCONF --name "$VDONAME" --device="$dev1" --vdoLogicalSize=23G
mkfs -E nodiscard "$DM_DEV_DIR/mapper/$VDONAME"
@@ -137,7 +137,6 @@ aux prepare_loop 60000 || skip
test -f LOOP
LOOP=$(< LOOP)
LOOP="${DM_DEV_DIR}/${LOOP##/dev/}"
aux extend_filter "a|$LOOP|"
aux extend_devices "$LOOP"
@@ -156,7 +155,7 @@ aux extend_devices "$LOOP"
#
# automate...
#
vdo create $VDOCONF --name "$VDONAME" --device "$LOOP" --vdoSlabSize 128M --vdoLogicalSize 23G\
vdo create $VDOCONF --name "$VDONAME" --device="$LOOP" --vdoLogicalSize=23G \
--blockMapCacheSize 192 \
--blockMapPeriod 2048 \
--emulate512 disabled \
@@ -174,7 +173,7 @@ vdo create $VDOCONF --name "$VDONAME" --device "$LOOP" --vdoSlabSize 128M --vdoL
# Get VDO table line
dmsetup table "$VDONAME" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee vdo-orig
lvm_import_vdo -y --name $vg/$lv "$LOOP"
DM_DEV_DIR="" lvm_import_vdo -y --name $vg/$lv "$LOOP"
lvs -a $vg
dmsetup table "$vg-${lv}_vpool-vpool" | tr " " "\n" | sed -e '5,6d' -e '12d' | tee new-vdo-lv

View File

@@ -37,7 +37,7 @@ bool register_test(struct test_suite *ts,
void test_fail(const char *fmt, ...)
__attribute__((noreturn, format (printf, 1, 2)));
#define T_ASSERT(e) do {if (!(e)) {test_fail("assertion failed: '%s'", # e);} } while(0)
#define T_ASSERT(e) do {if (!(e)) {test_fail("assertion failed: '%s' at %s:%d", # e, __FILE__, __LINE__);} } while(0)
#define T_ASSERT_EQUAL(x, y) T_ASSERT((x) == (y))
#define T_ASSERT_NOT_EQUAL(x, y) T_ASSERT((x) != (y))

View File

@@ -301,27 +301,6 @@ arg(foreign_ARG, '\0', "foreign", 0, 0, 0,
"Report/display foreign VGs that would otherwise be skipped.\n"
"See \\fBlvmsystemid\\fP(7) for more information about foreign VGs.\n")
arg(fs_ARG, '\0', "fs", string_VAL, 0, 0,
"File system handling when resizing an LV.\n"
"\\fBchecksize\\fP: Only when reducing size, does nothing when extending.\n"
"Check the fs size and reduce the LV if the fs is not using the affected\n"
"space, i.e. the fs does not need to be shrunk. Fail the command without\n"
"reducing the fs or LV if the fs is using the affected space.\n"
"\\fBresize_remount\\fP: Resize the fs if needed. Mounts or unmounts the fs as\n"
"required (avoids mounting/unmounting when possible.)\n"
"Attempts to restore the original mount state when finished.\n"
"\\fBresize_keepmount\\fP: Resize the fs if needed, only if it can be done without\n"
"changing the current mount state. Fail the command without\n"
"resizing the fs or LV if an fs resize requires mounting or unmounting\n"
"\\fBresize_unmount\\fP: Resize the fs if needed, only while unmounted. Unmount the\n"
"fs if needed. Fail the command without resizing the fs\n"
"or LV if an fs resize is needed that requires the the fs to be mounted\n"
"\\fBresize\\fP: Equivalent to resize_remount.\n"
"\\fBresize_fsadm\\fP: Use the old method of calling fsadm to do handle the fs\n"
"(deprecated).\n"
"\\fBignore\\fP: Resize the LV without checking for or handling a file system.\n"
"WARNING: using ignore when reducing the LV size may cause data loss.\n")
arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", 0, 0, 0,
"Allows a polling operation to continue when PVs are missing,\n"
"e.g. for repairs due to faulty devices.\n")
@@ -1468,8 +1447,7 @@ arg(readahead_ARG, 'r', "readahead", readahead_VAL, 0, 0,
"\\fBnone\\fP is equivalent to zero.\n")
arg(resizefs_ARG, 'r', "resizefs", 0, 0, 0,
"Resize the file system on the LV.\n"
"Equivalent to --fs resize_remount. See --fs for more options.\n")
"Resize underlying filesystem together with the LV using \\fBfsadm\\fP(8).\n")
/* Not used */
arg(reset_ARG, 'R', "reset", 0, 0, 0, NULL)

View File

@@ -1379,35 +1379,35 @@ lvextend --size PSizeMB LV
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync, --reportformat ReportFmt, --resizefs,
--stripes Number, --stripesize SizeKB, --poolmetadatasize PSizeMB,
--type SegType, --fs String
--type SegType
OP: PV ...
ID: lvextend_size
ID: lvextend_by_size
DESC: Extend an LV by a specified size.
lvextend LV PV ...
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB,
--type SegType, --fs String
ID: lvextend_pv
--type SegType
ID: lvextend_by_pv
DESC: Extend an LV by specified PV extents.
lvextend --poolmetadatasize PSizeMB LV_thinpool_linear
lvextend --poolmetadatasize PSizeMB LV_thinpool
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --stripes Number, --stripesize SizeKB,
--type SegType
OP: PV ...
ID: lvextend_pool_metadata
ID: lvextend_pool_metadata_by_size
DESC: Extend a pool metadata SubLV by a specified size.
lvextend --usepolicies LV_snapshot_thinpool_vdopool
lvextend --usepolicies LV_thinpool_snapshot
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors Number,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs,
--type SegType, --fs String
--type SegType
OP: PV ...
ID: lvextend_policy
ID: lvextend_by_policy
DESC: Extend an LV according to a predefined policy.
---
@@ -1454,8 +1454,8 @@ DESC: Remove the devices file entry for the given PVID.
lvreduce --size NSizeMB LV
OO: --autobackup Bool, --force, --nofsck, --noudevsync,
--reportformat ReportFmt, --resizefs, --fs String
ID: lvreduce_size
--reportformat ReportFmt, --resizefs
ID: lvreduce_general
---
@@ -1484,17 +1484,17 @@ lvresize --size SSizeMB LV
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync, --reportformat ReportFmt, --resizefs,
--stripes Number, --stripesize SizeKB, --poolmetadatasize PSizeMB,
--type SegType, --fs String
--type SegType
OP: PV ...
ID: lvresize_size
ID: lvresize_by_size
DESC: Resize an LV by a specified size.
lvresize LV PV ...
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat ReportFmt, --resizefs, --stripes Number, --stripesize SizeKB,
--type SegType, --fs String
ID: lvresize_pv
--type SegType
ID: lvresize_by_pv
DESC: Resize an LV by specified PV extents.
lvresize --poolmetadatasize PSizeMB LV_thinpool
@@ -1503,7 +1503,7 @@ OO: --alloc Alloc, --autobackup Bool, --force,
--reportformat ReportFmt, --stripes Number, --stripesize SizeKB,
--type SegType
OP: PV ...
ID: lvresize_pool_metadata
ID: lvresize_pool_metadata_by_size
DESC: Resize a pool metadata SubLV by a specified size.
---
@@ -1593,10 +1593,10 @@ pvdisplay
OO: --aligned, --all, --binary, --colon, --columns, --configreport ConfigReport,
--foreign, --ignorelockingfailure,
--logonly, --maps, --noheadings, --nosuffix, --options String,
--readonly, --reportformat ReportFmt, --select String, --separator String, --shared,
--readonly, --select String, --separator String, --shared,
--short, --sort String, --unbuffered, --units Units
OP: PV|Tag ...
IO: --ignoreskippedcluster
IO: --ignoreskippedcluster, --reportformat ReportFmt
ID: pvdisplay_general
---

View File

@@ -17,5 +17,5 @@
int lvextend(struct cmd_context *cmd, int argc, char **argv)
{
return lvresize_cmd(cmd, argc, argv);
return lvresize(cmd, argc, argv);
}

View File

@@ -165,16 +165,6 @@ static const struct command_function _command_functions[CMD_COUNT] = {
{ pvscan_display_CMD, pvscan_display_cmd },
{ pvscan_cache_CMD, pvscan_cache_cmd },
/* lvextend/lvreduce/lvresize */
{ lvextend_policy_CMD, lvextend_policy_cmd },
{ lvextend_pool_metadata_CMD, lvresize_cmd },
{ lvresize_pool_metadata_CMD, lvresize_cmd },
{ lvextend_pv_CMD, lvresize_cmd },
{ lvresize_pv_CMD, lvresize_cmd },
{ lvextend_size_CMD, lvresize_cmd },
{ lvreduce_size_CMD, lvresize_cmd },
{ lvresize_size_CMD, lvresize_cmd },
};
@@ -3153,9 +3143,6 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
if (!(cmd->command = _find_command(cmd, cmd->name, &argc, argv)))
return EINVALID_CMD_LINE;
/* avoid this by letting lib code use cmd->command */
cmd->command_enum = cmd->command->command_enum;
/*
* If option --foo is set which is listed in IO (ignore option) in
* command-lines.in, then unset foo. Commands won't usually use an
@@ -3318,7 +3305,6 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
hints_exit(cmd);
lvmcache_destroy(cmd, 1, 1);
label_scan_destroy(cmd);
devices_file_exit(cmd);
if ((config_string_cft = remove_config_tree_by_source(cmd, CONFIG_STRING)))
dm_config_destroy(config_string_cft);

View File

@@ -17,5 +17,5 @@
int lvreduce(struct cmd_context *cmd, int argc, char **argv)
{
return lvresize_cmd(cmd, argc, argv);
return lvresize(cmd, argc, argv);
}

View File

@@ -15,133 +15,12 @@
#include "tools.h"
static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
static int _lvresize_params(struct cmd_context *cmd, int argc, char **argv,
struct lvresize_params *lp)
{
const char *cmd_name = command_name(cmd);
const char *type_str = arg_str_value(cmd, type_ARG, NULL);
int only_linear = 0;
int set_fsopt = 0;
int set_extents_and_size = 0;
memset(lp, 0, sizeof(struct lvresize_params));
switch (cmd->command->command_enum) {
case lvextend_policy_CMD:
lp->resize = LV_EXTEND;
lp->size = 0;
lp->extents = 0;
lp->percent = PERCENT_LV;
lp->sign = SIGN_PLUS;
lp->poolmetadata_size = 0;
lp->use_policies = 1;
break;
case lvextend_pool_metadata_CMD:
case lvresize_pool_metadata_CMD:
lp->resize = LV_EXTEND;
lp->size = 0;
lp->extents = 0;
lp->percent = PERCENT_NONE;
lp->sign = SIGN_NONE;
lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0);
lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
break;
case lvextend_pv_CMD:
case lvresize_pv_CMD:
lp->resize = LV_EXTEND;
lp->size = 0;
lp->extents = 0;
lp->percent_value = 100;
lp->percent = PERCENT_PVS;
lp->sign = SIGN_PLUS;
lp->poolmetadata_size = 0;
set_fsopt = 1;
break;
case lvextend_size_CMD:
lp->resize = LV_EXTEND;
if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0)))
lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
set_extents_and_size = 1;
set_fsopt = 1;
break;
case lvreduce_size_CMD:
lp->resize = LV_REDUCE;
lp->poolmetadata_size = 0;
set_extents_and_size = 1;
set_fsopt = 1;
break;
case lvresize_size_CMD:
lp->resize = LV_ANY;
lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0);
if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0)))
lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
set_extents_and_size = 1;
set_fsopt = 1;
break;
default:
log_error(INTERNAL_ERROR "unknown lvresize type");
return 0;
};
if (set_fsopt) {
const char *str;
if ((str = arg_str_value(cmd, fs_ARG, NULL))) {
if (!strcmp(str, "checksize") ||
!strcmp(str, "resize") ||
!strcmp(str, "resize_remount") ||
!strcmp(str, "resize_keepmount") ||
!strcmp(str, "resize_unmount") ||
!strcmp(str, "resize_fsadm")) {
strncpy(lp->fsopt, str, sizeof(lp->fsopt)-1);
} else if (!strcmp(str, "ignore")) {
lp->fsopt[0] = '\0';
} else {
log_error("Unknown --fs value.");
return 0;
}
} else if (arg_is_set(cmd, resizefs_ARG)) {
/* --resizefs alone equates to --fs resize */
strncpy(lp->fsopt, "resize", sizeof(lp->fsopt)-1);
} else {
/*
* Use checksize when no fs option is specified.
* checksize with extend does nothing: the LV
* is extended and any fs is ignored.
* checksize with reduce checks for an fs that
* needs reducing: the LV is reduced only if the
* fs does not need to be reduced (or no fs.)
*/
strncpy(lp->fsopt, "checksize", sizeof(lp->fsopt)-1);
}
if (lp->fsopt[0])
lp->nofsck = arg_is_set(cmd, nofsck_ARG);
}
if (set_extents_and_size) {
if ((lp->extents = arg_uint_value(cmd, extents_ARG, 0))) {
lp->sign = arg_sign_value(cmd, extents_ARG, 0);
lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
}
if ((lp->size = arg_uint64_value(cmd, size_ARG, 0))) {
lp->sign = arg_sign_value(cmd, size_ARG, 0);
lp->percent = PERCENT_NONE;
}
if (lp->size && lp->extents) {
log_error("Please specify either size or extents but not both.");
return 0;
}
}
lp->alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, 0);
lp->yes = arg_is_set(cmd, yes_ARG);
lp->force = arg_is_set(cmd, force_ARG),
lp->nosync = arg_is_set(cmd, nosync_ARG);
lp->lockopt = arg_str_value(cmd, lockopt_ARG, NULL);
if (type_str) {
if (!strcmp(type_str, "linear")) {
@@ -153,6 +32,104 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
return_0;
}
if (!strcmp(cmd_name, "lvreduce"))
lp->resize = LV_REDUCE;
else if (!strcmp(cmd_name, "lvextend"))
lp->resize = LV_EXTEND;
else
lp->resize = LV_ANY;
lp->sign = lp->poolmetadata_sign = SIGN_NONE;
if ((lp->use_policies = arg_is_set(cmd, usepolicies_ARG))) {
/* do nothing; lv_resize will handle --use-policies itself */
if (arg_from_list_is_set(cmd, NULL,
chunksize_ARG, extents_ARG,
poolmetadatasize_ARG,
regionsize_ARG,
size_ARG,
stripes_ARG, stripesize_ARG,
-1))
log_print_unless_silent("Ignoring size parameters with --use-policies.");
} else {
/*
* Allow omission of extents and size if the user has given us
* one or more PVs. Most likely, the intent was "resize this
* LV the best you can with these PVs"
* If only --poolmetadatasize is specified with list of PVs,
* then metadata will be extended there.
*/
if ((lp->extents = arg_uint_value(cmd, extents_ARG, 0))) {
lp->sign = arg_sign_value(cmd, extents_ARG, SIGN_NONE);
lp->percent = arg_percent_value(cmd, extents_ARG, PERCENT_NONE);
}
if (arg_from_list_is_zero(cmd, "may not be zero",
chunksize_ARG, extents_ARG,
poolmetadatasize_ARG,
regionsize_ARG,
size_ARG,
stripes_ARG, stripesize_ARG,
virtualsize_ARG,
-1))
return_0;
if ((lp->poolmetadata_size = arg_uint64_value(cmd, poolmetadatasize_ARG, 0))) {
lp->poolmetadata_sign = arg_sign_value(cmd, poolmetadatasize_ARG, SIGN_NONE);
if (lp->poolmetadata_sign == SIGN_MINUS) {
log_error("Can't reduce pool metadata size.");
return 0;
}
}
if ((lp->size = arg_uint64_value(cmd, size_ARG, 0))) {
lp->sign = arg_sign_value(cmd, size_ARG, SIGN_NONE);
lp->percent = PERCENT_NONE;
}
if (lp->size && lp->extents) {
log_error("Please specify either size or extents but not both.");
return 0;
}
if (!lp->extents &&
!lp->size &&
!lp->poolmetadata_size &&
(argc >= 2)) {
lp->extents = 100;
lp->percent = PERCENT_PVS;
lp->sign = SIGN_PLUS;
}
}
if (lp->resize == LV_EXTEND && lp->sign == SIGN_MINUS) {
log_error("Negative argument not permitted - use lvreduce.");
return 0;
}
if (lp->resize == LV_REDUCE &&
((lp->sign == SIGN_PLUS) ||
(lp->poolmetadata_sign == SIGN_PLUS))) {
log_error("Positive sign not permitted - use lvextend.");
return 0;
}
if (!argc) {
log_error("Please provide the logical volume name.");
return 0;
}
lp->lv_name = argv[0];
if (!validate_lvname_param(cmd, &lp->vg_name, &lp->lv_name))
return_0;
/* Check for $LVM_VG_NAME */
if (!lp->vg_name && !(lp->vg_name = extract_vgname(cmd, NULL))) {
log_error("Please specify a logical volume path.");
return 0;
}
if (arg_is_set(cmd, mirrors_ARG)) {
if (arg_sign_value(cmd, mirrors_ARG, SIGN_NONE) != SIGN_NONE) {
log_error("Mirrors argument may not be signed.");
@@ -179,153 +156,66 @@ static int _lvresize_params(struct cmd_context *cmd, struct lvresize_params *lp)
return 0;
}
lp->argc = --argc;
lp->argv = ++argv;
return 1;
}
/*
* lvextend --use-policies is usually called by dmeventd, as a method of
* "auto extending" an LV as it's used. It checks how full a snapshot cow or
* thin pool is, and extends it if it's too full, based on threshold settings
* in lvm.conf for when to auto extend it.
*
* The extension of a thin pool LV can involve extending either the data sub
* LV, the metadata sub LV, or both, so there may be two LVs extended here.
*/
static int _lv_extend_policy(struct cmd_context *cmd, struct logical_volume *lv,
struct lvresize_params *lp, int *skipped)
{
struct lvresize_params lp_meta;
uint32_t percent_main = 0;
uint32_t percent_meta = 0;
int is_active;
memset(&lp_meta, 0, sizeof(lp_meta));
if (!lv_is_cow(lv) && !lv_is_thin_pool(lv) && !lv_is_vdo_pool(lv)) {
log_error("lvextend policy is supported only for snapshot, thin pool and vdo pool volumes.");
*skipped = 1;
return 0;
}
is_active = lv_is_active(lv);
if (vg_is_shared(lv->vg) && !is_active) {
log_debug("lvextend policy requires LV to be active in a shared VG.");
*skipped = 1;
return 1;
}
if (lv_is_thin_pool(lv) && !is_active) {
log_error("lvextend using policy requires the thin pool to be active.");
return 0;
}
/*
* Calculate the percent of extents to extend the LV based on current
* usage info from the kernel and policy settings from lvm.conf, e.g.
* autoextend_threshold, autoextend_percent. For thin pools, both the
* thin pool data LV and thin pool metadata LV may need to be extended.
* In this case, percent_main is the amount to extend the data LV, and
* percent_meta is the amount to extend the metadata LV.
*/
if (!lv_extend_policy_calculate_percent(lv, &percent_main, &percent_meta))
return_0;
if (!percent_main && !percent_meta) {
log_debug("lvextend policy not needed.");
*skipped = 1;
return 1;
}
*skipped = 0;
lp->policy_percent_main = percent_main;
lp->policy_percent_meta = percent_meta;
return lv_resize(cmd, lv, lp);
}
static int _lvextend_policy_single(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle)
static int _lvresize_single(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg, struct processing_handle *handle)
{
struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
int skipped = 0;
struct dm_list *pvh;
struct logical_volume *lv;
int ret = ECMD_FAILED;
if (cmd->position_argc > 1) {
/* First pos arg is required LV, remaining are optional PVs. */
if (!(lp->pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
return_ECMD_FAILED;
} else
lp->pvh = &lv->vg->pvs;
/* Does LV exist? */
if (!(lv = find_lv(vg, lp->lv_name))) {
log_error("Logical volume %s not found in volume group %s.",
lp->lv_name, vg->name);
goto out;
}
if (!_lv_extend_policy(cmd, lv, lp, &skipped))
return ECMD_FAILED;
if (!(pvh = lp->argc ? create_pv_list(cmd->mem, vg, lp->argc, lp->argv, 1) : &vg->pvs))
goto_out;
if (!skipped)
log_print_unless_silent("Logical volume %s successfully resized.", display_lvname(lv));
return ECMD_PROCESSED;
}
static int _lvresize_single(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle)
{
struct lvresize_params *lp = (struct lvresize_params *) handle->custom_handle;
int ret;
if (cmd->position_argc > 1) {
/* First pos arg is required LV, remaining are optional PVs. */
if (!(lp->pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
return_ECMD_FAILED;
} else
lp->pvh = &lv->vg->pvs;
ret = lv_resize(cmd, lv, lp);
if (ret || lp->extend_fs_error)
log_print_unless_silent("Logical volume %s successfully resized.",
display_lvname(lv));
if (!ret)
return ECMD_FAILED;
return ECMD_PROCESSED;
}
int lvextend_policy_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle;
struct lvresize_params lp;
int ret;
if (!_lvresize_params(cmd, &lp))
return EINVALID_CMD_LINE;
if (!(handle = init_processing_handle(cmd, NULL)))
return ECMD_FAILED;
handle->custom_handle = &lp;
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, NULL, &_lvextend_policy_single);
destroy_processing_handle(cmd, handle);
if (!lv_resize(lv, lp, pvh))
goto_out;
ret = ECMD_PROCESSED;
out:
return ret;
}
int lvresize_cmd(struct cmd_context *cmd, int argc, char **argv)
int lvresize(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle;
struct lvresize_params lp;
struct lvresize_params lp = {
.alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, 0),
.yes = arg_is_set(cmd, yes_ARG),
.force = arg_is_set(cmd, force_ARG),
.nofsck = arg_is_set(cmd, nofsck_ARG),
.nosync = arg_is_set(cmd, nosync_ARG),
.resizefs = arg_is_set(cmd, resizefs_ARG),
.lockopt = arg_str_value(cmd, lockopt_ARG, NULL),
};
int ret;
if (!_lvresize_params(cmd, &lp))
if (!_lvresize_params(cmd, argc, argv, &lp)) {
stack;
return EINVALID_CMD_LINE;
}
if (!(handle = init_processing_handle(cmd, NULL)))
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
return ECMD_FAILED;
}
handle->custom_handle = &lp;
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, NULL, &_lvresize_single);
ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, 0, handle,
&_lvresize_single);
destroy_processing_handle(cmd, handle);
@@ -334,16 +224,3 @@ int lvresize_cmd(struct cmd_context *cmd, int argc, char **argv)
return ret;
}
/*
* All lvresize command defs have their own function,
* so the generic function name is unused.
*/
int lvresize(struct cmd_context *cmd, int argc, char **argv)
{
log_error(INTERNAL_ERROR "Missing function for command definition %d:%s.",
cmd->command->command_index, cmd->command->command_id);
return ECMD_FAILED;
}

View File

@@ -45,18 +45,19 @@
#include "lib/notify/lvmnotify.h"
#include "lib/label/hints.h"
/*
* cmd_enum.h uses the generated cmds.h to create the enum with an ID
* for each command definition in command-lines.in.
*/
#include "lib/commands/cmd_enum.h"
#include <ctype.h>
#include <sys/types.h>
#define CMD_LEN 256
#define MAX_ARGS 64
/* define the enums for each unique ID in command defs in command-lines.in */
enum {
#define cmd(a, b) a ,
#include "cmds.h"
#undef cmd
};
/* define the enums for the values accepted by command line --options, foo_VAL */
enum {
#define val(a, b, c, d) a ,
@@ -294,7 +295,4 @@ int lvconvert_cachevol_attach_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle);
int lvresize_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvextend_policy_cmd(struct cmd_context *cmd, int argc, char **argv);
#endif