diff -Nru lvm2-2.02.167/daemons/dmeventd/plugins/raid/dmeventd_raid.c lvm2-2.02.168/daemons/dmeventd/plugins/raid/dmeventd_raid.c --- lvm2-2.02.167/daemons/dmeventd/plugins/raid/dmeventd_raid.c 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/dmeventd/plugins/raid/dmeventd_raid.c 2016-11-30 23:17:28.000000000 +0000 @@ -61,7 +61,7 @@ if (status->insync_regions < status->total_regions) { if (!state->warned) log_warn("WARNING: waiting for resynchronization to finish " - "before initiating repair on RAID device %s", device); + "before initiating repair on RAID device %s.", device); state->warned = 1; goto out; /* Not yet done syncing with accessible devices */ diff -Nru lvm2-2.02.167/daemons/lvmdbusd/automatedproperties.py lvm2-2.02.168/daemons/lvmdbusd/automatedproperties.py --- lvm2-2.02.167/daemons/lvmdbusd/automatedproperties.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/automatedproperties.py 2016-11-30 23:17:28.000000000 +0000 @@ -159,10 +159,7 @@ cfg.om.lookup_update(self, new_id[0], new_id[1]) # Grab the properties values, then replace the state of the object - # and retrieve the new values - # TODO: We need to add locking to prevent concurrent access to the - # properties so that a client is not accessing while we are - # replacing. + # and retrieve the new values. o_prop = get_properties(self) self.state = new_state n_prop = get_properties(self) diff -Nru lvm2-2.02.167/daemons/lvmdbusd/background.py lvm2-2.02.168/daemons/lvmdbusd/background.py --- lvm2-2.02.167/daemons/lvmdbusd/background.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/background.py 2016-11-30 23:17:28.000000000 +0000 @@ -13,6 +13,7 @@ import dbus from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug import os +import threading def pv_move_lv_cmd(move_options, lv_full_name, @@ -126,3 +127,16 @@ raise dbus.exceptions.DBusException( interface_name, 'LV with uuid %s and name %s not present!' % (lv_uuid, lv_name)) + + +def _run_cmd(req): + log_debug( + "_run_cmd: Running method: %s with args %s" % + (str(req.method), str(req.arguments))) + req.run_cmd() + log_debug("_run_cmd: complete!") + + +def cmd_runner(request): + t = threading.Thread(target=_run_cmd, args=(request,)) + t.start() diff -Nru lvm2-2.02.167/daemons/lvmdbusd/cfg.py lvm2-2.02.168/daemons/lvmdbusd/cfg.py --- lvm2-2.02.167/daemons/lvmdbusd/cfg.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/cfg.py 2016-11-30 23:17:28.000000000 +0000 @@ -38,12 +38,12 @@ # Lock used by pprint stdout_lock = multiprocessing.Lock() -kick_q = multiprocessing.Queue() worker_q = queue.Queue() # Main event loop loop = None +BUS_NAME = os.getenv('LVM_DBUS_NAME', 'com.redhat.lvmdbus1') BASE_INTERFACE = 'com.redhat.lvmdbus1' PV_INTERFACE = BASE_INTERFACE + '.Pv' VG_INTERFACE = BASE_INTERFACE + '.Vg' @@ -77,6 +77,7 @@ # Used to prevent circular imports... load = None +event = None # Global cached state db = None diff -Nru lvm2-2.02.167/daemons/lvmdbusd/cmdhandler.py lvm2-2.02.168/daemons/lvmdbusd/cmdhandler.py --- lvm2-2.02.167/daemons/lvmdbusd/cmdhandler.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/cmdhandler.py 2016-11-30 23:17:28.000000000 +0000 @@ -15,14 +15,9 @@ import traceback import os -try: - from . import cfg - from .utils import pv_dest_ranges, log_debug, log_error - from .lvm_shell_proxy import LVMShellProxy -except SystemError: - import cfg - from utils import pv_dest_ranges, log_debug, log_error - from lvm_shell_proxy import LVMShellProxy +from lvmdbusd import cfg +from lvmdbusd.utils import pv_dest_ranges, log_debug, log_error +from lvmdbusd.lvm_shell_proxy import LVMShellProxy try: import simplejson as json @@ -60,18 +55,19 @@ class LvmFlightRecorder(object): - def __init__(self): - self.queue = collections.deque(maxlen=16) + def __init__(self, size=16): + self.queue = collections.deque(maxlen=size) def add(self, lvm_exec_meta): self.queue.append(lvm_exec_meta) def dump(self): with cmd_lock: - log_error("LVM dbus flight recorder START") - for c in self.queue: - log_error(str(c)) - log_error("LVM dbus flight recorder END") + if len(self.queue): + log_error("LVM dbus flight recorder START") + for c in self.queue: + log_error(str(c)) + log_error("LVM dbus flight recorder END") cfg.blackbox = LvmFlightRecorder() @@ -117,6 +113,7 @@ def _shell_cfg(): global _t_call + # noinspection PyBroadException try: lvm_shell = LVMShellProxy() _t_call = lvm_shell.call_lvm @@ -357,7 +354,8 @@ size_bytes, num_stripes, stripe_size_kb) -def vg_lv_create_mirror(vg_name, create_options, name, size_bytes, num_copies): +def vg_lv_create_mirror( + vg_name, create_options, name, size_bytes, num_copies): cmd = ['lvcreate'] cmd.extend(options_to_cli_args(create_options)) @@ -732,8 +730,8 @@ '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'] + '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) @@ -750,4 +748,4 @@ pv_data = pv_retrieve_with_segs() for p in pv_data: - log_debug(str(p)) + print(str(p)) diff -Nru lvm2-2.02.167/daemons/lvmdbusd/fetch.py lvm2-2.02.168/daemons/lvmdbusd/fetch.py --- lvm2-2.02.167/daemons/lvmdbusd/fetch.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/fetch.py 2016-11-30 23:17:28.000000000 +0000 @@ -11,7 +11,10 @@ from .vg import load_vgs from .lv import load_lvs from . import cfg -from .utils import MThreadRunner, log_debug +from .utils import MThreadRunner, log_debug, log_error +import threading +import queue +import traceback def _main_thread_load(refresh=True, emit_signal=True): @@ -45,3 +48,114 @@ rc = _main_thread_load(refresh, emit_signal) return rc + + +# Even though lvm can handle multiple changes concurrently it really doesn't +# make sense to make a 1-1 fetch of data for each change of lvm because when +# we fetch the data once all previous changes are reflected. +class StateUpdate(object): + + class UpdateRequest(object): + + def __init__(self, refresh, emit_signal, cache_refresh, log, + need_main_thread): + self.is_done = False + self.refresh = refresh + self.emit_signal = emit_signal + self.cache_refresh = cache_refresh + self.log = log + self.need_main_thread = need_main_thread + self.result = None + self.cond = threading.Condition(threading.Lock()) + + def done(self): + with self.cond: + if not self.is_done: + self.cond.wait() + return self.result + + def set_result(self, result): + with self.cond: + self.result = result + self.is_done = True + self.cond.notify_all() + + @staticmethod + def update_thread(obj): + while cfg.run.value != 0: + # noinspection PyBroadException + try: + queued_requests = [] + refresh = True + emit_signal = True + cache_refresh = True + log = True + need_main_thread = True + + with obj.lock: + wait = not obj.deferred + obj.deferred = False + + if wait: + queued_requests.append(obj.queue.get(True, 2)) + + # Ok we have one or the deferred queue has some, + # check if any others + try: + while True: + queued_requests.append(obj.queue.get(False)) + + except queue.Empty: + pass + + if len(queued_requests) > 1: + log_debug("Processing %d updates!" % len(queued_requests), + 'bg_black', 'fg_light_green') + + # We have what we can, run the update with the needed options + for i in queued_requests: + if not i.refresh: + refresh = False + if not i.emit_signal: + emit_signal = False + if not i.cache_refresh: + cache_refresh = False + if not i.log: + log = False + if not i.need_main_thread: + need_main_thread = False + + num_changes = load(refresh, emit_signal, cache_refresh, log, + need_main_thread) + # Update is done, let everyone know! + for i in queued_requests: + i.set_result(num_changes) + + except queue.Empty: + pass + except Exception: + st = traceback.format_exc() + log_error("update_thread exception: \n%s" % st) + + def __init__(self): + self.lock = threading.RLock() + self.queue = queue.Queue() + self.deferred = False + + # Do initial load + load(refresh=False, emit_signal=False, need_main_thread=False) + + self.thread = threading.Thread(target=StateUpdate.update_thread, + args=(self,)) + + def load(self, refresh=True, emit_signal=True, cache_refresh=True, + log=True, need_main_thread=True): + # Place this request on the queue and wait for it to be completed + req = StateUpdate.UpdateRequest(refresh, emit_signal, cache_refresh, + log, need_main_thread) + self.queue.put(req) + return req.done() + + def event(self): + with self.lock: + self.deferred = True diff -Nru lvm2-2.02.167/daemons/lvmdbusd/job.py lvm2-2.02.168/daemons/lvmdbusd/job.py --- lvm2-2.02.167/daemons/lvmdbusd/job.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/job.py 2016-11-30 23:17:28.000000000 +0000 @@ -8,11 +8,12 @@ # along with this program. If not, see . from .automatedproperties import AutomatedProperties -from .utils import job_obj_path_generate, mt_async_result, log_debug +from .utils import job_obj_path_generate, mt_async_result, mt_run_no_wait from . import cfg from .cfg import JOB_INTERFACE import dbus import threading +# noinspection PyUnresolvedReferences from gi.repository import GLib @@ -179,9 +180,15 @@ def Complete(self): return dbus.Boolean(self.state.Complete) + @staticmethod + def _signal_complete(obj): + obj.PropertiesChanged( + JOB_INTERFACE, dict(Complete=dbus.Boolean(obj.state.Complete)), []) + @Complete.setter def Complete(self, value): self.state.Complete = value + mt_run_no_wait(Job._signal_complete, self) @property def GetError(self): diff -Nru lvm2-2.02.167/daemons/lvmdbusd/lvm_shell_proxy.py lvm2-2.02.168/daemons/lvmdbusd/lvm_shell_proxy.py --- lvm2-2.02.167/daemons/lvmdbusd/lvm_shell_proxy.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/lvm_shell_proxy.py 2016-11-30 23:17:28.000000000 +0000 @@ -42,59 +42,81 @@ class LVMShellProxy(object): - def _read_until_prompt(self): + + @staticmethod + def _read(stream): + tmp = stream.read() + if tmp: + return tmp.decode("utf-8") + return '' + + # Read until we get prompt back and a result + # @param: no_output Caller expects no output to report FD + # Returns stdout, report, stderr (report is JSON!) + def _read_until_prompt(self, no_output=False): stdout = "" report = "" stderr = "" + keep_reading = True + extra_passes = 3 + report_json = {} + prev_report_len = 0 # Try reading from all FDs to prevent one from filling up and causing - # a hang. We are also assuming that we won't get the lvm prompt back - # until we have already received all the output from stderr and the - # report descriptor too. - while not stdout.endswith(SHELL_PROMPT): + # 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 = [ self.lvm_shell.stdout.fileno(), - self.report_r, + self.report_stream.fileno(), self.lvm_shell.stderr.fileno()] ready = select.select(rd_fd, [], [], 2) for r in ready[0]: if r == self.lvm_shell.stdout.fileno(): - while True: - tmp = self.lvm_shell.stdout.read() - if tmp: - stdout += tmp.decode("utf-8") - else: - break - - elif r == self.report_r: - while True: - tmp = os.read(self.report_r, 16384) - if tmp: - report += tmp.decode("utf-8") - if len(tmp) != 16384: - break - else: - break - + stdout += LVMShellProxy._read(self.lvm_shell.stdout) + elif r == self.report_stream.fileno(): + report += LVMShellProxy._read(self.report_stream) elif r == self.lvm_shell.stderr.fileno(): - while True: - tmp = self.lvm_shell.stderr.read() - if tmp: - stderr += tmp.decode("utf-8") - else: - break + stderr += LVMShellProxy._read(self.lvm_shell.stderr) # Check to see if the lvm process died on us if self.lvm_shell.poll(): raise Exception(self.lvm_shell.returncode, "%s" % stderr) + if stdout.endswith(SHELL_PROMPT): + if no_output: + keep_reading = False + else: + cur_report_len = len(report) + if cur_report_len != 0: + # Only bother to parse if we have more data + if prev_report_len != cur_report_len: + prev_report_len = cur_report_len + # Parse the JSON if it's good we are done, + # if not we will try to read some more. + try: + report_json = json.loads(report) + keep_reading = False + except ValueError: + pass + + 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)) pass - return stdout, report, stderr + return stdout, report_json, stderr def _write_cmd(self, cmd): cmd_bytes = bytes(cmd, "utf-8") @@ -102,6 +124,11 @@ assert (num_written == len(cmd_bytes)) self.lvm_shell.stdin.flush() + @staticmethod + def _make_non_block(stream): + flags = fcntl(stream, F_GETFL) + fcntl(stream, F_SETFL, flags | os.O_NONBLOCK) + def __init__(self): # Create a temp directory @@ -114,7 +141,10 @@ except FileExistsError: pass - self.report_r = os.open(tmp_file, os.O_NONBLOCK) + # 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) # Setup the environment for using our own socket for reporting local_env = copy.deepcopy(os.environ) @@ -125,9 +155,6 @@ # when utilizing the lvm shell. local_env["LVM_LOG_FILE_MAX_LINES"] = "0" - flags = fcntl(self.report_r, F_GETFL) - fcntl(self.report_r, F_SETFL, flags | os.O_NONBLOCK) - # run the lvm shell self.lvm_shell = subprocess.Popen( [LVM_CMD + " 32>%s" % tmp_file], @@ -135,20 +162,18 @@ stderr=subprocess.PIPE, close_fds=True, shell=True) try: - flags = fcntl(self.lvm_shell.stdout, F_GETFL) - fcntl(self.lvm_shell.stdout, F_SETFL, flags | os.O_NONBLOCK) - flags = fcntl(self.lvm_shell.stderr, F_GETFL) - fcntl(self.lvm_shell.stderr, F_SETFL, flags | os.O_NONBLOCK) + LVMShellProxy._make_non_block(self.lvm_shell.stdout) + LVMShellProxy._make_non_block(self.lvm_shell.stderr) # wait for the first prompt - errors = self._read_until_prompt()[2] + 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 can be - # sure to clean up correctly no matter how we finish + # 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) @@ -157,33 +182,24 @@ self._write_cmd('lastlog\n') # read everything from the STDOUT to the next prompt - stdout, report, stderr = self._read_until_prompt() + 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 + for log_entry in report_json['log']: + if log_entry['log_type'] == "error": + if error_msg: + error_msg += ', ' + log_entry['log_message'] + else: + error_msg = log_entry['log_message'] - try: - log = json.loads(report) + return error_msg - if 'log' in log: - error_msg = "" - # Walk the entire log array and build an error string - for log_entry in log['log']: - if log_entry['log_type'] == "error": - if error_msg: - error_msg += ', ' + log_entry['log_message'] - else: - error_msg = log_entry['log_message'] - - return error_msg - - return 'No error reason provided! (missing "log" section)' - except ValueError: - log_error("Invalid JSON returned from LVM") - log_error("BEGIN>>\n%s\n< 0: - _discard_pending_refreshes() - - if num_refreshes > 1: - log_debug( - "Inspect method %s for too many refreshes" % - (str(req.method))) log_debug("Method complete ") except queue.Empty: pass @@ -93,6 +54,14 @@ utils.log_error("process_request exception: \n%s" % st) +def check_bb_size(value): + v = int(value) + if v < 0: + raise argparse.ArgumentTypeError( + "positive integers only ('%s' invalid)" % value) + return v + + def main(): start = time.time() # Add simple command line handling @@ -115,6 +84,12 @@ help="Use the lvm shell, not fork & exec lvm", default=False, dest='use_lvm_shell') + parser.add_argument( + "--blackboxsize", + help="Size of the black box flight recorder, 0 to disable", + default=10, + type=check_bb_size, + dest='bb_size') use_session = os.getenv('LVMDBUSD_USE_SESSION', False) @@ -123,12 +98,15 @@ cfg.args = parser.parse_args() + # We create a flight recorder in cmdhandler too, but we replace it here + # as the user may be specifying a different size. The default one in + # cmdhandler is for when we are running other code with a different main. + cfg.blackbox = LvmFlightRecorder(cfg.args.bb_size) + if cfg.args.use_lvm_shell and not cfg.args.use_json: log_error("You cannot specify --lvmshell and --nojson") sys.exit(1) - cmdhandler.set_execution(cfg.args.use_lvm_shell) - # List of threads that we start up thread_list = [] @@ -142,30 +120,37 @@ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) dbus.mainloop.glib.threads_init() + cmdhandler.set_execution(cfg.args.use_lvm_shell) + if use_session: cfg.bus = dbus.SessionBus() else: cfg.bus = dbus.SystemBus() # The base name variable needs to exist for things to work. # noinspection PyUnusedLocal - base_name = dbus.service.BusName(BASE_INTERFACE, cfg.bus) + base_name = dbus.service.BusName(BUS_NAME, cfg.bus) cfg.om = Lvm(BASE_OBJ_PATH) cfg.om.register_object(Manager(MANAGER_OBJ_PATH)) - cfg.load = load - cfg.db = lvmdb.DataStore(cfg.args.use_json) # Using a thread to process requests, we cannot hang the dbus library # thread that is handling the dbus interface thread_list.append(threading.Thread(target=process_request)) - cfg.load(refresh=False, emit_signal=False, need_main_thread=False) + # Have a single thread handling updating lvm and the dbus model so we + # don't have multiple threads doing this as the same time + updater = StateUpdate() + thread_list.append(updater.thread) + + cfg.load = updater.load + cfg.event = updater.event + cfg.loop = GLib.MainLoop() - for process in thread_list: - process.damon = True - process.start() + for thread in thread_list: + thread.damon = True + thread.start() # Add udev watching if cfg.args.use_udev: @@ -187,8 +172,8 @@ cfg.loop.run() udevwatch.remove() - for process in thread_list: - process.join() + for thread in thread_list: + thread.join() except KeyboardInterrupt: utils.handler(signal.SIGINT, None) return 0 diff -Nru lvm2-2.02.167/daemons/lvmdbusd/Makefile.in lvm2-2.02.168/daemons/lvmdbusd/Makefile.in --- lvm2-2.02.167/daemons/lvmdbusd/Makefile.in 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/Makefile.in 2016-11-30 23:17:28.000000000 +0000 @@ -33,7 +33,6 @@ manager.py \ objectmanager.py \ pv.py \ - refresh.py \ request.py \ state.py \ udevwatch.py \ diff -Nru lvm2-2.02.167/daemons/lvmdbusd/manager.py lvm2-2.02.168/daemons/lvmdbusd/manager.py --- lvm2-2.02.167/daemons/lvmdbusd/manager.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/manager.py 2016-11-30 23:17:28.000000000 +0000 @@ -14,9 +14,7 @@ import dbus from . import cfg from . import cmdhandler -from .fetch import load_pvs, load_vgs from .request import RequestEntry -from .refresh import event_add from . import udevwatch @@ -160,16 +158,24 @@ return p return '/' + @staticmethod + def _use_lvm_shell(yes_no): + return dbus.Boolean(cmdhandler.set_execution(yes_no)) + @dbus.service.method( dbus_interface=MANAGER_INTERFACE, - in_signature='b', out_signature='b') - def UseLvmShell(self, yes_no): + in_signature='b', out_signature='b', + async_callbacks=('cb', 'cbe')) + def UseLvmShell(self, yes_no, cb, cbe): """ Allow the client to enable/disable lvm shell, used for testing :param yes_no: + :param cb: dbus python call back parameter, not client visible + :param cbe: dbus python error call back parameter, not client visible :return: Nothing """ - return dbus.Boolean(cmdhandler.set_execution(yes_no)) + r = RequestEntry(-1, Manager._use_lvm_shell, (yes_no,), cb, cbe, False) + cfg.worker_q.put(r) @dbus.service.method( dbus_interface=MANAGER_INTERFACE, @@ -183,7 +189,8 @@ "udev monitoring") # We are dependent on external events now to stay current! cfg.ee = True - event_add((command,)) + utils.log_debug("ExternalEvent %s" % command) + cfg.event() return dbus.Int32(0) @staticmethod diff -Nru lvm2-2.02.167/daemons/lvmdbusd/pv.py lvm2-2.02.168/daemons/lvmdbusd/pv.py --- lvm2-2.02.167/daemons/lvmdbusd/pv.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/pv.py 2016-11-30 23:17:28.000000000 +0000 @@ -18,7 +18,7 @@ from .loader import common from .request import RequestEntry from .state import State -from .utils import round_size, mt_remove_dbus_objects +from .utils import round_size # noinspection PyUnusedLocal @@ -140,7 +140,7 @@ if dbo: rc, out, err = cmdhandler.pv_remove(pv_name, remove_options) if rc == 0: - mt_remove_dbus_objects((dbo,)) + cfg.load() else: # Need to work on error handling, need consistent raise dbus.exceptions.DBusException( diff -Nru lvm2-2.02.167/daemons/lvmdbusd/refresh.py lvm2-2.02.168/daemons/lvmdbusd/refresh.py --- lvm2-2.02.167/daemons/lvmdbusd/refresh.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/refresh.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved. -# -# This copyrighted material is made available to anyone wishing to use, -# modify, copy, or redistribute it subject to the terms and conditions -# of the GNU General Public License v.2. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Try and minimize the refreshes we do. - -import threading -from .request import RequestEntry -from . import cfg -from . import utils - -_rlock = threading.RLock() -_count = 0 - - -def handle_external_event(command): - utils.log_debug("External event: '%s'" % command) - event_complete() - cfg.load() - - -def event_add(params): - global _rlock - global _count - with _rlock: - if _count == 0: - _count += 1 - r = RequestEntry( - -1, handle_external_event, - params, None, None, False) - cfg.worker_q.put(r) - - -def event_complete(): - global _rlock - global _count - with _rlock: - if _count > 0: - _count -= 1 - return _count diff -Nru lvm2-2.02.167/daemons/lvmdbusd/request.py lvm2-2.02.168/daemons/lvmdbusd/request.py --- lvm2-2.02.167/daemons/lvmdbusd/request.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/request.py 2016-11-30 23:17:28.000000000 +0000 @@ -126,7 +126,6 @@ mt_async_result(self.cb_error, error_exception) else: # We have a job and it's complete, indicate that it's done. - # TODO: We need to signal the job is done too. self._job.Complete = True self._job = None diff -Nru lvm2-2.02.167/daemons/lvmdbusd/udevwatch.py lvm2-2.02.168/daemons/lvmdbusd/udevwatch.py --- lvm2-2.02.167/daemons/lvmdbusd/udevwatch.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/udevwatch.py 2016-11-30 23:17:28.000000000 +0000 @@ -9,7 +9,6 @@ import pyudev import threading -from .refresh import event_add from . import cfg observer = None @@ -38,7 +37,7 @@ refresh = True if refresh: - event_add(('udev',)) + cfg.event() def add(): diff -Nru lvm2-2.02.167/daemons/lvmdbusd/utils.py lvm2-2.02.168/daemons/lvmdbusd/utils.py --- lvm2-2.02.167/daemons/lvmdbusd/utils.py 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmdbusd/utils.py 2016-11-30 23:17:28.000000000 +0000 @@ -17,6 +17,7 @@ import dbus from lvmdbusd import cfg +# noinspection PyUnresolvedReferences from gi.repository import GLib import threading @@ -508,11 +509,17 @@ log_debug('Results = %s' % str(results)) call_back(results) + # Return result in main thread def mt_async_result(call_back, results): GLib.idle_add(_async_result, call_back, results) +# Take the supplied function and run it on the main thread and not wait for +# a result! +def mt_run_no_wait(function, param): + GLib.idle_add(function, param) + # Run the supplied function and arguments on the main thread and wait for them # to complete while allowing the ability to get the return value too. # @@ -523,6 +530,7 @@ @staticmethod def runner(obj): + # noinspection PyProtectedMember obj._run() with obj.cond: obj.function_complete = True diff -Nru lvm2-2.02.167/daemons/lvmpolld/lvmpolld-data-utils.c lvm2-2.02.168/daemons/lvmpolld/lvmpolld-data-utils.c --- lvm2-2.02.167/daemons/lvmpolld/lvmpolld-data-utils.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/daemons/lvmpolld/lvmpolld-data-utils.c 2016-11-30 23:17:28.000000000 +0000 @@ -19,6 +19,8 @@ #include #include +static const char LVM_SYSTEM_DIR[] = "LVM_SYSTEM_DIR="; + static char *_construct_full_lvname(const char *vgname, const char *lvname) { char *name; @@ -52,7 +54,7 @@ *env = '\0'; - if (sysdir && dm_snprintf(env, l, "LVM_SYSTEM_DIR=%s", sysdir) < 0) { + if (sysdir && dm_snprintf(env, l, "%s%s", LVM_SYSTEM_DIR, sysdir) < 0) { dm_free(env); env = NULL; } @@ -259,8 +261,8 @@ buffer_append(buff, tmp); if (dm_snprintf(tmp, sizeof(tmp), "\t\tlvm_command_interval=\"%s\"\n", pdlv->sinterval ?: "") > 0) buffer_append(buff, tmp); - if (dm_snprintf(tmp, sizeof(tmp), "\t\tLVM_SYSTEM_DIR=\"%s\"\n", - (*pdlv->lvm_system_dir_env ? (pdlv->lvm_system_dir_env + strlen("LVM_SYSTEM_DIR=")) : "")) > 0) + if (dm_snprintf(tmp, sizeof(tmp), "\t\t%s\"%s\"\n", LVM_SYSTEM_DIR, + (*pdlv->lvm_system_dir_env ? (pdlv->lvm_system_dir_env + (sizeof(LVM_SYSTEM_DIR) - 1)) : "")) > 0) buffer_append(buff, tmp); if (dm_snprintf(tmp, sizeof(tmp), "\t\tlvm_command_pid=%d\n", pdlv->cmd_pid) > 0) buffer_append(buff, tmp); diff -Nru lvm2-2.02.167/daemons/Makefile.in lvm2-2.02.168/daemons/Makefile.in --- lvm2-2.02.167/daemons/Makefile.in 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/daemons/Makefile.in 2016-11-30 23:17:28.000000000 +0000 @@ -41,11 +41,11 @@ endif ifeq ("@BUILD_LVMLOCKD@", "yes") - SUBDIRS += lvmlockd + SUBDIRS += lvmlockd endif ifeq ("@BUILD_LVMDBUSD@", "yes") - SUBDIRS += lvmdbusd + SUBDIRS += lvmdbusd endif ifeq ($(MAKECMDGOALS),distclean) diff -Nru lvm2-2.02.167/debian/changelog lvm2-2.02.168/debian/changelog --- lvm2-2.02.167/debian/changelog 2017-05-04 00:14:00.000000000 +0000 +++ lvm2-2.02.168/debian/changelog 2017-05-08 23:59:53.000000000 +0000 @@ -1,3 +1,58 @@ +lvm2 (2.02.168-2ubuntu1) artful; urgency=medium + + * Merge with Debian unstable. Remaining changes: + - Add and install clvmd resource agent + - Lower libdevmapper1.02.1's Depends: dmsetup to a Recommends:. This + breaks the circular dependency that causes upgrade failures. As dmsetup + is "Priority: required", this has no other practical consequences. + - debian/control: add dmsetup-udeb to libdevmapper1.02.1-udeb recommends. + - debian/dmsetup-udeb.install: install udev rules in udebs + (Debian #504341). + - Add debian/initramfs-tools/lvm2/scripts/init-bottom/lvm2: We cannot + properly synthesize LVM LV change events with udevadm trigger, so + if we use LVM, we need to let it finish; otherwise we get missing LV + symlinks. + - Add debian/initramfs-tools/lvm2/scripts/init-premount/lvm2: failure + hooks to help fix bad boots (Debian #468115) + - Do not start lvmetad when inside a container. + - Add enable-issue-discards.patch: Enable "issue_discards" option by + default to trim SSDs when changing PVs. This option has no effect if the + kernel or the drive does not support trimming, so it's safe to enable by + default. (Debian #717313) + - debian/rules: + + Copy .po file to .pot file for Rosetta (Ubuntu specific). + - debian/initramfs-tools/lvm2/hooks/lvm2: depend on udev since + we ship udev rules. + - debian/clvm.maintscripts: Drop the /etc/default/clvm conffile on + upgrade. This delta can be dropped after 18.04 release. + - Add a patch to fix crashes on 32bit platforms: + + 0013-fix-lvmetad-32bit.patch + [ patch renamed ] + - d/p/fix-strips-limit.patch: Fix regression limiting number of + stripes to 8 (LP #1675770) + [ patch refreshed ] + + [ Balint Reczey ] + * Do not start lvm2-monitor in containers (LP #1576341) + [ patch renamed ] + + -- Nishanth Aravamudan Mon, 08 May 2017 16:59:53 -0700 + +lvm2 (2.02.168-2) unstable; urgency=medium + + * Don't try to disable cluster locking on clvm purge. (closes: #856696) + * Drop symlinks for private libs. (closes: #857954) + * Deny writemostly/writebehind during raid1 resync. (closes: #855895) + + -- Bastian Blank Fri, 17 Mar 2017 17:29:47 +0100 + +lvm2 (2.02.168-1) unstable; urgency=medium + + * New upstream release. + * Install but not start cmirrord. (closes: #570232) + + -- Bastian Blank Fri, 16 Dec 2016 15:29:17 +0100 + lvm2 (2.02.167-1ubuntu6) artful; urgency=medium * Drop: @@ -2701,3 +2756,4 @@ -- Andres Salomon Wed, 20 Feb 2002 03:17:25 -0500 + diff -Nru lvm2-2.02.167/debian/clvm.install lvm2-2.02.168/debian/clvm.install --- lvm2-2.02.167/debian/clvm.install 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/clvm.install 2017-05-08 23:55:13.000000000 +0000 @@ -1,6 +1,9 @@ lib/systemd/lvm2-cluster* lib/systemd/system/lvm2-cluster* lib/systemd/system/lvm2-clvmd* +lib/systemd/system/lvm2-cmirrord* usr/sbin/clvmd +usr/sbin/cmirrord usr/share/man/man8/clvmd* +usr/share/man/man8/cmirrord* usr/lib/ocf/resource.d/lvm2/clvmd diff -Nru lvm2-2.02.167/debian/clvm.prerm lvm2-2.02.168/debian/clvm.prerm --- lvm2-2.02.167/debian/clvm.prerm 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/clvm.prerm 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#!/bin/sh - -set -e - -case "$1" in - remove) - lvmconf --disable-cluster - ;; -esac - -#DEBHELPER# - -exit 0 diff -Nru lvm2-2.02.167/debian/.git-dpm lvm2-2.02.168/debian/.git-dpm --- lvm2-2.02.167/debian/.git-dpm 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/.git-dpm 2017-05-08 23:47:21.000000000 +0000 @@ -1,8 +1,8 @@ # see git-dpm(1) from git-dpm package -91d4c2e7d57d50e2401648b660fe6b2f9bdaf1d1 -91d4c2e7d57d50e2401648b660fe6b2f9bdaf1d1 -afed491aaa558a1d2940f31500a19a47fc293e3a -afed491aaa558a1d2940f31500a19a47fc293e3a -lvm2_2.02.167.orig.tar.xz -176ed47e4961df2d2586aa0fe217be1181617833 -1558928 +27e1059ec6e67a4ac0faaf0f53cd086ac4ed0e35 +27e1059ec6e67a4ac0faaf0f53cd086ac4ed0e35 +25e563d1362762aaecaea177d69fe560748aa40b +25e563d1362762aaecaea177d69fe560748aa40b +lvm2_2.02.168.orig.tar.xz +8f3feb1c7db077a5dcdbdb71b2471319f023dacd +1562080 diff -Nru lvm2-2.02.167/debian/libdevmapper-dev.install lvm2-2.02.168/debian/libdevmapper-dev.install --- lvm2-2.02.167/debian/libdevmapper-dev.install 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/libdevmapper-dev.install 2017-05-08 23:47:21.000000000 +0000 @@ -1,3 +1,5 @@ usr/include/libdevmapper* -usr/lib/*/libdevmapper*.so -usr/lib/*/pkgconfig/devmapper* +usr/lib/*/libdevmapper.so +usr/lib/*/libdevmapper-event.so +usr/lib/*/pkgconfig/devmapper.pc +usr/lib/*/pkgconfig/devmapper-event.pc diff -Nru lvm2-2.02.167/debian/patches/0001-install.patch lvm2-2.02.168/debian/patches/0001-install.patch --- lvm2-2.02.167/debian/patches/0001-install.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0001-install.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From b91bc878fffbfbaca131dfae5052ae1e5bd963db Mon Sep 17 00:00:00 2001 +From c039196cf14088a3d34a87c79ac9068728086c2d Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:04 +0200 Subject: install @@ -8,7 +8,7 @@ 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/make.tmpl.in b/make.tmpl.in -index d418cfb..a78ef08 100644 +index d418cfba2..a78ef0857 100644 --- a/make.tmpl.in +++ b/make.tmpl.in @@ -17,20 +17,10 @@ SHELL = /bin/sh diff -Nru lvm2-2.02.167/debian/patches/0002-libs-cleanup.patch lvm2-2.02.168/debian/patches/0002-libs-cleanup.patch --- lvm2-2.02.167/debian/patches/0002-libs-cleanup.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0002-libs-cleanup.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 8ec4e01f96c0d0c599b2a64784c8b6c5cf9774d7 Mon Sep 17 00:00:00 2001 +From 8826ff3faa77992cc5016650001ee4c2da438b4a Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:05 +0200 Subject: libs-cleanup @@ -8,7 +8,7 @@ 1 file changed, 7 insertions(+), 60 deletions(-) diff --git a/configure.in b/configure.in -index cc77aab..f67f004 100644 +index cc77aaba9..f67f00434 100644 --- a/configure.in +++ b/configure.in @@ -668,7 +668,7 @@ dnl -- Disable readline diff -Nru lvm2-2.02.167/debian/patches/0003-dirs.patch lvm2-2.02.168/debian/patches/0003-dirs.patch --- lvm2-2.02.167/debian/patches/0003-dirs.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0003-dirs.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From d5aafeff99b728811033372670cf7575dbb98bc7 Mon Sep 17 00:00:00 2001 +From b37895a4dedbc165d845214f614abc0dc7a17255 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:07 +0200 Subject: dirs @@ -9,7 +9,7 @@ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/conf/example.conf.in b/conf/example.conf.in -index b1a2a9c..736b4bd 100644 +index b1a2a9c54..736b4bd88 100644 --- a/conf/example.conf.in +++ b/conf/example.conf.in @@ -158,7 +158,7 @@ devices { @@ -22,7 +22,7 @@ # Configuration option devices/cache_file_prefix. # A prefix used before the .cache file name. See devices/cache_dir. diff --git a/lib/config/config.c b/lib/config/config.c -index 6ad04e5..3c57542 100644 +index 3e309510f..d5a5e3c8e 100644 --- a/lib/config/config.c +++ b/lib/config/config.c @@ -2344,10 +2344,8 @@ const char *get_default_devices_cache_CFG(struct cmd_context *cmd, struct profil diff -Nru lvm2-2.02.167/debian/patches/0004-force-paths.patch lvm2-2.02.168/debian/patches/0004-force-paths.patch --- lvm2-2.02.167/debian/patches/0004-force-paths.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0004-force-paths.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 424b1a7c04f26a4111b62ec4b6414ffcac6027df Mon Sep 17 00:00:00 2001 +From ea980746dd4908458bfbe6731a280b0f7b7624b5 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:08 +0200 Subject: force-paths @@ -8,7 +8,7 @@ 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/configure.in b/configure.in -index f67f004..48f4bf7 100644 +index f67f00434..48f4bf753 100644 --- a/configure.in +++ b/configure.in @@ -1799,11 +1799,7 @@ if test "$UDEV_SYNC" = yes; then diff -Nru lvm2-2.02.167/debian/patches/0005-implicit-pointer.patch lvm2-2.02.168/debian/patches/0005-implicit-pointer.patch --- lvm2-2.02.167/debian/patches/0005-implicit-pointer.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0005-implicit-pointer.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 44cb87a7960f3aac7da77530b39094520dbaa18a Mon Sep 17 00:00:00 2001 +From 13afa44df10ab529ac41b26a12218acf59577877 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:09 +0200 Subject: implicit-pointer @@ -8,7 +8,7 @@ 1 file changed, 4 deletions(-) diff --git a/tools/lvm.c b/tools/lvm.c -index b3af020..21fb753 100644 +index b3af0206b..21fb753ca 100644 --- a/tools/lvm.c +++ b/tools/lvm.c @@ -26,10 +26,6 @@ int main(int argc, char **argv) diff -Nru lvm2-2.02.167/debian/patches/0006-dm-event-api.patch lvm2-2.02.168/debian/patches/0006-dm-event-api.patch --- lvm2-2.02.167/debian/patches/0006-dm-event-api.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0006-dm-event-api.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 9bc012aeeb56137f18aff033620a4d8f16a2e28d Mon Sep 17 00:00:00 2001 +From e4009bd1efcd6a8eca9d6546c5eb674f2ad17f10 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:10 +0200 Subject: dm-event-api @@ -10,7 +10,7 @@ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/daemons/dmeventd/.exported_symbols b/daemons/dmeventd/.exported_symbols -index fab74dc..46c14fb 100644 +index fab74dc1d..46c14fb5a 100644 --- a/daemons/dmeventd/.exported_symbols +++ b/daemons/dmeventd/.exported_symbols @@ -1,4 +1,4 @@ @@ -22,7 +22,7 @@ +dm_event_daemon_talk dm_event_get_version diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c -index 58922ac..1565b80 100644 +index 58922ac84..1565b8063 100644 --- a/daemons/dmeventd/dmeventd.c +++ b/daemons/dmeventd/dmeventd.c @@ -1967,7 +1967,7 @@ static int _reinstate_registrations(struct dm_event_fifos *fifos) @@ -110,7 +110,7 @@ } diff --git a/daemons/dmeventd/libdevmapper-event.c b/daemons/dmeventd/libdevmapper-event.c -index b23b6c1..6f7af9e 100644 +index b23b6c152..6f7af9e15 100644 --- a/daemons/dmeventd/libdevmapper-event.c +++ b/daemons/dmeventd/libdevmapper-event.c @@ -341,7 +341,7 @@ static int _daemon_write(struct dm_event_fifos *fifos, diff -Nru lvm2-2.02.167/debian/patches/0007-udev.patch lvm2-2.02.168/debian/patches/0007-udev.patch --- lvm2-2.02.167/debian/patches/0007-udev.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0007-udev.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 3ec025fa1c55abce5cbb2620ffc3e525719dca5f Mon Sep 17 00:00:00 2001 +From 880999303a52620db0e1c1a7ddb8673c0ad1821b Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:11 +0200 Subject: udev @@ -11,7 +11,7 @@ 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/udev/10-dm.rules.in b/udev/10-dm.rules.in -index b4fa52a..49111ec 100644 +index b4fa52ab7..49111ecbd 100644 --- a/udev/10-dm.rules.in +++ b/udev/10-dm.rules.in @@ -12,7 +12,6 @@ @@ -87,7 +87,7 @@ ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/$env{DM_NAME}" diff --git a/udev/11-dm-lvm.rules.in b/udev/11-dm-lvm.rules.in -index 91cb991..0894893 100644 +index 91cb991df..089489321 100644 --- a/udev/11-dm-lvm.rules.in +++ b/udev/11-dm-lvm.rules.in @@ -14,7 +14,7 @@ @@ -100,7 +100,7 @@ # Use DM name and split it up into its VG/LV/layer constituents. diff --git a/udev/13-dm-disk.rules.in b/udev/13-dm-disk.rules.in -index 4b64dd6..b5cc790 100644 +index 4b64dd69e..b5cc790c3 100644 --- a/udev/13-dm-disk.rules.in +++ b/udev/13-dm-disk.rules.in @@ -11,7 +11,7 @@ @@ -113,7 +113,7 @@ SYMLINK+="disk/by-id/dm-name-$env{DM_NAME}" diff --git a/udev/Makefile.in b/udev/Makefile.in -index cb968df..04e2338 100644 +index cb968dfe1..04e233842 100644 --- a/udev/Makefile.in +++ b/udev/Makefile.in @@ -17,10 +17,10 @@ top_builddir = @top_builddir@ diff -Nru lvm2-2.02.167/debian/patches/0008-systemd.patch lvm2-2.02.168/debian/patches/0008-systemd.patch --- lvm2-2.02.167/debian/patches/0008-systemd.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0008-systemd.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 2bbe305741c0dc4f1968aa48d4a56f5dfbcb5f82 Mon Sep 17 00:00:00 2001 +From cf4fe36f0b453ac0efd569b94bff22a2493f3a08 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:12 +0200 Subject: systemd @@ -10,7 +10,7 @@ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/lvm2_activation_generator_systemd_red_hat.c b/scripts/lvm2_activation_generator_systemd_red_hat.c -index 0f7f89c..269edd3 100644 +index 0f7f89c86..269edd32d 100644 --- a/scripts/lvm2_activation_generator_systemd_red_hat.c +++ b/scripts/lvm2_activation_generator_systemd_red_hat.c @@ -131,7 +131,7 @@ static int generate_unit(const char *dir, int unit, int sysinit_needed) @@ -23,7 +23,7 @@ if (unit == UNIT_EARLY) { fputs("After=systemd-udev-settle.service\n" diff --git a/scripts/lvm2_cluster_activation_systemd_red_hat.service.in b/scripts/lvm2_cluster_activation_systemd_red_hat.service.in -index 970e93a..5f8b415 100644 +index 970e93ad3..5f8b4159d 100644 --- a/scripts/lvm2_cluster_activation_systemd_red_hat.service.in +++ b/scripts/lvm2_cluster_activation_systemd_red_hat.service.in @@ -9,7 +9,7 @@ Conflicts=shutdown.target @@ -36,7 +36,7 @@ ExecStop=@systemdutildir@/lvm2-cluster-activation deactivate diff --git a/scripts/lvm2_clvmd_systemd_red_hat.service.in b/scripts/lvm2_clvmd_systemd_red_hat.service.in -index f506fa8..ddf9853 100644 +index f506fa87f..ddf985303 100644 --- a/scripts/lvm2_clvmd_systemd_red_hat.service.in +++ b/scripts/lvm2_clvmd_systemd_red_hat.service.in @@ -13,8 +13,8 @@ Conflicts=shutdown.target diff -Nru lvm2-2.02.167/debian/patches/0009-clvmd-openais-format.patch lvm2-2.02.168/debian/patches/0009-clvmd-openais-format.patch --- lvm2-2.02.167/debian/patches/0009-clvmd-openais-format.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0009-clvmd-openais-format.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 6f5388d728987fe67e7b4deb20c10370c7f3a4fa Mon Sep 17 00:00:00 2001 +From d0da93ac31f93beda01cb090a5cca71e674cdd71 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 30 Jun 2015 11:46:13 +0200 Subject: clvmd-openais-format @@ -8,7 +8,7 @@ 1 file changed, 1 insertion(+) diff --git a/daemons/clvmd/clvmd-openais.c b/daemons/clvmd/clvmd-openais.c -index 2f1a4fd..6194994 100644 +index 2f1a4fdeb..619499420 100644 --- a/daemons/clvmd/clvmd-openais.c +++ b/daemons/clvmd/clvmd-openais.c @@ -34,6 +34,7 @@ diff -Nru lvm2-2.02.167/debian/patches/0011-fix-lvmetad-32bit.patch lvm2-2.02.168/debian/patches/0011-fix-lvmetad-32bit.patch --- lvm2-2.02.167/debian/patches/0011-fix-lvmetad-32bit.patch 2017-03-27 08:25:05.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0011-fix-lvmetad-32bit.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -From 5d7407119bc7289ada84de819651d27a187e76c3 Mon Sep 17 00:00:00 2001 -From: Christian Brauner -Date: Fri, 10 Mar 2017 19:57:53 +0100 -Subject: [PATCH] make sure we send correctly aligned int - -Signed-off-by: Christian Brauner ---- - lib/cache/lvmetad.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c -index 8e9bb1fd3..843e1c3e8 100644 ---- a/lib/cache/lvmetad.c -+++ b/lib/cache/lvmetad.c -@@ -1304,7 +1304,7 @@ int lvmetad_vg_remove_pending(struct volume_group *vg) - reply = _lvmetad_send(vg->cmd, "set_vg_info", - "name = %s", vg->name, - "uuid = %s", uuid, -- "version = %d", 0, -+ "version = %"PRId64, (int64_t)0, - NULL); - - if (!_lvmetad_handle_reply(reply, "set_vg_info", vg->name, NULL)) { --- -2.11.0 diff -Nru lvm2-2.02.167/debian/patches/0012-lvchange-reject-writemostly-writebehind-on-raid1-dur.patch lvm2-2.02.168/debian/patches/0012-lvchange-reject-writemostly-writebehind-on-raid1-dur.patch --- lvm2-2.02.167/debian/patches/0012-lvchange-reject-writemostly-writebehind-on-raid1-dur.patch 1970-01-01 00:00:00.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0012-lvchange-reject-writemostly-writebehind-on-raid1-dur.patch 2017-05-08 23:47:21.000000000 +0000 @@ -0,0 +1,146 @@ +From 27e1059ec6e67a4ac0faaf0f53cd086ac4ed0e35 Mon Sep 17 00:00:00 2001 +From: Heinz Mauelshagen +Date: Thu, 23 Feb 2017 15:09:29 +0100 +Subject: lvchange: reject writemostly/writebehind on raid1 during resync + +The MD kernel raid1 personality does no use any writemostly leg as the primary. + +In case a previous linear LV holding data gets upconverted to +raid1 it becomes the primary leg of the new raid1 LV and a full +resynchronization is started to update the new legs. + +No writemostly and/or writebehind setting may be allowed during +this initial, full synchronization period of this new raid1 LV +(using the lvchange(8) command), because that would change the +primary (i.e the previous linear LV) thus causing data loss. + +lvchange has a bug not preventing this scenario. + +Fix rejects setting writemostly and/or writebehind on resychronizing raid1 LVs. + +Once we have status in the lvm2 metadata about the linear -> raid upconversion, +we may relax this constraint for other types of resynchronization +(e.g. for user requested "lvchange --resync "). + +New lvchange-raid1-writemostly.sh test is added to the test suite. + +Resolves: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=855895 +--- + lib/metadata/metadata-exported.h | 1 + + lib/metadata/raid_manip.c | 8 ++++++- + test/shell/lvchange-raid1-writemostly.sh | 41 ++++++++++++++++++++++++++++++++ + tools/lvchange.c | 15 ++++++++++++ + 4 files changed, 64 insertions(+), 1 deletion(-) + create mode 100644 test/shell/lvchange-raid1-writemostly.sh + +diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h +index cdd4984c1..080073925 100644 +--- a/lib/metadata/metadata-exported.h ++++ b/lib/metadata/metadata-exported.h +@@ -1212,6 +1212,7 @@ int lv_raid_replace(struct logical_volume *lv, int force, + struct dm_list *remove_pvs, struct dm_list *allocate_pvs); + int lv_raid_remove_missing(struct logical_volume *lv); + int partial_raid_lv_supports_degraded_activation(const struct logical_volume *lv); ++int lv_raid_in_sync(const struct logical_volume *lv); + /* -- metadata/raid_manip.c */ + + /* ++ metadata/cache_manip.c */ +diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c +index 7e591e988..00e5551a3 100644 +--- a/lib/metadata/raid_manip.c ++++ b/lib/metadata/raid_manip.c +@@ -268,7 +268,7 @@ static int _deactivate_and_remove_lvs(struct volume_group *vg, struct dm_list *r + * Returns: 1 if in-sync, 0 otherwise. + */ + #define _RAID_IN_SYNC_RETRIES 6 +-static int _raid_in_sync(struct logical_volume *lv) ++static int _raid_in_sync(const struct logical_volume *lv) + { + int retries = _RAID_IN_SYNC_RETRIES; + dm_percent_t sync_percent; +@@ -299,6 +299,12 @@ static int _raid_in_sync(struct logical_volume *lv) + return (sync_percent == DM_PERCENT_100) ? 1 : 0; + } + ++/* External interface to raid in-sync check */ ++int lv_raid_in_sync(const struct logical_volume *lv) ++{ ++ return _raid_in_sync(lv); ++} ++ + /* Check if RaidLV @lv is synced or any raid legs of @lv are not synced */ + static int _raid_devs_sync_healthy(struct logical_volume *lv) + { +diff --git a/test/shell/lvchange-raid1-writemostly.sh b/test/shell/lvchange-raid1-writemostly.sh +new file mode 100644 +index 000000000..edf11bd4e +--- /dev/null ++++ b/test/shell/lvchange-raid1-writemostly.sh +@@ -0,0 +1,41 @@ ++#!/bin/sh ++# Copyright (C) 2017 Red Hat, Inc. All rights reserved. ++# ++# This copyrighted material is made available to anyone wishing to use, ++# modify, copy, or redistribute it subject to the terms and conditions ++# of the GNU General Public License v.2. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software Foundation, ++# Inc., 51 Franklin Street, Fifth Floor, Boston, MA2110-1301 USA ++ ++SKIP_WITH_LVMLOCKD=1 ++SKIP_WITH_LVMPOLLD=1 ++ ++. lib/inittest ++ ++which mkfs.ext4 || skip ++aux have_raid 1 3 5 || skip ++ ++aux prepare_vg 4 ++ ++for d in $dev1 $dev2 $dev3 $dev4 ++do ++ aux delay_dev $d 1 ++done ++ ++# ++# Test writemostly prohibited on resyncrhonizing raid1 ++# ++ ++# Create 4-way striped LV ++lvcreate -aey --ty raid1 -m 3 -L 32M -n $lv1 $vg ++not lvchange -y --writemostly $dev1 $vg/$lv1 ++check lv_field $vg/$lv1 segtype "raid1" ++check lv_field $vg/$lv1 stripes 4 ++check lv_attr_bit health $vg/${lv1}_rimage_0 "-" ++aux wait_for_sync $vg $lv1 ++lvchange -y --writemostly $dev1 $vg/$lv1 ++check lv_attr_bit health $vg/${lv1}_rimage_0 "w" ++ ++vgremove -ff $vg +diff --git a/tools/lvchange.c b/tools/lvchange.c +index 250d7209b..964eb5179 100644 +--- a/tools/lvchange.c ++++ b/tools/lvchange.c +@@ -821,6 +821,21 @@ static int _lvchange_writemostly(struct logical_volume *lv) + return 0; + } + ++ /* ++ * Prohibit writebehind and writebehind during synchronization. ++ * ++ * FIXME: we can do better once we can distingush between ++ * an initial sync after a linear -> raid1 upconversion ++ * and any later additions of legs, requested resyncs ++ * via lvchange or leg repairs/replacements. ++ */ ++ if (!lv_raid_in_sync(lv)) { ++ log_error("Unable to change write%s on %s while it is not in-sync.", ++ arg_is_set(cmd, writemostly_ARG) ? "mostly" : "behind", ++ display_lvname(lv)); ++ return 0; ++ } ++ + if (arg_is_set(cmd, writebehind_ARG)) + raid_seg->writebehind = arg_uint_value(cmd, writebehind_ARG, 0); + diff -Nru lvm2-2.02.167/debian/patches/0013-fix-lvmetad-32bit.patch lvm2-2.02.168/debian/patches/0013-fix-lvmetad-32bit.patch --- lvm2-2.02.167/debian/patches/0013-fix-lvmetad-32bit.patch 1970-01-01 00:00:00.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0013-fix-lvmetad-32bit.patch 2017-05-08 23:59:32.000000000 +0000 @@ -0,0 +1,25 @@ +From 5d7407119bc7289ada84de819651d27a187e76c3 Mon Sep 17 00:00:00 2001 +From: Christian Brauner +Date: Fri, 10 Mar 2017 19:57:53 +0100 +Subject: [PATCH] make sure we send correctly aligned int + +Signed-off-by: Christian Brauner +--- + lib/cache/lvmetad.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c +index 8e9bb1fd3..843e1c3e8 100644 +--- a/lib/cache/lvmetad.c ++++ b/lib/cache/lvmetad.c +@@ -1304,7 +1304,7 @@ int lvmetad_vg_remove_pending(struct volume_group *vg) + reply = _lvmetad_send(vg->cmd, "set_vg_info", + "name = %s", vg->name, + "uuid = %s", uuid, +- "version = %d", 0, ++ "version = %"PRId64, (int64_t)0, + NULL); + + if (!_lvmetad_handle_reply(reply, "set_vg_info", vg->name, NULL)) { +-- +2.11.0 diff -Nru lvm2-2.02.167/debian/patches/0014-no-lvm2-monitor-in-containers.patch lvm2-2.02.168/debian/patches/0014-no-lvm2-monitor-in-containers.patch --- lvm2-2.02.167/debian/patches/0014-no-lvm2-monitor-in-containers.patch 1970-01-01 00:00:00.000000000 +0000 +++ lvm2-2.02.168/debian/patches/0014-no-lvm2-monitor-in-containers.patch 2017-05-08 23:59:38.000000000 +0000 @@ -0,0 +1,17 @@ +Description: Do not start lvmetad in containers +Author: Balint Reczey +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/lvm2/+bug/1576341 +Forwarded: no +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ + +--- lvm2-2.02.167.orig/scripts/lvm2_monitoring_systemd_red_hat.service.in ++++ lvm2-2.02.167/scripts/lvm2_monitoring_systemd_red_hat.service.in +@@ -6,6 +6,7 @@ After=dm-event.socket dm-event.service l + Before=local-fs-pre.target + DefaultDependencies=no + Conflicts=shutdown.target ++ConditionVirtualization=!container + + [Service] + Type=oneshot diff -Nru lvm2-2.02.167/debian/patches/fix-strips-limit.patch lvm2-2.02.168/debian/patches/fix-strips-limit.patch --- lvm2-2.02.167/debian/patches/fix-strips-limit.patch 2017-03-27 08:33:46.000000000 +0000 +++ lvm2-2.02.168/debian/patches/fix-strips-limit.patch 2017-05-08 23:59:36.000000000 +0000 @@ -17,11 +17,9 @@ Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/dpdk/+bug/1675770 Last-Update: 2017-03-27 -diff --git a/tools/lvcreate.c b/tools/lvcreate.c -index cd31c99..ed56757 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c -@@ -558,8 +558,10 @@ static int _read_mirror_and_raid_params(struct cmd_context *cmd, +@@ -559,8 +559,10 @@ else if (seg_is_any_raid6(lp)) max_images -= 2; } diff -Nru lvm2-2.02.167/debian/patches/series lvm2-2.02.168/debian/patches/series --- lvm2-2.02.167/debian/patches/series 2017-03-27 08:25:30.000000000 +0000 +++ lvm2-2.02.168/debian/patches/series 2017-05-08 23:59:38.000000000 +0000 @@ -10,6 +10,8 @@ 0010-no-metad-in-container.patch udev-md.patch systemd-pvscan-background.patch +0012-lvchange-reject-writemostly-writebehind-on-raid1-dur.patch enable-issue-discards.patch -0011-fix-lvmetad-32bit.patch +0013-fix-lvmetad-32bit.patch fix-strips-limit.patch +0014-no-lvm2-monitor-in-containers.patch diff -Nru lvm2-2.02.167/debian/patches/systemd-pvscan-background.patch lvm2-2.02.168/debian/patches/systemd-pvscan-background.patch --- lvm2-2.02.167/debian/patches/systemd-pvscan-background.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/systemd-pvscan-background.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 91d4c2e7d57d50e2401648b660fe6b2f9bdaf1d1 Mon Sep 17 00:00:00 2001 +From 17785df719bf5bd7246e6fc825f4a4daa0aae1bc Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Tue, 11 Aug 2015 22:06:54 +0200 Subject: Don't run pvscan in background @@ -9,7 +9,7 @@ 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/udev/Makefile.in b/udev/Makefile.in -index 04e2338..0b84f7f 100644 +index 04e233842..0b84f7fa3 100644 --- a/udev/Makefile.in +++ b/udev/Makefile.in @@ -48,7 +48,7 @@ endif diff -Nru lvm2-2.02.167/debian/patches/udev-md.patch lvm2-2.02.168/debian/patches/udev-md.patch --- lvm2-2.02.167/debian/patches/udev-md.patch 2017-03-27 07:16:59.000000000 +0000 +++ lvm2-2.02.168/debian/patches/udev-md.patch 2017-05-08 23:47:21.000000000 +0000 @@ -1,4 +1,4 @@ -From 5551ac0739a8a530a7e62aad6692a69dc01644ab Mon Sep 17 00:00:00 2001 +From 0d0e3b68c346bad2baa01af6cbb64aa7a25eca70 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Sun, 2 Aug 2015 10:03:28 +0200 Subject: Fix mdadm udev interaction @@ -11,7 +11,7 @@ 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/udev/69-dm-lvm-metad.rules.in b/udev/69-dm-lvm-metad.rules.in -index bd75fc8..9318e2a 100644 +index bd75fc8ef..9318e2ae6 100644 --- a/udev/69-dm-lvm-metad.rules.in +++ b/udev/69-dm-lvm-metad.rules.in @@ -19,6 +19,11 @@ SUBSYSTEM!="block", GOTO="lvm_end" diff -Nru lvm2-2.02.167/debian/rules lvm2-2.02.168/debian/rules --- lvm2-2.02.167/debian/rules 2017-03-27 08:24:35.000000000 +0000 +++ lvm2-2.02.168/debian/rules 2017-05-08 23:55:13.000000000 +0000 @@ -89,6 +89,7 @@ --enable-applib \ --enable-blkid_wiping \ --enable-cmdlib \ + --enable-cmirrord \ --enable-dmeventd \ --enable-lvmetad \ --enable-lvmpolld \ diff -Nru lvm2-2.02.167/lib/activate/dev_manager.c lvm2-2.02.168/lib/activate/dev_manager.c --- lvm2-2.02.167/lib/activate/dev_manager.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/activate/dev_manager.c 2016-11-30 23:17:28.000000000 +0000 @@ -424,7 +424,7 @@ return_0; if (!dm_task_run(dmt)) { - log_error("Failed to get state of snapshot or snapshot origin device"); + log_error("Failed to get state of snapshot or snapshot origin device."); goto out; } @@ -432,14 +432,14 @@ next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); if (!target_type || !strcmp(target_type, TARGET_NAME_SNAPSHOT)) { if (!params || sscanf(params, "%d:%d %d:%d", &major1, &minor1, &major2, &minor2) != 4) { - log_error("Incorrect snapshot table found"); - goto_out; + log_error("Incorrect snapshot table found."); + goto out; } r = r || _device_is_suspended(major1, minor1) || _device_is_suspended(major2, minor2); } else if (!strcmp(target_type, TARGET_NAME_SNAPSHOT_ORIGIN)) { if (!params || sscanf(params, "%d:%d", &major1, &minor1) != 2) { - log_error("Incorrect snapshot-origin table found"); - goto_out; + log_error("Incorrect snapshot-origin table found."); + goto out; } r = r || _device_is_suspended(major1, minor1); } @@ -2250,8 +2250,8 @@ return NULL; } -static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree, - struct lv_segment *seg, int s) +static char *_add_error_or_zero_device(struct dev_manager *dm, struct dm_tree *dtree, + struct lv_segment *seg, int s, int use_zero) { char *dlid, *name; char errid[32]; @@ -2262,13 +2262,15 @@ uint64_t size = (uint64_t) seg->len * seg->lv->vg->extent_size; dm_list_iterate_items(seg_i, &seg->lv->segments) { - if (seg == seg_i) + if (seg == seg_i) { segno = i; + break; + } ++i; } if (segno < 0) { - log_error("_add_error_device called with bad segment"); + log_error(INTERNAL_ERROR "_add_error_or_zero_device called with bad segment."); return NULL; } @@ -2281,7 +2283,7 @@ seg->lv->name, errid))) return_NULL; - log_debug_activation("Getting device info for %s [%s]", name, dlid); + log_debug_activation("Getting device info for %s [%s].", name, dlid); if (!_info(dm->cmd, dlid, 1, 0, &info, NULL, NULL)) { log_error("Failed to get info for %s [%s].", name, dlid); return 0; @@ -2291,14 +2293,19 @@ /* Create new node */ if (!(node = dm_tree_add_new_dev(dtree, name, dlid, 0, 0, 0, 0, 0))) return_NULL; - if (!dm_tree_node_add_error_target(node, size)) - return_NULL; + + if (use_zero) { + if (!dm_tree_node_add_zero_target(node, size)) + return_NULL; + } else + if (!dm_tree_node_add_error_target(node, size)) + return_NULL; } else { /* Already exists */ if (!dm_tree_add_dev(dtree, info.major, info.minor)) { - log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree", + log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree.", info.major, info.minor); - return_NULL; + return NULL; } } @@ -2310,14 +2317,15 @@ { char *dlid; uint64_t extent_size = seg->lv->vg->extent_size; + int use_zero = !strcmp(dm->cmd->stripe_filler, TARGET_NAME_ZERO) ? 1 : 0; - if (!strcmp(dm->cmd->stripe_filler, TARGET_NAME_ERROR)) { + if (!strcmp(dm->cmd->stripe_filler, TARGET_NAME_ERROR) || use_zero) { /* * FIXME, the tree pointer is first field of dm_tree_node, but * we don't have the struct definition available. */ struct dm_tree **tree = (struct dm_tree **) node; - if (!(dlid = _add_error_device(dm, *tree, seg, s))) + if (!(dlid = _add_error_or_zero_device(dm, *tree, seg, s, use_zero))) return_0; if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_le(seg, s))) return_0; @@ -2825,7 +2833,7 @@ if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer))) return_0; - /* Even unused thin-pool still needs to get layered UUID -suffix */ + /* Even unused thin-pool still needs to get layered UUID -suffix */ if (!layer && lv_is_new_thin_pool(lv)) layer = lv_layer(lv); diff -Nru lvm2-2.02.167/lib/commands/toolcontext.c lvm2-2.02.168/lib/commands/toolcontext.c --- lvm2-2.02.167/lib/commands/toolcontext.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/commands/toolcontext.c 2016-11-30 23:17:28.000000000 +0000 @@ -640,8 +640,8 @@ if (!strcmp(cmd->stripe_filler, "/dev/ioerror") && stat(cmd->stripe_filler, &st)) cmd->stripe_filler = "error"; - - if (strcmp(cmd->stripe_filler, "error")) { + else if (strcmp(cmd->stripe_filler, "error") && + strcmp(cmd->stripe_filler, "zero")) { if (stat(cmd->stripe_filler, &st)) { log_warn("WARNING: activation/missing_stripe_filler = \"%s\" " "is invalid,", cmd->stripe_filler); @@ -997,7 +997,7 @@ if (!(cn = find_config_tree_array(cmd, devices_scan_CFG, NULL))) { log_error(INTERNAL_ERROR "Unable to find configuration for devices/scan."); - return_0; + return 0; } for (cv = cn->v; cv; cv = cv->next) { diff -Nru lvm2-2.02.167/lib/config/config.c lvm2-2.02.168/lib/config/config.c --- lvm2-2.02.167/lib/config/config.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/config/config.c 2016-11-30 23:17:28.000000000 +0000 @@ -389,7 +389,7 @@ !config_force_check(cmd, CONFIG_STRING, cft_new)) { log_error("Ignoring invalid configuration string."); dm_config_destroy(cft_new); - return_0; + return 0; } if (!(cs = dm_pool_zalloc(cft_new->mem, sizeof(struct config_source)))) { diff -Nru lvm2-2.02.167/lib/config/config_settings.h lvm2-2.02.168/lib/config/config_settings.h --- lvm2-2.02.167/lib/config/config_settings.h 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/config/config_settings.h 2016-11-30 23:17:28.000000000 +0000 @@ -1111,7 +1111,8 @@ cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_STRIPE_FILLER, vsn(1, 0, 0), NULL, 0, NULL, "Method to fill missing stripes when activating an incomplete LV.\n" "Using 'error' will make inaccessible parts of the device return I/O\n" - "errors on access. You can instead use a device path, in which case,\n" + "errors on access. Using 'zero' will return success (and zero) on I/O\n" + "You can instead use a device path, in which case,\n" "that device will be used in place of missing stripes. Using anything\n" "other than 'error' with mirrored or snapshotted volumes is likely to\n" "result in data corruption.\n") diff -Nru lvm2-2.02.167/lib/device/dev-type.c lvm2-2.02.168/lib/device/dev-type.c --- lvm2-2.02.167/lib/device/dev-type.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/device/dev-type.c 2016-11-30 23:17:28.000000000 +0000 @@ -1009,7 +1009,7 @@ if (!udev_context) { log_warn("WARNING: No udev context available to check if device %s is multipath component.", dev_name(dev)); - return_0; + return 0; } while (1) { diff -Nru lvm2-2.02.167/lib/format_text/import_vsn1.c lvm2-2.02.168/lib/format_text/import_vsn1.c --- lvm2-2.02.167/lib/format_text/import_vsn1.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/format_text/import_vsn1.c 2016-11-30 23:17:29.000000000 +0000 @@ -732,7 +732,7 @@ if (!(hlvn = hlvn->child)) { log_error("Empty removed logical volume section."); - goto_bad; + goto bad; } if (!_read_id(&glv->historical->lvid.id[1], hlvn, "id")) { diff -Nru lvm2-2.02.167/lib/metadata/lv_manip.c lvm2-2.02.168/lib/metadata/lv_manip.c --- lvm2-2.02.167/lib/metadata/lv_manip.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/metadata/lv_manip.c 2016-11-30 23:17:29.000000000 +0000 @@ -736,11 +736,11 @@ } } - log_very_verbose("Adding %s:%" PRIu32 " as an user of %s", - seg->lv->name, seg->le, lv->name); + log_very_verbose("Adding %s:" FMTu32 " as an user of %s.", + display_lvname(seg->lv), seg->le, display_lvname(lv)); if (!(sl = dm_pool_zalloc(lv->vg->vgmem, sizeof(*sl)))) { - log_error("Failed to allocate segment list"); + log_error("Failed to allocate segment list."); return 0; } @@ -762,16 +762,16 @@ if (sl->count > 1) sl->count--; else { - log_very_verbose("%s:%" PRIu32 " is no longer a user " - "of %s", seg->lv->name, seg->le, - lv->name); + log_very_verbose("%s:" FMTu32 " is no longer a user of %s.", + display_lvname(seg->lv), seg->le, + display_lvname(lv)); dm_list_del(&sl->list); } return 1; } - log_error(INTERNAL_ERROR "Segment %s:%u is not a user of %s.", - seg->lv->name, seg->le, lv->name); + log_error(INTERNAL_ERROR "Segment %s:" FMTu32 " is not a user of %s.", + display_lvname(seg->lv), seg->le, display_lvname(lv)); return 0; } @@ -798,8 +798,9 @@ if (sl->count != 1) { log_error("%s is expected to have only one segment using it, " - "while %s:%" PRIu32 " uses it %d times.", - display_lvname(lv), sl->seg->lv->name, sl->seg->le, sl->count); + "while %s:" FMTu32 " uses it %d times.", + display_lvname(lv), display_lvname(sl->seg->lv), + sl->seg->le, sl->count); return NULL; } @@ -890,7 +891,7 @@ /* Round up extents to stripe divisible amount */ if ((size_rest = extents % stripes)) { new_extents += extend ? stripes - size_rest : -size_rest; - log_print_unless_silent("Rounding size %s (%d extents) up to stripe boundary size %s (%d extents).", + log_print_unless_silent("Rounding size %s (%u extents) up to stripe boundary size %s (%u extents).", display_size(vg->cmd, (uint64_t) extents * vg->extent_size), extents, display_size(vg->cmd, (uint64_t) new_extents * vg->extent_size), new_extents); } @@ -1014,11 +1015,11 @@ */ if (area_reduction != seg->area_len) { log_error("Unable to reduce RAID LV - operation not implemented."); - return_0; + return 0; } else { if (!lv_remove(lv)) { - log_error("Failed to remove RAID image %s", - lv->name); + log_error("Failed to remove RAID image %s.", + display_lvname(lv)); return 0; } } @@ -1027,22 +1028,24 @@ if (seg->meta_areas && seg_metalv(seg, s) && (area_reduction == seg->area_len)) { if (!lv_reduce(seg_metalv(seg, s), seg_metalv(seg, s)->le_count)) { - log_error("Failed to remove RAID meta-device %s", - seg_metalv(seg, s)->name); + log_error("Failed to remove RAID meta-device %s.", + display_lvname(seg_metalv(seg, s))); return 0; } } + return 1; } if (area_reduction == seg->area_len) { - log_very_verbose("Remove %s:%" PRIu32 "[%" PRIu32 "] from " - "the top of LV %s:%" PRIu32, - seg->lv->name, seg->le, s, - lv->name, seg_le(seg, s)); + log_very_verbose("Remove %s:" FMTu32 "[" FMTu32 "] from " + "the top of LV %s:" FMTu32 ".", + display_lvname(seg->lv), seg->le, s, + display_lvname(lv), seg_le(seg, s)); if (!remove_seg_from_segs_using_this_lv(lv, seg)) return_0; + seg_lv(seg, s) = NULL; seg_le(seg, s) = 0; seg_type(seg, s) = AREA_UNASSIGNED; @@ -1132,14 +1135,15 @@ struct logical_volume *lv, uint32_t le, uint64_t status) { - log_very_verbose("Stack %s:%" PRIu32 "[%" PRIu32 "] on LV %s:%" PRIu32, - seg->lv->name, seg->le, area_num, lv->name, le); + log_very_verbose("Stack %s:" FMTu32 "[" FMTu32 "] on LV %s:" FMTu32 ".", + display_lvname(seg->lv), seg->le, area_num, + display_lvname(lv), le); if (status & RAID_META) { seg->meta_areas[area_num].type = AREA_LV; seg_metalv(seg, area_num) = lv; if (le) { - log_error(INTERNAL_ERROR "Meta le != 0"); + log_error(INTERNAL_ERROR "Meta le != 0."); return 0; } seg_metale(seg, area_num) = 0; @@ -1378,7 +1382,7 @@ return 1; } -int lv_refresh_suspend_resume(const struct logical_volume *lv) +static int _lv_refresh_suspend_resume(const struct logical_volume *lv) { struct cmd_context *cmd = lv->vg->cmd; int r = 1; @@ -1403,6 +1407,33 @@ return r; } +int lv_refresh_suspend_resume(const struct logical_volume *lv) +{ + /* + * FIXME: + * + * in case of RAID, refresh the SubLVs before + * refreshing the top-level one in order to cope + * with transient failures of SubLVs. + */ + if (lv_is_raid(lv)) { + uint32_t s; + struct lv_segment *seg = first_seg(lv); + + for (s = 0; s < seg->area_count; s++) { + if (seg_type(seg, s) == AREA_LV && + !_lv_refresh_suspend_resume(seg_lv(seg, s))) + return 0; + if (seg->meta_areas && + seg_metatype(seg, s) == AREA_LV && + !_lv_refresh_suspend_resume(seg_metalv(seg, s))) + return 0; + } + } + + return _lv_refresh_suspend_resume(lv); +} + /* * Remove given number of extents from LV. */ @@ -3479,7 +3510,7 @@ seg->area_count, seg->area_len, seg->chunk_size, region_size, seg->extents_copied, NULL))) { - log_error("Couldn't allocate converted LV segment"); + log_error("Couldn't allocate converted LV segment."); return NULL; } @@ -3512,13 +3543,14 @@ if (!lv_is_pvmove(lv)) { log_error(INTERNAL_ERROR - "Non-pvmove LV, %s, passed as argument", lv->name); + "Non-pvmove LV, %s, passed as argument.", + display_lvname(lv)); return 0; } if (seg_type(first_seg(lv), 0) != AREA_PV) { log_error(INTERNAL_ERROR - "Bad segment type for first segment area"); + "Bad segment type for first segment area."); return 0; } @@ -3529,8 +3561,8 @@ */ dm_list_iterate_items(aa, &ah->alloced_areas[0]) { if (!(seg = find_seg_by_le(lv, current_le))) { - log_error("Failed to find segment for %s extent %" - PRIu32, lv->name, current_le); + log_error("Failed to find segment for %s extent " FMTu32 ".", + display_lvname(lv), current_le); return 0; } @@ -3538,7 +3570,8 @@ if (aa[0].len < seg->area_len) { if (!lv_split_segment(lv, seg->le + aa[0].len)) { log_error("Failed to split segment at %s " - "extent %" PRIu32, lv->name, le); + "extent " FMTu32 ".", + display_lvname(lv), le); return 0; } } @@ -3548,8 +3581,8 @@ current_le = le; if (!insert_layer_for_lv(lv->vg->cmd, lv, PVMOVE, "_mimage_0")) { - log_error("Failed to build pvmove LV-type mirror, %s", - lv->name); + log_error("Failed to build pvmove LV-type mirror %s.", + display_lvname(lv)); return 0; } orig_lv = seg_lv(first_seg(lv), 0); @@ -3570,8 +3603,8 @@ dm_list_iterate_items(aa, &ah->alloced_areas[0]) { if (!(seg = find_seg_by_le(orig_lv, current_le))) { - log_error("Failed to find segment for %s extent %" - PRIu32, lv->name, current_le); + log_error("Failed to find segment for %s extent " FMTu32 ".", + display_lvname(lv), current_le); return 0; } @@ -3617,16 +3650,16 @@ dm_list_iterate_items(aa, &ah->alloced_areas[0]) { if (!(seg = find_seg_by_le(lv, current_le))) { - log_error("Failed to find segment for %s extent %" - PRIu32, lv->name, current_le); + log_error("Failed to find segment for %s extent " FMTu32 ".", + display_lvname(lv), current_le); return 0; } /* Allocator assures aa[0].len <= seg->area_len */ if (aa[0].len < seg->area_len) { if (!lv_split_segment(lv, seg->le + aa[0].len)) { - log_error("Failed to split segment at %s " - "extent %" PRIu32, lv->name, le); + log_error("Failed to split segment at %s extent " FMTu32 ".", + display_lvname(lv), le); return 0; } } @@ -3667,15 +3700,13 @@ uint32_t num_extra_areas, uint64_t status, uint32_t region_size) { - struct lv_segment *seg; - uint32_t old_area_count, new_area_count; uint32_t m; + uint32_t old_area_count, new_area_count; struct segment_type *mirror_segtype; - - seg = first_seg(lv); + struct lv_segment *seg = first_seg(lv); if (dm_list_size(&lv->segments) != 1 || seg_type(seg, 0) != AREA_LV) { - log_error("Mirror layer must be inserted before adding mirrors"); + log_error(INTERNAL_ERROR "Mirror layer must be inserted before adding mirrors."); return 0; } @@ -3685,7 +3716,7 @@ return_0; if (region_size && region_size != seg->region_size) { - log_error("Conflicting region_size"); + log_error("Conflicting region_size."); return 0; } @@ -3694,7 +3725,7 @@ if (!_lv_segment_add_areas(lv, seg, new_area_count)) { log_error("Failed to allocate widened LV segment for %s.", - lv->name); + display_lvname(lv)); return 0; } @@ -3844,6 +3875,7 @@ uint32_t fa, s; int clear_metadata = 0; uint32_t area_multiple = 1; + int fail; if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED))) return_0; @@ -3917,45 +3949,60 @@ if (!vg_write(lv->vg) || !vg_commit(lv->vg)) return_0; - for (s = 0; s < seg->area_count; s++) { - meta_lv = seg_metalv(seg, s); - - if (test_mode()) { - lv_set_hidden(meta_lv); - continue; + if (test_mode()) + log_verbose("Test mode: Skipping wiping of metadata areas."); + else { + fail = 0; + /* Activate all rmeta devices locally first (more efficient) */ + for (s = 0; !fail && s < seg->area_count; s++) { + meta_lv = seg_metalv(seg, s); + + if (!activate_lv_local(meta_lv->vg->cmd, meta_lv)) { + log_error("Failed to activate %s for clearing.", + display_lvname(meta_lv)); + fail = 1; + } } - /* For clearing, simply activate locally */ - if (!activate_lv_local(meta_lv->vg->cmd, meta_lv)) { - log_error("Failed to activate %s/%s for clearing", - meta_lv->vg->name, meta_lv->name); - return 0; - } + /* Clear all rmeta devices */ + for (s = 0; !fail && s < seg->area_count; s++) { + meta_lv = seg_metalv(seg, s); - log_verbose("Clearing metadata area of %s", - display_lvname(meta_lv)); - /* - * Rather than wiping meta_lv->size, we can simply - * wipe '1' to remove the superblock of any previous - * RAID devices. It is much quicker. - */ - if (!wipe_lv(meta_lv, (struct wipe_params) - { .do_zero = 1, .zero_sectors = 1 })) { - log_error("Failed to zero %s/%s", - meta_lv->vg->name, meta_lv->name); - return 0; + log_verbose("Clearing metadata area of %s.", + display_lvname(meta_lv)); + /* + * Rather than wiping meta_lv->size, we can simply + * wipe '1' to remove the superblock of any previous + * RAID devices. It is much quicker. + */ + if (!wipe_lv(meta_lv, (struct wipe_params) + { .do_zero = 1, .zero_sectors = 1 })) { + stack; + fail = 1; + } } - if (!deactivate_lv(meta_lv->vg->cmd, meta_lv)) { - log_error("Failed to deactivate %s/%s", - meta_lv->vg->name, meta_lv->name); - return 0; + /* Deactivate all rmeta devices */ + for (s = 0; s < seg->area_count; s++) { + meta_lv = seg_metalv(seg, s); + + if (!deactivate_lv(meta_lv->vg->cmd, meta_lv)) { + log_error("Failed to deactivate %s after clearing.", + display_lvname(meta_lv)); + fail = 1; + } + + /* Wipe any temporary tags required for activation. */ + str_list_wipe(&meta_lv->tags); } - lv_set_hidden(meta_lv); - /* Wipe any temporary tags required for activation. */ - str_list_wipe(&meta_lv->tags); + if (fail) + /* Fail, after trying to deactivate all we could */ + return_0; } + + for (s = 0; s < seg->area_count; s++) + lv_set_hidden(seg_metalv(seg, s)); } seg->area_len += extents / area_multiple; @@ -6557,7 +6604,7 @@ if (lv_is_active_exclusive_locally(lv_where)) exclusive = 1; - if (lv_is_active(lv_where) && strstr(name, "_mimagetmp")) { + if (lv_is_active(lv_where) && strstr(name, MIRROR_SYNC_LAYER)) { log_very_verbose("Creating transient LV %s for mirror conversion in VG %s.", name, lv_where->vg->name); segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_ERROR); diff -Nru lvm2-2.02.167/lib/metadata/metadata.c lvm2-2.02.168/lib/metadata/metadata.c --- lvm2-2.02.167/lib/metadata/metadata.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/metadata/metadata.c 2016-11-30 23:17:29.000000000 +0000 @@ -828,25 +828,25 @@ struct pv_list *pvl; unsigned int max_phys_block_size = 0; - log_debug_metadata("Adding PVs to VG %s", vg->name); + log_debug_metadata("Adding PVs to VG %s.", vg->name); if (_vg_bad_status_bits(vg, RESIZEABLE_VG)) return_0; dm_list_iterate_items(pvl, &pp->pvs) { - log_debug_metadata("Adding PV %s to VG %s", pv_dev_name(pvl->pv), vg->name); + log_debug_metadata("Adding PV %s to VG %s.", pv_dev_name(pvl->pv), vg->name); if (!(check_dev_block_size_for_vg(pvl->pv->dev, (const struct volume_group *) vg, &max_phys_block_size))) { - log_error("PV %s has wrong block size", pv_dev_name(pvl->pv)); - return_0; + log_error("PV %s has wrong block size.", pv_dev_name(pvl->pv)); + return 0; } if (!add_pv_to_vg(vg, pv_dev_name(pvl->pv), pvl->pv, 0)) { log_error("PV %s cannot be added to VG %s.", pv_dev_name(pvl->pv), vg->name); - return_0; + return 0; } } diff -Nru lvm2-2.02.167/lib/metadata/mirror.c lvm2-2.02.168/lib/metadata/mirror.c --- lvm2-2.02.167/lib/metadata/mirror.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/metadata/mirror.c 2016-11-30 23:17:29.000000000 +0000 @@ -136,16 +136,15 @@ { struct lv_segment *mirror_seg; - mirror_seg = get_only_segment_using_this_lv(seg->lv); - - if (!mirror_seg) { - log_error("Failed to find mirror_seg for %s", seg->lv->name); + if (!(mirror_seg = get_only_segment_using_this_lv(seg->lv))) { + log_error("Failed to find mirror_seg for %s", display_lvname(seg->lv)); return NULL; } if (!seg_is_mirrored(mirror_seg)) { - log_error("%s on %s is not a mirror segments", - mirror_seg->lv->name, seg->lv->name); + log_error("LV %s on %s is not a mirror segments.", + display_lvname(mirror_seg->lv), + display_lvname(seg->lv)); return NULL; } @@ -246,7 +245,7 @@ if (mimage >= mirrored_seg->area_count) { log_error("Invalid index (%u) of mirror image supplied " - "to shift_mirror_images()", mimage); + "to shift_mirror_images().", mimage); return 0; } @@ -282,21 +281,22 @@ log_header.nr_regions = xlate64((uint64_t)-1); if (!(name = dm_pool_alloc(cmd->mem, PATH_MAX))) { - log_error("Name allocation failed - log header not written (%s)", - lv->name); + log_error("Name allocation failed - log header not written (%s).", + display_lvname(lv)); return 0; } if (dm_snprintf(name, PATH_MAX, "%s%s/%s", cmd->dev_dir, lv->vg->name, lv->name) < 0) { - log_error("Name too long - log header not written (%s)", lv->name); + log_error("Name too long - log header not written (%s).", + display_lvname(lv)); return 0; } - log_verbose("Writing log header to device, %s", lv->name); + log_verbose("Writing log header to device %s.", display_lvname(lv)); if (!(dev = dev_cache_get(name, NULL))) { - log_error("%s: not found: log header not written", name); + log_error("%s: not found: log header not written.", name); return 0; } @@ -304,7 +304,7 @@ return 0; if (!dev_write(dev, UINT64_C(0), sizeof(log_header), &log_header)) { - log_error("Failed to write log header to %s", name); + log_error("Failed to write log header to %s.", name); dev_close_immediate(dev); return 0; } @@ -663,8 +663,8 @@ struct cmd_context *cmd = lv->vg->cmd; if (!lv_is_mirrored(lv)) { - log_error("Unable to split non-mirrored LV, %s", - lv->name); + log_error("Unable to split non-mirrored LV %s.", + display_lvname(lv)); return 0; } @@ -673,8 +673,8 @@ return 0; } - log_verbose("Detaching %d images from mirror, %s", - split_count, lv->name); + log_verbose("Detaching %d images from mirror %s.", + split_count, display_lvname(lv)); if (!_move_removable_mimages_to_end(lv, split_count, removable_pvs)) { /* @@ -684,8 +684,7 @@ * removable PVs or all of them. Should we allow * them to just specify some - making us pick the rest? */ - log_error("Insufficient removable PVs given" - " to satisfy request"); + log_error("Insufficient removable PVs given to satisfy request."); return 0; } @@ -704,7 +703,7 @@ if (!release_lv_segment_area(mirrored_seg, mirrored_seg->area_count, mirrored_seg->area_len)) return_0; - log_very_verbose("%s assigned to be split", sub_lv->name); + log_very_verbose("LV %s assigned to be split.", display_lvname(sub_lv)); if (!new_lv) { lv_set_visible(sub_lv); @@ -715,7 +714,7 @@ /* If there is more than one image being split, add to list */ lvl = dm_pool_alloc(lv->vg->vgmem, sizeof(*lvl)); if (!lvl) { - log_error("lv_list alloc failed"); + log_error("lv_list alloc failed."); return 0; } lvl->lv = sub_lv; @@ -738,8 +737,8 @@ */ if (!insert_layer_for_lv(cmd, new_lv, 0, "_mimage_%d")) { - log_error("Failed to build new mirror, %s", - new_lv->name); + log_error("Failed to build new mirror, %s.", + display_lvname(new_lv)); return 0; } @@ -750,25 +749,25 @@ if (dm_snprintf(format, len, "%s_mimage_%%d", new_lv->name) < 0) { - log_error("Failed to build new image name."); + log_error("Failed to build new image name for %s.", + display_lvname(new_lv)); return 0; } - layer_name = dm_pool_alloc(lv->vg->vgmem, len); - if (!layer_name) { - log_error("Unable to allocate memory"); + if (!(layer_name = dm_pool_alloc(lv->vg->vgmem, len))) { + log_error("Unable to allocate memory."); return 0; } if (!generate_lv_name(lv->vg, format, layer_name, len)|| sscanf(layer_name, format, &i) != 1) { - log_error("Failed to generate new image names"); + log_error("Failed to generate new image names for %s.", + display_lvname(new_lv)); return 0; } sub_lv->name = layer_name; } if (!_merge_mirror_images(new_lv, &split_images)) { - log_error("Failed to group split " - "images into new mirror"); + log_error("Failed to group split images into new mirror."); return 0; } @@ -794,41 +793,15 @@ detached_log_lv = detach_mirror_log(mirrored_seg); if (!remove_layer_from_lv(lv, sub_lv)) return_0; - lv->status &= ~MIRROR; - lv->status &= ~MIRRORED; - lv->status &= ~LV_NOTSYNCED; - } - - if (!vg_write(mirrored_seg->lv->vg)) { - log_error("Intermediate VG metadata write failed."); - return 0; - } - - /* - * Suspend the mirror - this includes all the sub-LVs and - * soon-to-be-split sub-LVs - */ - if (!suspend_lv(cmd, mirrored_seg->lv)) { - log_error("Failed to lock %s", mirrored_seg->lv->name); - vg_revert(mirrored_seg->lv->vg); - return 0; + lv->status &= ~(MIRROR | MIRRORED | LV_NOTSYNCED); } - if (!vg_commit(mirrored_seg->lv->vg)) { - resume_lv(cmd, mirrored_seg->lv); - return 0; - } - - log_very_verbose("Updating \"%s\" in kernel", mirrored_seg->lv->name); - /* - * Resume the mirror - this also activates the visible, independent - * soon-to-be-split sub-LVs + * Suspend and resume the mirror - this includes all + * the sub-LVs and soon-to-be-split sub-LVs */ - if (!resume_lv(cmd, mirrored_seg->lv)) { - log_error("Problem resuming %s", mirrored_seg->lv->name); - return 0; - } + if (!lv_update_and_reload(mirrored_seg->lv)) + return_0; /* * Recycle newly split LV so it is properly renamed. @@ -893,7 +866,7 @@ struct logical_volume *sub_lv; struct logical_volume *detached_log_lv = NULL; struct logical_volume *temp_layer_lv = NULL; - struct lv_segment *pvmove_seg, *mirrored_seg = first_seg(lv); + struct lv_segment *seg, *pvmove_seg, *mirrored_seg = first_seg(lv); uint32_t old_area_count = mirrored_seg->area_count; uint32_t new_area_count = mirrored_seg->area_count; struct lv_list *lvl; @@ -904,15 +877,14 @@ if (removed) *removed = 0; - log_very_verbose("Reducing mirror set %s from %" PRIu32 " to %" - PRIu32 " image(s)%s.", lv->name, + log_very_verbose("Reducing mirror set %s from " FMTu32 " to " FMTu32 + " image(s)%s.", display_lvname(lv), old_area_count, old_area_count - num_removed, remove_log ? " and no log volume" : ""); if (collapse && (old_area_count - num_removed != 1)) { - log_error("Incompatible parameters to _remove_mirror_images"); + log_error("Incompatible parameters to _remove_mirror_images."); return 0; - } num_removed = 0; @@ -936,7 +908,8 @@ */ if ((s == 0) && !_mirrored_lv_in_sync(lv) && !(lv_is_partial(lv))) { - log_error("Unable to remove primary mirror image while mirror is not in-sync"); + log_error("Unable to remove primary mirror image while mirror volume " + "%s is not in-sync.", display_lvname(lv)); return 0; } if (!shift_mirror_images(mirrored_seg, s)) @@ -965,7 +938,7 @@ seg_lv(mirrored_seg, m)->status &= ~MIRROR_IMAGE; lv_set_visible(seg_lv(mirrored_seg, m)); if (!(lvl = dm_pool_alloc(lv->vg->cmd->mem, sizeof(*lvl)))) { - log_error("lv_list alloc failed"); + log_error("lv_list alloc failed."); return 0; } lvl->lv = seg_lv(mirrored_seg, m); @@ -987,19 +960,17 @@ if (!remove_layer_from_lv(lv, temp_layer_lv)) return_0; if (collapse && !_merge_mirror_images(lv, &tmp_orphan_lvs)) { - log_error("Failed to add mirror images"); + log_error("Failed to add mirror images."); return 0; } - /* - * No longer a mirror? Even though new_area_count was 1, - * _merge_mirror_images may have resulted into lv being still a - * mirror. Fix up the flags if we only have one image left. - */ - if (lv_mirror_count(lv) == 1) { - lv->status &= ~MIRROR; - lv->status &= ~MIRRORED; - lv->status &= ~LV_NOTSYNCED; - } + /* + * No longer a mirror? Even though new_area_count was 1, + * _merge_mirror_images may have resulted into lv being still a + * mirror. Fix up the flags if we only have one image left. + */ + if (lv_mirror_count(lv) == 1) + lv->status &= ~(MIRROR | MIRRORED | LV_NOTSYNCED); + mirrored_seg = first_seg(lv); if (remove_log && !detached_log_lv) detached_log_lv = detach_mirror_log(mirrored_seg); @@ -1008,14 +979,12 @@ dm_list_iterate_items(pvmove_seg, &lv->segments) pvmove_seg->status |= PVMOVE; } else if (new_area_count == 0) { - log_very_verbose("All mimages of %s are gone", lv->name); + log_very_verbose("All mimages of %s are gone.", display_lvname(lv)); /* All mirror images are gone. * It can happen for vgreduce --removemissing. */ detached_log_lv = detach_mirror_log(mirrored_seg); - lv->status &= ~MIRROR; - lv->status &= ~MIRRORED; - lv->status &= ~LV_NOTSYNCED; + lv->status &= ~(MIRROR | MIRRORED | LV_NOTSYNCED); if (!replace_lv_with_error_segment(lv)) return_0; } else if (remove_log) @@ -1035,10 +1004,10 @@ */ if (detached_log_lv && lv_is_mirrored(detached_log_lv) && lv_is_partial(detached_log_lv)) { - struct lv_segment *seg = first_seg(detached_log_lv); + seg = first_seg(detached_log_lv); - log_very_verbose("%s being removed due to failures", - detached_log_lv->name); + log_very_verbose("%s being removed due to failures.", + display_lvname(detached_log_lv)); /* * We are going to replace the mirror with an @@ -1047,47 +1016,24 @@ * the sub-lv's) */ for (m = 0; m < seg->area_count; m++) { + if (!(lvl = dm_pool_alloc(lv->vg->cmd->mem, + sizeof(*lvl)))) + return_0; + seg_lv(seg, m)->status &= ~MIRROR_IMAGE; lv_set_visible(seg_lv(seg, m)); - if (!(lvl = dm_pool_alloc(lv->vg->cmd->mem, - sizeof(*lvl)))) { - log_error("dm_pool_alloc failed"); - return 0; - } lvl->lv = seg_lv(seg, m); dm_list_add(&tmp_orphan_lvs, &lvl->list); } if (!replace_lv_with_error_segment(detached_log_lv)) { - log_error("Failed error target substitution for %s", - detached_log_lv->name); - return 0; - } - - if (!vg_write(detached_log_lv->vg)) { - log_error("intermediate VG write failed."); + log_error("Failed error target substitution for %s.", + display_lvname(detached_log_lv)); return 0; } - if (!suspend_lv(detached_log_lv->vg->cmd, - detached_log_lv)) { - log_error("Failed to suspend %s", - detached_log_lv->name); - return 0; - } - - if (!vg_commit(detached_log_lv->vg)) { - if (!resume_lv(detached_log_lv->vg->cmd, - detached_log_lv)) - stack; + if (!lv_update_and_reload(detached_log_lv)) return_0; - } - - if (!resume_lv(detached_log_lv->vg->cmd, detached_log_lv)) { - log_error("Failed to resume %s", - detached_log_lv->name); - return 0; - } } /* @@ -1095,14 +1041,13 @@ * remove the LVs from the mirror set, commit that metadata * then deactivate and remove them fully. */ - if (!vg_write(mirrored_seg->lv->vg)) { log_error("intermediate VG write failed."); return 0; } if (!suspend_lv_origin(mirrored_seg->lv->vg->cmd, mirrored_seg->lv)) { - log_error("Failed to lock %s", mirrored_seg->lv->name); + log_error("Failed to lock %s.", display_lvname(mirrored_seg->lv)); vg_revert(mirrored_seg->lv->vg); return 0; } @@ -1115,7 +1060,7 @@ * FIXME: check propagation of suspend with visible flag */ if (temp_layer_lv && !suspend_lv(temp_layer_lv->vg->cmd, temp_layer_lv)) - log_error("Problem suspending temporary LV %s", temp_layer_lv->name); + log_error("Problem suspending temporary LV %s.", display_lvname(temp_layer_lv)); if (!vg_commit(mirrored_seg->lv->vg)) { if (!resume_lv(mirrored_seg->lv->vg->cmd, mirrored_seg->lv)) @@ -1123,7 +1068,7 @@ return_0; } - log_very_verbose("Updating \"%s\" in kernel", mirrored_seg->lv->name); + log_very_verbose("Updating %s in kernel.", display_lvname(mirrored_seg->lv)); /* * Avoid having same mirror target loaded twice simultaneously by first @@ -1132,12 +1077,12 @@ * explicitly. */ if (temp_layer_lv && !resume_lv(temp_layer_lv->vg->cmd, temp_layer_lv)) { - log_error("Problem resuming temporary LV, %s", temp_layer_lv->name); + log_error("Problem resuming temporary LV %s.", display_lvname(temp_layer_lv)); return 0; } if (!resume_lv_origin(mirrored_seg->lv->vg->cmd, mirrored_seg->lv)) { - log_error("Problem reactivating %s", mirrored_seg->lv->name); + log_error("Problem reactivating %s.", display_lvname(mirrored_seg->lv)); return 0; } @@ -1162,7 +1107,8 @@ 1, &lv->tags, 0)) { /* As a result, unnecessary sync may run after * collapsing. But safe.*/ - log_error("Failed to initialize log device"); + log_error("Failed to initialize log device %s.", + display_lvname(first_seg(lv)->log_lv)); return 0; } } @@ -1170,8 +1116,9 @@ if (removed) *removed = old_area_count - new_area_count; - log_very_verbose(FMTu32 " image(s) removed from %s", - old_area_count - new_area_count, lv->name); + log_very_verbose(FMTu32 " image(s) removed from %s.", + old_area_count - new_area_count, + display_lvname(lv)); return 1; } @@ -1353,15 +1300,15 @@ /* FIXME: Use lvconvert rather than duplicating its code */ if (mirrored_seg->area_count < num_mirrors) { - log_warn("WARNING: Failed to replace mirror device in %s/%s", - mirrored_seg->lv->vg->name, mirrored_seg->lv->name); + log_warn("WARNING: Failed to replace mirror device in %s.", + display_lvname(mirrored_seg->lv); if ((mirrored_seg->area_count > 1) && !mirrored_seg->log_lv) - log_warn("WARNING: Use 'lvconvert -m %d %s/%s --corelog' to replace failed devices", - num_mirrors - 1, lv->vg->name, lv->name); + log_warn("WARNING: Use 'lvconvert -m %d %s --corelog' to replace failed devices.", + num_mirrors - 1, display_lvname(lv)); else - log_warn("WARNING: Use 'lvconvert -m %d %s/%s' to replace failed devices", - num_mirrors - 1, lv->vg->name, lv->name); + log_warn("WARNING: Use 'lvconvert -m %d %s' to replace failed devices.", + num_mirrors - 1, display_lvname(lv)); r = 0; /* REMEMBER/FIXME: set in_sync to 0 if a new mirror device was added */ @@ -1374,11 +1321,11 @@ */ if ((mirrored_seg->area_count > 1) && !mirrored_seg->log_lv && (log_policy != MIRROR_REMOVE)) { - log_warn("WARNING: Failed to replace mirror log device in %s/%s", - lv->vg->name, lv->name); + log_warn("WARNING: Failed to replace mirror log device in %s.", + display_lvname(lv)); - log_warn("WARNING: Use 'lvconvert -m %d %s/%s' to replace failed devices", - mirrored_seg->area_count - 1 , lv->vg->name, lv->name); + log_warn("WARNING: Use 'lvconvert -m %d %s' to replace failed devices.", + mirrored_seg->area_count - 1 , display_lvname(lv)); r = 0; } @@ -1411,8 +1358,8 @@ /* Unable to remove bad devices */ return 0; - log_warn("WARNING: Bad device removed from mirror volume, %s/%s", - mirrored_seg->lv->vg->name, mirrored_seg->lv->name); + log_warn("WARNING: Bad device removed from mirror volume %s.", + display_lvname(mirrored_seg->lv)); log_policy = _get_mirror_log_fault_policy(mirrored_seg->lv->vg->cmd); dev_policy = _get_mirror_device_fault_policy(mirrored_seg->lv->vg->cmd); @@ -1424,20 +1371,20 @@ if (!r) /* Failed to replace device(s) */ - log_warn("WARNING: Unable to find substitute device for mirror volume, %s/%s", - mirrored_seg->lv->vg->name, mirrored_seg->lv->name); + log_warn("WARNING: Unable to find substitute device for mirror volume %s.", + display_lvname(mirrored_seg->lv)); else if (r > 0) /* Success in replacing device(s) */ - log_warn("WARNING: Mirror volume, %s/%s restored - substitute for failed device found.", - mirrored_seg->lv->vg->name, mirrored_seg->lv->name); + log_warn("WARNING: Mirror volume %s restored - substitute for failed device found.", + display_lvname(mirrored_seg->lv)); else /* Bad device removed, but not replaced because of policy */ if (mirrored_seg->area_count == 1) { - log_warn("WARNING: Mirror volume, %s/%s converted to linear due to device failure.", - mirrored_seg->lv->vg->name, mirrored_seg->lv->name); + log_warn("WARNING: Mirror volume %s converted to linear due to device failure.", + display_lvname(mirrored_seg->lv); } else if (had_log && !mirrored_seg->log_lv) { - log_warn("WARNING: Mirror volume, %s/%s disk log removed due to device failure.", - mirrored_seg->lv->vg->name, mirrored_seg->lv->name); + log_warn("WARNING: Mirror volume %s disk log removed due to device failure.", + display_lvname(mirrored_seg->lv)); } /* * If we made it here, we at least removed the bad device. @@ -1734,23 +1681,26 @@ if (!(ah = allocate_extents(lv->vg, NULL, segtype, 1, mirrors, 0, 0, lv->le_count, allocatable_pvs, alloc, 0, parallel_areas))) { - log_error("Unable to allocate mirror extents for %s.", lv->name); + log_error("Unable to allocate mirror extents for %s.", + display_lvname(lv)); return 0; } if (flags & MIRROR_BY_SEG) { if (!lv_add_mirror_areas(ah, lv, 0, adjusted_region_size)) { - log_error("Failed to add mirror areas to %s", lv->name); + log_error("Failed to add mirror areas to %s.", + display_lvname(lv)); r = 0; } } else if (flags & MIRROR_BY_SEGMENTED_LV) { if (!lv_add_segmented_mirror_image(ah, lv, 0, adjusted_region_size)) { - log_error("Failed to add mirror areas to %s", lv->name); + log_error("Failed to add mirror areas to %s.", + display_lvname(lv)); r = 0; } } else { - log_error(INTERNAL_ERROR "Unknown mirror flag"); + log_error(INTERNAL_ERROR "Unknown mirror flag."); r = 0; } alloc_destroy(ah); @@ -1784,7 +1734,7 @@ /* Unimplemented features */ if (dm_list_size(&lv->segments) != 1) { - log_error("Multiple-segment mirror is not supported"); + log_error("Multiple-segment mirror is not supported."); return 0; } @@ -1796,19 +1746,19 @@ return 0; } } else if (lv_is_active(lv)) { - log_error("Unable to determine sync status of" - " remotely active mirror, %s", lv->name); + log_error("Unable to determine sync status of " + "remotely active mirror volume %s.", display_lvname(lv)); return 0; } else if (vg_is_clustered(vg)) { log_error("Unable to convert the log of an inactive " - "cluster mirror, %s", lv->name); + "cluster mirror volume %s.", display_lvname(lv)); return 0; - } else if (force || yes_no_prompt("Full resync required to convert " - "inactive mirror %s to core log. " - "Proceed? [y/n]: ", lv->name) == 'y') + } else if (force || yes_no_prompt("Full resync required to convert inactive " + "mirror volume %s to core log. " + "Proceed? [y/n]: ", display_lvname(lv)) == 'y') sync_percent = 0; else { - log_error("Logical volume %s NOT converted.", lv->name); + log_error("Logical volume %s NOT converted.", display_lvname(lv)); return 0; } @@ -1872,7 +1822,7 @@ if (dm_list_size(&lv->segments) != 1 || seg_type(first_seg(lv), 0) != AREA_LV) if (!insert_layer_for_lv(cmd, lv, 0, "_mimage_%d")) - return 0; + return_0; /* * create mirror image LVs @@ -1883,7 +1833,9 @@ return_0; if (!lv_add_mirror_lvs(lv, img_lvs, mirrors, - MIRROR_IMAGE | (lv->status & LOCKED), + /* Pass through MIRRORED & LOCKED status flag + * TODO: Any other would be needed ?? */ + MIRROR_IMAGE | (lv->status & (MIRRORED | LOCKED)), region_size)) { log_error("Aborting. Failed to add mirror segment. " "Remove new LV and retry."); @@ -1974,25 +1926,25 @@ int r = 0; if (vg_is_clustered(lv->vg) && (log_count > 1)) { - log_error("Log type, \"mirrored\", is unavailable to cluster mirrors"); + log_error("Log type, \"mirrored\", is unavailable to cluster mirrors."); return 0; } if (dm_list_size(&lv->segments) != 1) { - log_error("Multiple-segment mirror is not supported"); + log_error("Multiple-segment mirror is not supported."); return 0; } if (lv_is_active_but_not_locally(lv)) { log_error("Unable to convert the log of a mirror, %s, that is " - "active remotely but not locally", lv->name); + "active remotely but not locally.", display_lvname(lv)); return 0; } log_lv = first_seg(lv)->log_lv; old_log_count = (log_lv) ? lv_mirror_count(log_lv) : 0; if (old_log_count == log_count) { - log_verbose("Mirror already has a %s log", + log_verbose("Mirror %s already has a %s log.", display_lvname(lv), !log_count ? "core" : (log_count == 1) ? "disk" : "mirrored"); return 1; @@ -2007,16 +1959,15 @@ if (activation() && segtype->ops->target_present && !segtype->ops->target_present(cmd, NULL, NULL)) { log_error("%s: Required device-mapper target(s) not " - "detected in your kernel", segtype->name); + "detected in your kernel.", segtype->name); return 0; } /* allocate destination extents */ - ah = allocate_extents(lv->vg, NULL, segtype, - 0, 0, log_count - old_log_count, region_size, - lv->le_count, allocatable_pvs, - alloc, 0, parallel_areas); - if (!ah) { + if (!(ah = allocate_extents(lv->vg, NULL, segtype, + 0, 0, log_count - old_log_count, region_size, + lv->le_count, allocatable_pvs, + alloc, 0, parallel_areas))) { log_error("Unable to allocate extents for mirror log."); return 0; } @@ -2077,10 +2028,9 @@ if (!(segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_MIRROR))) return_0; - ah = allocate_extents(lv->vg, NULL, segtype, - stripes, mirrors, log_count, region_size, lv->le_count, - allocatable_pvs, alloc, 0, parallel_areas); - if (!ah) { + if (!(ah = allocate_extents(lv->vg, NULL, segtype, + stripes, mirrors, log_count, region_size, lv->le_count, + allocatable_pvs, alloc, 0, parallel_areas))) { log_error("Unable to allocate extents for mirror(s)."); return 0; } @@ -2136,7 +2086,7 @@ struct dm_list *pvs, alloc_policy_t alloc, uint32_t flags) { if (!mirrors && !log_count) { - log_error("No conversion is requested"); + log_error("No conversion is requested."); return 0; } @@ -2156,7 +2106,7 @@ * log daemon is multi-threaded. */ if (log_count > 1) { - log_error("Log type, \"mirrored\", is unavailable to cluster mirrors"); + log_error("Log type, \"mirrored\", is unavailable to cluster mirrors."); return 0; } } @@ -2174,12 +2124,12 @@ if (flags & MIRROR_BY_SEG) { if (log_count) { log_error("Persistent log is not supported on " - "segment-by-segment mirroring"); + "segment-by-segment mirroring."); return 0; } if (stripes > 1) { log_error("Striped-mirroring is not supported on " - "segment-by-segment mirroring"); + "segment-by-segment mirroring."); return 0; } @@ -2189,7 +2139,7 @@ } else if (flags & MIRROR_BY_SEGMENTED_LV) { if (stripes > 1) { log_error("Striped-mirroring is not supported on " - "segment-by-segment mirroring"); + "segment-by-segment mirroring."); return 0; } @@ -2205,26 +2155,27 @@ pvs, alloc, log_count); } - log_error("Unsupported mirror conversion type"); + log_error("Unsupported mirror conversion type."); + return 0; } int lv_split_mirror_images(struct logical_volume *lv, const char *split_name, uint32_t split_count, struct dm_list *removable_pvs) { - int r; int historical; if (lv_name_is_used_in_vg(lv->vg, split_name, &historical)) { log_error("%sLogical Volume \"%s\" already exists in " - "volume group \"%s\"", historical ? "historical " : "", + "volume group \"%s\".", historical ? "historical " : "", split_name, lv->vg->name); return 0; } /* Can't split a mirror that is not in-sync... unless force? */ if (!_mirrored_lv_in_sync(lv)) { - log_error("Unable to split mirror that is not in-sync."); + log_error("Unable to split mirror %s that is not in-sync.", + display_lvname(lv)); return 0; } @@ -2238,8 +2189,7 @@ * is being implemented. For now, we force the user to * come up with a name for their LV. */ - r = _split_mirror_images(lv, split_name, split_count, removable_pvs); - if (!r) + if (!_split_mirror_images(lv, split_name, split_count, removable_pvs)) return_0; return 1; @@ -2261,18 +2211,18 @@ struct lv_segment *seg; if (!mirrors && !log_count) { - log_error("No conversion is requested"); + log_error("No conversion is requested."); return 0; } seg = first_seg(lv); if (!seg_is_mirrored(seg)) { - log_error("Not a mirror segment"); + log_error("Not a mirror segment."); return 0; } if (lv_mirror_count(lv) <= mirrors) { - log_error("Removing more than existing: %d <= %d", + log_error("Removing more than existing: %d <= %d.", seg->area_count, mirrors); return 0; } @@ -2288,7 +2238,7 @@ /* MIRROR_BY_SEG */ if (log_count) { log_error("Persistent log is not supported on " - "segment-by-segment mirroring"); + "segment-by-segment mirroring."); return 0; } return remove_mirrors_from_segments(lv, new_mirrors, status_mask); diff -Nru lvm2-2.02.167/lib/metadata/raid_manip.c lvm2-2.02.168/lib/metadata/raid_manip.c --- lvm2-2.02.167/lib/metadata/raid_manip.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/metadata/raid_manip.c 2016-11-30 23:17:29.000000000 +0000 @@ -34,6 +34,7 @@ return 1; } +__attribute__ ((__unused__)) /* Check that all lv has segments have exactly the required number of areas */ static int _check_num_areas_in_lv_segments(struct logical_volume *lv, unsigned num_areas) { @@ -283,8 +284,8 @@ * https://bugzilla.redhat.com/1210637 */ if (!lv_raid_percent(lv, &sync_percent)) { - log_error("Unable to determine sync status of %s/%s.", - lv->vg->name, lv->name); + log_error("Unable to determine sync status of %s.", + display_lvname(lv)); return 0; } if (sync_percent > DM_PERCENT_0) @@ -1055,11 +1056,10 @@ seg_type(seg, idx) = AREA_UNASSIGNED; seg_metatype(seg, idx) = AREA_UNASSIGNED; - /* FIXME Remove duplicated prefix? */ - if (!(data_lv->name = _generate_raid_name(data_lv, "_extracted", -1))) + if (!(data_lv->name = _generate_raid_name(data_lv, "extracted", -1))) return_0; - if (!(meta_lv->name = _generate_raid_name(meta_lv, "_extracted", -1))) + if (!(meta_lv->name = _generate_raid_name(meta_lv, "extracted", -1))) return_0; *extracted_rmeta = meta_lv; @@ -1861,25 +1861,25 @@ dm_list_init(&meta_lvs); - log_debug_metadata("Allocating metadata LVs for %s", display_lvname(lv)); + log_debug_metadata("Allocating metadata LVs for %s.", display_lvname(lv)); if (!_alloc_rmeta_devs_for_lv(lv, &meta_lvs, allocate_pvs, &seg_meta_areas)) { - log_error("Failed to allocate metadata LVs for %s", display_lvname(lv)); - return_0; + log_error("Failed to allocate metadata LVs for %s.", display_lvname(lv)); + return 0; } /* Metadata LVs must be cleared before being added to the array */ - log_debug_metadata("Clearing newly allocated metadata LVs for %s", display_lvname(lv)); + log_debug_metadata("Clearing newly allocated metadata LVs for %s.", display_lvname(lv)); if (!_clear_lvs(&meta_lvs)) { - log_error("Failed to initialize metadata LVs for %s", display_lvname(lv)); - return_0; + log_error("Failed to initialize metadata LVs for %s.", display_lvname(lv)); + return 0; } /* Set segment areas for metadata sub_lvs */ seg->meta_areas = seg_meta_areas; - log_debug_metadata("Adding newly allocated metadata LVs to %s", display_lvname(lv)); + log_debug_metadata("Adding newly allocated metadata LVs to %s.", display_lvname(lv)); if (!_add_image_component_list(seg, 1, 0, &meta_lvs, 0)) { - log_error("Failed to add newly allocated metadata LVs to %s", display_lvname(lv)); - return_0; + log_error("Failed to add newly allocated metadata LVs to %s.", display_lvname(lv)); + return 0; } return 1; @@ -3663,14 +3663,14 @@ /* Got to do check for raid5 -> raid6 ... */ } else if (seg_is_any_raid5(seg_from) && segtype_is_any_raid6(*segtype)) { - log_error("Conversion not supported."); - return_0; + log_error("Conversion not supported."); + return 0; /* ... and raid6 -> raid5 */ } else if (seg_is_any_raid6(seg_from) && segtype_is_any_raid5(*segtype)) { - log_error("Conversion not supported."); - return_0; + log_error("Conversion not supported."); + return 0; } return 1; diff -Nru lvm2-2.02.167/lib/notify/lvmnotify.c lvm2-2.02.168/lib/notify/lvmnotify.c --- lvm2-2.02.167/lib/notify/lvmnotify.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/notify/lvmnotify.c 2016-11-30 23:17:29.000000000 +0000 @@ -15,6 +15,8 @@ #define LVM_DBUS_DESTINATION "com.redhat.lvmdbus1" #define LVM_DBUS_PATH "/com/redhat/lvmdbus1/Manager" #define LVM_DBUS_INTERFACE "com.redhat.lvmdbus1.Manager" +#define SD_BUS_SYSTEMD_NO_SUCH_UNIT_ERROR "org.freedesktop.systemd1.NoSuchUnit" +#define SD_BUS_DBUS_SERVICE_UNKNOWN_ERROR "org.freedesktop.DBus.Error.ServiceUnknown" #ifdef NOTIFYDBUS_SUPPORT #include @@ -26,6 +28,7 @@ void lvmnotify_send(struct cmd_context *cmd) { + static const char _dbus_notification_failed_msg[] = "D-Bus notification failed"; sd_bus *bus = NULL; sd_bus_message *m = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; @@ -61,7 +64,11 @@ cmd_name); if (ret < 0) { - log_warn("WARNING: D-Bus notification failed: %s", error.message); + if (sd_bus_error_has_name(&error, SD_BUS_SYSTEMD_NO_SUCH_UNIT_ERROR) || + sd_bus_error_has_name(&error, SD_BUS_DBUS_SERVICE_UNKNOWN_ERROR)) + log_debug_dbus("%s: %s", _dbus_notification_failed_msg, error.message); + else + log_warn("WARNING: %s: %s", _dbus_notification_failed_msg, error.message); goto out; } diff -Nru lvm2-2.02.167/lib/raid/raid.c lvm2-2.02.168/lib/raid/raid.c --- lvm2-2.02.167/lib/raid/raid.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/lib/raid/raid.c 2016-11-30 23:17:29.000000000 +0000 @@ -342,13 +342,69 @@ *total_denominator += denominator; if (seg) - seg->extents_copied = seg->area_len * numerator / denominator; + seg->extents_copied = (uint64_t) seg->area_len * dm_make_percent(numerator, denominator) / DM_PERCENT_100; *percent = dm_make_percent(numerator, denominator); return 1; } +static int _raid_transient_status(struct dm_pool *mem, + struct lv_segment *seg, + char *params) +{ + int failed = 0, r = 0; + unsigned i; + struct lvinfo info; + struct logical_volume *lv; + struct dm_status_raid *sr; + + log_debug("Raid transient status %s.", params); + + if (!dm_get_status_raid(mem, params, &sr)) + return_0; + + if (sr->dev_count != seg->area_count) { + log_error("Active raid has a wrong number of raid images!"); + log_error("Metadata says %u, kernel says %u.", + seg->area_count, sr->dev_count); + goto out; + } + + if (seg->meta_areas) + for (i = 0; i < seg->area_count; ++i) { + lv = seg_metalv(seg, i); + if (!lv_info(lv->vg->cmd, lv, 0, &info, 0, 0)) { + log_error("Check for existence of raid meta %s failed.", + display_lvname(lv)); + goto out; + } + } + + for (i = 0; i < seg->area_count; ++i) { + lv = seg_lv(seg, i); + if (!lv_info(lv->vg->cmd, lv, 0, &info, 0, 0)) { + log_error("Check for existence of raid image %s failed.", + display_lvname(lv)); + goto out; + } + if (sr->dev_health[i] == 'D') { + lv->status |= PARTIAL_LV; + ++failed; + } + } + + /* Update PARTIAL_LV flags across the VG */ + if (failed) + vg_mark_partial_lvs(lv->vg, 0); + + r = 1; +out: + dm_pool_free(mem, sr); + + return r; +} + static int _raid_target_present(struct cmd_context *cmd, const struct lv_segment *seg __attribute__((unused)), unsigned *attributes) @@ -460,6 +516,7 @@ #ifdef DEVMAPPER_SUPPORT .target_percent = _raid_target_percent, .target_present = _raid_target_present, + .check_transient_status = _raid_transient_status, .modules_needed = _raid_modules_needed, # ifdef DMEVENTD .target_monitored = _raid_target_monitored, diff -Nru lvm2-2.02.167/libdm/libdevmapper.h lvm2-2.02.168/libdm/libdevmapper.h --- lvm2-2.02.167/libdm/libdevmapper.h 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/libdm/libdevmapper.h 2016-11-30 23:17:30.000000000 +0000 @@ -327,7 +327,9 @@ uint64_t mismatch_count; uint32_t dev_count; char *raid_type; + /* A - alive, a - alive not in-sync, D - dead/failed */ char *dev_health; + /* idle, frozen, resync, recover, check, repair */ char *sync_action; }; diff -Nru lvm2-2.02.167/libdm/libdm-stats.c lvm2-2.02.168/libdm/libdm-stats.c --- lvm2-2.02.167/libdm/libdm-stats.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/libdm/libdm-stats.c 2016-11-30 23:17:30.000000000 +0000 @@ -1841,7 +1841,7 @@ if (!group_tag) { log_error("Could not build group descriptor for " "region ID " FMTu64, region_id); - goto_bad; + goto bad; } } @@ -2241,7 +2241,11 @@ if (!_stats_bound(dms)) return_0; - if (!region || !_stats_parse_region(dms, resp, region, region->timescale)) { + if (!region) { + log_error("Cannot populate empty handle before dm_stats_list()."); + return 0; + } + if (!_stats_parse_region(dms, resp, region, region->timescale)) { log_error("Could not parse @stats_print message response."); return 0; } diff -Nru lvm2-2.02.167/libdm/regex/parse_rx.c lvm2-2.02.168/libdm/regex/parse_rx.c --- lvm2-2.02.167/libdm/regex/parse_rx.c 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/libdm/regex/parse_rx.c 2016-11-30 23:17:30.000000000 +0000 @@ -19,6 +19,7 @@ #ifdef DEBUG #include +__attribute__ ((__unused__)) static void _regex_print(struct rx_node *rx, int depth, unsigned show_nodes) { int i, numchars; diff -Nru lvm2-2.02.167/man/lvconvert.8.in lvm2-2.02.168/man/lvconvert.8.in --- lvm2-2.02.167/man/lvconvert.8.in 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/man/lvconvert.8.in 2016-11-30 23:17:30.000000000 +0000 @@ -365,6 +365,9 @@ VG/RaidLV .br \[bu] +Options \-\-background, \-\-interval. +.br +\[bu] Replace failed PVs in RaidLV. .B lvconvert \-\-replace @@ -502,6 +505,9 @@ VG/MirrorLV .br \[bu] +Options \-\-background, \-\-interval. +.br +\[bu] Replace failed PVs in MirrorLV. .B lvconvert \-\-type linear diff -Nru lvm2-2.02.167/man/lvm.8.in lvm2-2.02.168/man/lvm.8.in --- lvm2-2.02.167/man/lvm.8.in 2016-11-05 01:06:48.000000000 +0000 +++ lvm2-2.02.168/man/lvm.8.in 2016-11-30 23:17:30.000000000 +0000 @@ -328,7 +328,7 @@ All rows are displayed with the additional "selected" column (\fB-o selected\fP) showing 1 if the row matches the \fISelection\fP and 0 otherwise. For non-reporting commands which process LVM entities, the selection can be used to match items -to process. See \fBSELECTION CRITERIA\fP section of this man page for more +to process. See \fBSelection\fP section in \fBlvmreport\fP(7) man page for more information about the way the selection criteria are constructed. . .HP @@ -639,108 +639,6 @@ require more than one command to create. The cache (\fBlvmcache\fP(7)) and thin provisioning (\fBlvmthin\fP(7)) types are examples of this. . -.SH SELECTION CRITERIA -. -The selection criteria are a set of \fBstatements\fP combined by \fBlogical -and grouping operators\fP. The \fBstatement\fP consists of \fBcolumn\fP -name for which a set of valid \fBvalues\fP is defined using -\fBcomparison operators\fP. For complete list of column names (fields) -that can be used in selection, see the output of \fB -S help\fP. -.P -.SS Comparison operators \fR(cmp_op) -.sp -.PD 0 -.TP -.B =~ -Matching regular expression. -.TP -.B !~ -Not matching regular expression. -.TP -.B = -Equal to. -.TP -.B != -Not equal to. -.TP -.B >= -Greater than or equal to. -.TP -.B > -Greater than -.TP -.B <= -Less than or equal to. -.TP -.B < -Less than. -.PD -.P -.SS Binary logical operators \fR(cmp_log) -.sp -.PD 0 -.TP -.B && -All fields must match -.TP -.B , -All fields must match -.TP -.B || -At least one field must match -.TP -.B # -At least one field must match -.PD -.P -.SS Unary logical operators -.TP -.B ! -Logical negation -.P -.SS Grouping operators -.sp -.PD 0 -.TP -.B ( -Left parenthesis -.TP -.B ) -Right parenthesis -.TP -.B [ -List start -.TP -.B ] -List end -.TP -.B { -List subset start -.TP -.B } -List subset end -.PD -.SS Informal grammar specification -.HP -.BR STATEMENT " = " column " cmp_op " VALUE " | " \%STATEMENT " log_op " STATEMENT " | " \%(STATEMENT) " | " \%!(STATEMENT) -.br -.HP -.BR VALUE " = " [VALUE " log_op " VALUE] -.br -For list-based types: string list. Matches strictly. -The log_op must always be of one type within the whole list value. -.HP -.BR VALUE " = " {VALUE " log_op " VALUE} -.br -For list-based types: string list. Matches a subset. -The log_op must always be of one type within the whole list value. -.HP -.BR VALUE " = " value -.br -For scalar types: number (integer), size (floating point number -with size unit suffix), percent (floating point number with or -without % suffix), string. -. .SH DIAGNOSTICS . All tools return a status code of zero on success or non-zero on failure. @@ -835,6 +733,7 @@ .nh .BR lvm.conf (5), .BR lvmcache (7), +.BR lvmreport(7), .BR lvmthin (7), .BR clvmd (8), .BR dmsetup (8), diff -Nru lvm2-2.02.167/scripts/blk_availability_init_red_hat.in lvm2-2.02.168/scripts/blk_availability_init_red_hat.in --- lvm2-2.02.167/scripts/blk_availability_init_red_hat.in 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/scripts/blk_availability_init_red_hat.in 2016-11-30 23:17:31.000000000 +0000 @@ -10,10 +10,10 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # -# This file is part of LVM2. -# It is required for the proper handling of failures of LVM2 mirror -# devices that were created using the -m option of lvcreate. -# +# This script is responsible for executing blkdeactivate at shutdown +# to properly unmount filesystems and deactivate device stacks containing +# device-mapper devices (including plain device-mapper devices, LVM2 and +# multipath devices) and MD devices. # # chkconfig: 12345 25 75 # description: Controls availability of block devices diff -Nru lvm2-2.02.167/test/api/dbustest.sh lvm2-2.02.168/test/api/dbustest.sh --- lvm2-2.02.167/test/api/dbustest.sh 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/api/dbustest.sh 2016-11-30 23:17:31.000000000 +0000 @@ -20,13 +20,17 @@ # We need the lvmdbusd.profile for the daemon to utilize JSON # output -mkdir -p $TESTDIR/etc/profile/ -cp -v $TESTOLDPWD/../conf/lvmdbusd.profile $TESTDIR/etc/profile/. +mkdir -p "$TESTDIR/etc/profile" +cp -v "$TESTOLDPWD/lib/lvmdbusd.profile" "$TESTDIR/etc/profile/" # Need to set this up so that the lvmdbusd service knows which # binary to be running, which should be the one we just built -export LVM_BINARY=$TESTOLDPWD/../tools/lvm +export LVM_BINARY=$(which lvm 2>/dev/null) +# skip if we don't have our own lvmetad... +if test -z "${installed_testsuite+varset}"; then + (echo "$LVM_BINARY" | grep -q "$abs_builddir") || skip +fi aux prepare_lvmdbusd -$test_data_dir/dbus/lvmdbustest.py -v +$TESTOLDPWD/dbus/lvmdbustest.py -v diff -Nru lvm2-2.02.167/test/dbus/lvmdbustest.py lvm2-2.02.168/test/dbus/lvmdbustest.py --- lvm2-2.02.167/test/dbus/lvmdbustest.py 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/dbus/lvmdbustest.py 2016-11-30 23:17:31.000000000 +0000 @@ -14,27 +14,43 @@ # noinspection PyUnresolvedReferences from dbus.mainloop.glib import DBusGMainLoop import unittest -import sys import time import pyudev -import os from testlib import * +import testlib g_tmo = 0 +# Prefix on created objects to enable easier clean-up g_prefix = os.getenv('PREFIX', '') -use_session = os.getenv('LVMDBUSD_USE_SESSION', False) +# Use the session bus instead of the system bus +use_session = os.getenv('LVM_DBUSD_USE_SESSION', False) + +# Only use the devices listed in the ENV variable +pv_device_list = os.getenv('LVM_DBUSD_PV_DEVICE_LIST', None) + +# Default is to test all modes +# 0 == Only test fork & exec mode +# 1 == Test both fork & exec & lvm shell mode (default) +# Other == Test just lvm shell mode +test_shell = os.getenv('LVM_DBUSD_TEST_MODE', 1) + +# Empty options dictionary (EOD) +EOD = dbus.Dictionary({}, signature=dbus.Signature('sv')) +# Base interfaces on LV objects +LV_BASE_INT = (LV_COMMON_INT, LV_INT) if use_session: bus = dbus.SessionBus(mainloop=DBusGMainLoop()) else: bus = dbus.SystemBus(mainloop=DBusGMainLoop()) - -def std_err_print(*args): - sys.stderr.write(' '.join(map(str, args)) + '\n') - sys.stderr.flush() +# If we have multiple clients we will globally disable introspection +# validation to limit the massive amount of introspection calls we make as +# that method prevents things from executing concurrently +if pv_device_list: + testlib.validate_introspection = False def vg_n(): @@ -55,25 +71,45 @@ THINPOOL_INT: [], JOB_INT: [], SNAPSHOT_INT: [], LV_COMMON_INT: [], CACHE_POOL_INT: [], CACHE_LV_INT: []} - manager = dbus.Interface(bus.get_object( - BUSNAME, "/com/redhat/lvmdbus1"), - "org.freedesktop.DBus.ObjectManager") - - objects = manager.GetManagedObjects() - - for object_path, val in list(objects.items()): - for interface, props in list(val.items()): - o = ClientProxy(bus, object_path, interface, props) - rc[interface].append(o) + object_manager_object = bus.get_object( + BUS_NAME, "/com/redhat/lvmdbus1", introspect=False) + + manager_interface = dbus.Interface(object_manager_object, + "org.freedesktop.DBus.ObjectManager") + + objects = manager_interface.GetManagedObjects() + + for object_path, v in objects.items(): + proxy = ClientProxy(bus, object_path, v) + for interface, prop in v.items(): + if interface == PV_INT: + # If we have a list of PVs to use, lets only use those in + # the list + # noinspection PyUnresolvedReferences + if pv_device_list and not (proxy.Pv.Name in pv_device_list): + continue + rc[interface].append(proxy) return rc, bus -def set_execution(lvmshell): +def set_execution(lvmshell, test_result): + if lvmshell: + m = 'lvm shell (non-fork)' + else: + m = "forking & exec'ing" + lvm_manager = dbus.Interface(bus.get_object( - BUSNAME, "/com/redhat/lvmdbus1/Manager"), + BUS_NAME, "/com/redhat/lvmdbus1/Manager", introspect=False), "com.redhat.lvmdbus1.Manager") - return lvm_manager.UseLvmShell(lvmshell) + rc = lvm_manager.UseLvmShell(lvmshell) + + if rc: + std_err_print('Successfully changed execution mode to "%s"' % m) + else: + std_err_print('ERROR: Failed to change execution mode to "%s"' % m) + test_result.register_fail() + return rc # noinspection PyUnresolvedReferences @@ -90,9 +126,12 @@ std_err_print('Expecting a manager object!') sys.exit(1) - if len(self.objs[VG_INT]) != 0: - std_err_print('Expecting no VGs to exist!') - sys.exit(1) + # We will skip the vg device number check if the test user + # has specified a PV list + if pv_device_list is None: + if len(self.objs[VG_INT]) != 0: + std_err_print('Expecting no VGs to exist!') + sys.exit(1) self.pvs = [] for p in self.objs[PV_INT]: @@ -102,9 +141,23 @@ # If we get here it means we passed setUp, so lets remove anything # and everything that remains, besides the PVs themselves self.objs, self.bus = get_objects() - for v in self.objs[VG_INT]: - # print "DEBUG: Removing VG= ", v.Uuid, v.Name - self.handle_return(v.Vg.Remove(g_tmo, {})) + + if pv_device_list is None: + for v in self.objs[VG_INT]: + self.handle_return( + v.Vg.Remove( + dbus.Int32(g_tmo), + EOD)) + else: + for p in self.objs[PV_INT]: + # When we remove a VG for a PV it could ripple across multiple + # VGs, so update each PV while removing each VG, to ensure + # the properties are current and correct. + p.update() + if p.Pv.Vg != '/': + v = ClientProxy(self.bus, p.Pv.Vg, interfaces=(VG_INT, )) + self.handle_return( + v.Vg.Remove(dbus.Int32(g_tmo), EOD)) # Check to make sure the PVs we had to start exist, else re-create # them @@ -120,6 +173,12 @@ # print('Re-creating PV=', p) self._pv_create(p) + def _check_consistency(self): + # Only do consistency checks if we aren't running the unit tests + # concurrently + if pv_device_list is None: + self.assertEqual(self._refresh(), 0) + def handle_return(self, rc): if isinstance(rc, (tuple, list)): # We have a tuple returned @@ -137,7 +196,7 @@ pv_path = self.handle_return( self.objs[MANAGER_INT][0].Manager.PvCreate( - device, g_tmo, {}) + dbus.String(device), dbus.Int32(g_tmo), EOD) ) self.assertTrue(pv_path is not None and len(pv_path) > 0) return pv_path @@ -149,13 +208,12 @@ return self._manager().Manager.Refresh() def test_refresh(self): - rc = self._refresh() - self.assertEqual(rc, 0) + self._check_consistency() def test_version(self): rc = self.objs[MANAGER_INT][0].Manager.Version self.assertTrue(rc is not None and len(rc) > 0) - self.assertEqual(self._refresh(), 0) + self._check_consistency() def _vg_create(self, pv_paths=None): @@ -166,23 +224,28 @@ vg_path = self.handle_return( self.objs[MANAGER_INT][0].Manager.VgCreate( - vg_name, pv_paths, g_tmo, {})) + dbus.String(vg_name), + dbus.Array(pv_paths, signature=dbus.Signature('o')), + dbus.Int32(g_tmo), + EOD)) self.assertTrue(vg_path is not None and len(vg_path) > 0) - return ClientProxy(self.bus, vg_path) + return ClientProxy(self.bus, vg_path, interfaces=(VG_INT, )) def test_vg_create(self): self._vg_create() - self.assertEqual(self._refresh(), 0) + self._check_consistency() def test_vg_delete(self): vg = self._vg_create().Vg - self.handle_return(vg.Remove(g_tmo, {})) - self.assertEqual(self._refresh(), 0) + self.handle_return( + vg.Remove(dbus.Int32(g_tmo), EOD)) + self._check_consistency() def _pv_remove(self, pv): - rc = self.handle_return(pv.Pv.Remove(g_tmo, {})) + rc = self.handle_return( + pv.Pv.Remove(dbus.Int32(g_tmo), EOD)) return rc def test_pv_remove_add(self): @@ -191,12 +254,12 @@ # Remove the PV rc = self._pv_remove(target) self.assertTrue(rc == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() # Add it back rc = self._pv_create(target.Pv.Name)[0] self.assertTrue(rc == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() def _create_raid5_thin_pool(self, vg=None): @@ -209,20 +272,38 @@ lv_meta_path = self.handle_return( vg.LvCreateRaid( - "meta_r5", "raid5", mib(4), 0, 0, g_tmo, {}) + dbus.String("meta_r5"), + dbus.String("raid5"), + dbus.UInt64(mib(4)), + dbus.UInt32(0), + dbus.UInt32(0), + dbus.Int32(g_tmo), + EOD) ) lv_data_path = self.handle_return( vg.LvCreateRaid( - "data_r5", "raid5", mib(16), 0, 0, g_tmo, {}) + dbus.String("data_r5"), + dbus.String("raid5"), + dbus.UInt64(mib(16)), + dbus.UInt32(0), + dbus.UInt32(0), + dbus.Int32(g_tmo), + EOD) ) thin_pool_path = self.handle_return( - vg.CreateThinPool(lv_meta_path, lv_data_path, g_tmo, {}) + vg.CreateThinPool( + dbus.ObjectPath(lv_meta_path), + dbus.ObjectPath(lv_data_path), + dbus.Int32(g_tmo), EOD) ) # Get thin pool client proxy - thin_pool = ClientProxy(self.bus, thin_pool_path) + thin_pool = ClientProxy(self.bus, thin_pool_path, + interfaces=(LV_COMMON_INT, + LV_INT, + THINPOOL_INT)) return vg, thin_pool @@ -243,11 +324,15 @@ # Cache the thin pool cached_thin_pool_path = self.handle_return( cache_pool.CachePool.CacheLv( - thin_pool.object_path, g_tmo, {}) + dbus.ObjectPath(thin_pool.object_path), + dbus.Int32(g_tmo), EOD) ) # Get object proxy for cached thin pool - cached_thin_pool_object = ClientProxy(self.bus, cached_thin_pool_path) + cached_thin_pool_object = ClientProxy(self.bus, cached_thin_pool_path, + interfaces=(LV_COMMON_INT, + LV_INT, + THINPOOL_INT)) # Check properties on cache pool self.assertTrue(cached_thin_pool_object.ThinPool.DataLv != '/') @@ -279,10 +364,12 @@ vg = self._vg_create([pv_initial.object_path]).Vg path = self.handle_return( - vg.Extend([pv_next.object_path], g_tmo, {}) + vg.Extend( + dbus.Array([pv_next.object_path], signature="o"), + dbus.Int32(g_tmo), EOD) ) self.assertTrue(path == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() # noinspection PyUnresolvedReferences def test_vg_reduce(self): @@ -294,10 +381,12 @@ self.objs[PV_INT][1].object_path]).Vg path = self.handle_return( - vg.Reduce(False, [vg.Pvs[0]], g_tmo, {}) + vg.Reduce( + dbus.Boolean(False), dbus.Array([vg.Pvs[0]], signature='o'), + dbus.Int32(g_tmo), EOD) ) self.assertTrue(path == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() # noinspection PyUnresolvedReferences def test_vg_rename(self): @@ -306,7 +395,7 @@ mgr = self.objs[MANAGER_INT][0].Manager # Do a vg lookup - path = mgr.LookUpByLvmId(vg.Name) + path = mgr.LookUpByLvmId(dbus.String(vg.Name)) vg_name_start = vg.Name @@ -317,17 +406,18 @@ for i in range(0, 5): lv_t = self._create_lv(size=mib(4), vg=vg) full_name = "%s/%s" % (vg_name_start, lv_t.LvCommon.Name) - lv_path = mgr.LookUpByLvmId(full_name) + lv_path = mgr.LookUpByLvmId(dbus.String(full_name)) self.assertTrue(lv_path == lv_t.object_path) new_name = 'renamed_' + vg.Name - path = self.handle_return(vg.Rename(new_name, g_tmo, {})) + path = self.handle_return( + vg.Rename(dbus.String(new_name), dbus.Int32(g_tmo), EOD)) self.assertTrue(path == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() # Do a vg lookup - path = mgr.LookUpByLvmId(new_name) + path = mgr.LookUpByLvmId(dbus.String(new_name)) self.assertTrue(path != '/', "%s" % (path)) self.assertTrue(prev_path == path, "%s != %s" % (prev_path, path)) @@ -339,12 +429,13 @@ self.assertTrue(len(lv_paths) == 5) for l in lv_paths: - lv_proxy = ClientProxy(self.bus, l).LvCommon + lv_proxy = ClientProxy(self.bus, l, + interfaces=(LV_COMMON_INT,)).LvCommon self.assertTrue( lv_proxy.Vg == vg.object_path, "%s != %s" % (lv_proxy.Vg, vg.object_path)) full_name = "%s/%s" % (new_name, lv_proxy.Name) - lv_path = mgr.LookUpByLvmId(full_name) + lv_path = mgr.LookUpByLvmId(dbus.String(full_name)) self.assertTrue( lv_path == lv_proxy.object_path, "%s != %s" % (lv_path, lv_proxy.object_path)) @@ -355,14 +446,15 @@ hidden_lv_paths = lv_common_object.HiddenLvs for h in hidden_lv_paths: - h_lv = ClientProxy(self.bus, h).LvCommon + h_lv = ClientProxy(self.bus, h, + interfaces=(LV_COMMON_INT,)).LvCommon if len(h_lv.HiddenLvs) > 0: self._verify_hidden_lookups(h_lv, vgname) full_name = "%s/%s" % (vgname, h_lv.Name) # print("Hidden check %s" % (full_name)) - lookup_path = mgr.LookUpByLvmId(full_name) + lookup_path = mgr.LookUpByLvmId(dbus.String(full_name)) self.assertTrue(lookup_path != '/') self.assertTrue(lookup_path == h_lv.object_path) @@ -370,7 +462,7 @@ full_name = "%s/%s" % (vgname, h_lv.Name[1:-1]) # print("Hidden check %s" % (full_name)) - lookup_path = mgr.LookUpByLvmId(full_name) + lookup_path = mgr.LookUpByLvmId(dbus.String(full_name)) self.assertTrue(lookup_path != '/') self.assertTrue(lookup_path == h_lv.object_path) @@ -389,23 +481,27 @@ thin_lv_path = self.handle_return( thin_pool.ThinPool.LvCreate( - lv_name, mib(16), g_tmo, {})) + dbus.String(lv_name), + dbus.UInt64(mib(16)), + dbus.Int32(g_tmo), + EOD)) self.assertTrue(thin_lv_path != '/') full_name = "%s/%s" % (vg_name_start, lv_name) - lookup_lv_path = mgr.LookUpByLvmId(full_name) + lookup_lv_path = mgr.LookUpByLvmId(dbus.String(full_name)) self.assertTrue( thin_lv_path == lookup_lv_path, "%s != %s" % (thin_lv_path, lookup_lv_path)) # Rename the VG new_name = 'renamed_' + vg.Name - path = self.handle_return(vg.Rename(new_name, g_tmo, {})) + path = self.handle_return( + vg.Rename(dbus.String(new_name), dbus.Int32(g_tmo), EOD)) self.assertTrue(path == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() # Go through each LV and make sure it has the correct path back to the # VG @@ -415,13 +511,14 @@ lv_paths = vg.Lvs for l in lv_paths: - lv_proxy = ClientProxy(self.bus, l).LvCommon + lv_proxy = ClientProxy(self.bus, l, + interfaces=(LV_COMMON_INT,)).LvCommon self.assertTrue( lv_proxy.Vg == vg.object_path, "%s != %s" % (lv_proxy.Vg, vg.object_path)) full_name = "%s/%s" % (new_name, lv_proxy.Name) # print('Full Name %s' % (full_name)) - lv_path = mgr.LookUpByLvmId(full_name) + lv_path = mgr.LookUpByLvmId(dbus.String(full_name)) self.assertTrue( lv_path == lv_proxy.object_path, "%s != %s" % (lv_path, lv_proxy.object_path)) @@ -429,35 +526,37 @@ # noinspection PyTypeChecker self._verify_hidden_lookups(thin_pool.LvCommon, new_name) - def _test_lv_create(self, method, params, vg): + def _test_lv_create(self, method, params, vg, proxy_interfaces=None): lv = None path = self.handle_return(method(*params)) self.assertTrue(vg) if path: - lv = ClientProxy(self.bus, path) - # TODO verify object properties + lv = ClientProxy(self.bus, path, interfaces=proxy_interfaces) # We are quick enough now that we can get VolumeType changes from # 'I' to 'i' between the time it takes to create a RAID and it returns # and when we refresh state here. Not sure how we can handle this as # we cannot just sit and poll all the time for changes... - # self.assertEqual(self._refresh(), 0) + # self._check_consistency() return lv def test_lv_create(self): vg = self._vg_create().Vg self._test_lv_create( vg.LvCreate, - (lv_n(), mib(4), - dbus.Array([], '(ott)'), g_tmo, {}), vg) + (dbus.String(lv_n()), dbus.UInt64(mib(4)), + dbus.Array([], signature='(ott)'), dbus.Int32(g_tmo), + EOD), vg, LV_BASE_INT) def test_lv_create_job(self): vg = self._vg_create().Vg (object_path, job_path) = vg.LvCreate( - lv_n(), mib(4), dbus.Array([], '(ott)'), 0, {}) + dbus.String(lv_n()), dbus.UInt64(mib(4)), + dbus.Array([], signature='(ott)'), dbus.Int32(0), + EOD) self.assertTrue(object_path == '/') self.assertTrue(job_path != '/') @@ -469,7 +568,9 @@ vg = self._vg_create().Vg self._test_lv_create( vg.LvCreateLinear, - (lv_n(), mib(4), False, g_tmo, {}), vg) + (dbus.String(lv_n()), dbus.UInt64(mib(4)), dbus.Boolean(False), + dbus.Int32(g_tmo), EOD), + vg, LV_BASE_INT) def test_lv_create_striped(self): pv_paths = [] @@ -478,7 +579,11 @@ vg = self._vg_create(pv_paths).Vg self._test_lv_create( - vg.LvCreateStriped, (lv_n(), mib(4), 2, 8, False, g_tmo, {}), vg) + vg.LvCreateStriped, + (dbus.String(lv_n()), dbus.UInt64(mib(4)), + dbus.UInt32(2), dbus.UInt32(8), dbus.Boolean(False), + dbus.Int32(g_tmo), EOD), + vg, LV_BASE_INT) def test_lv_create_mirror(self): pv_paths = [] @@ -487,7 +592,9 @@ vg = self._vg_create(pv_paths).Vg self._test_lv_create( - vg.LvCreateMirror, (lv_n(), mib(4), 2, g_tmo, {}), vg) + vg.LvCreateMirror, + (dbus.String(lv_n()), dbus.UInt64(mib(4)), dbus.UInt32(2), + dbus.Int32(g_tmo), EOD), vg, LV_BASE_INT) def test_lv_create_raid(self): pv_paths = [] @@ -496,10 +603,20 @@ vg = self._vg_create(pv_paths).Vg self._test_lv_create( - vg.LvCreateRaid, (lv_n(), 'raid4', mib(16), 2, 8, g_tmo, {}), vg) + vg.LvCreateRaid, + (dbus.String(lv_n()), dbus.String('raid5'), dbus.UInt64(mib(16)), + dbus.UInt32(2), dbus.UInt32(8), dbus.Int32(g_tmo), + EOD), + vg, + LV_BASE_INT) def _create_lv(self, thinpool=False, size=None, vg=None): + interfaces = list(LV_BASE_INT) + + if thinpool: + interfaces.append(THINPOOL_INT) + if not vg: pv_paths = [] for pp in self.objs[PV_INT]: @@ -512,7 +629,9 @@ return self._test_lv_create( vg.LvCreateLinear, - (lv_n(), size, thinpool, g_tmo, {}), vg) + (dbus.String(lv_n()), dbus.UInt64(size), + dbus.Boolean(thinpool), dbus.Int32(g_tmo), EOD), + vg, interfaces) def test_lv_create_rounding(self): self._create_lv(size=(mib(2) + 13)) @@ -529,11 +648,13 @@ new_name = 'renamed_' + lv.LvCommon.Name - self.handle_return(lv.Lv.Rename(new_name, g_tmo, {})) + self.handle_return(lv.Lv.Rename(dbus.String(new_name), + dbus.Int32(g_tmo), EOD)) - path = self.objs[MANAGER_INT][0].Manager.LookUpByLvmId(new_name) + path = self.objs[MANAGER_INT][0].Manager.LookUpByLvmId( + dbus.String(new_name)) - self.assertEqual(self._refresh(), 0) + self._check_consistency() self.assertTrue(prev_path == path, "%s != %s" % (prev_path, path)) def test_lv_thinpool_rename(self): @@ -544,9 +665,10 @@ "%s" % (tp.object_path)) new_name = 'renamed_' + tp.LvCommon.Name - self.handle_return(tp.Lv.Rename(new_name, g_tmo, {})) + self.handle_return(tp.Lv.Rename( + dbus.String(new_name), dbus.Int32(g_tmo), EOD)) tp.update() - self.assertEqual(self._refresh(), 0) + self._check_consistency() self.assertEqual(new_name, tp.LvCommon.Name) # noinspection PyUnresolvedReferences @@ -559,38 +681,50 @@ thin_path = self.handle_return( tp.ThinPool.LvCreate( - lv_n('_thin_lv'), mib(8), g_tmo, {}) + dbus.String(lv_n('_thin_lv')), + dbus.UInt64(mib(8)), + dbus.Int32(g_tmo), + EOD) ) - lv = ClientProxy(self.bus, thin_path) + lv = ClientProxy(self.bus, thin_path, + interfaces=(LV_COMMON_INT, LV_INT)) rc = self.handle_return( - lv.Lv.Rename('rename_test' + lv.LvCommon.Name, g_tmo, {}) + lv.Lv.Rename( + dbus.String('rename_test' + lv.LvCommon.Name), + dbus.Int32(g_tmo), + EOD) ) self.assertTrue(rc == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() def test_lv_remove(self): lv = self._create_lv().Lv - rc = self.handle_return(lv.Remove(g_tmo, {})) + rc = self.handle_return( + lv.Remove( + dbus.Int32(g_tmo), + EOD)) self.assertTrue(rc == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() def test_lv_snapshot(self): lv_p = self._create_lv() ss_name = 'ss_' + lv_p.LvCommon.Name rc = self.handle_return(lv_p.Lv.Snapshot( - ss_name, 0, g_tmo, {})) + dbus.String(ss_name), + dbus.UInt64(0), + dbus.Int32(g_tmo), + EOD)) self.assertTrue(rc != '/') # noinspection PyUnresolvedReferences def _wait_for_job(self, j_path): - import time rc = None - j = ClientProxy(self.bus, j_path).Job + j = ClientProxy(self.bus, j_path, interfaces=(JOB_INT, )).Job while True: j.update() @@ -617,13 +751,15 @@ pv = vg.Pvs - pvp = ClientProxy(self.bus, pv[0]) + pvp = ClientProxy(self.bus, pv[0], interfaces=(PV_INT,)) self._test_lv_create( - vg.LvCreate, - (lv_n(), mib(4), + vg.LvCreate, ( + dbus.String(lv_n()), + dbus.UInt64(mib(4)), dbus.Array([[pvp.object_path, 0, (pvp.Pv.PeCount - 1)]], - '(ott)'), g_tmo, {}), vg) + signature='(ott)'), + dbus.Int32(g_tmo), EOD), vg, LV_BASE_INT) def test_lv_resize(self): @@ -648,21 +784,23 @@ prev = lv.LvCommon.SizeBytes if len(pv_empty): - p = ClientProxy(self.bus, pv_empty[0]) + p = ClientProxy(self.bus, pv_empty[0], interfaces=(PV_INT,)) rc = self.handle_return( lv.Lv.Resize( - size, + dbus.UInt64(size), dbus.Array( [[p.object_path, 0, p.Pv.PeCount - 1]], '(oii)'), - g_tmo, {})) + dbus.Int32(g_tmo), EOD)) else: rc = self.handle_return( lv.Lv.Resize( - size, dbus.Array([], '(oii)'), g_tmo, {})) + dbus.UInt64(size), + dbus.Array([], '(oii)'), + dbus.Int32(g_tmo), EOD)) self.assertEqual(rc, '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() lv.update() @@ -682,7 +820,9 @@ with self.assertRaises(dbus.exceptions.DBusException): lv.Lv.Resize( - lv.LvCommon.SizeBytes, dbus.Array([], '(oii)'), -1, {}) + dbus.UInt64(lv.LvCommon.SizeBytes), + dbus.Array([], '(oii)'), + dbus.Int32(-1), EOD) def test_lv_move(self): lv = self._create_lv() @@ -692,11 +832,12 @@ # Test moving a specific LV rc = self.handle_return( lv.Lv.Move( - pv_path_move, - (0, 0), - dbus.Array([], '(oii)'), g_tmo, {})) + dbus.ObjectPath(pv_path_move), + dbus.Struct((0, 0), signature='(tt)'), + dbus.Array([], '(ott)'), dbus.Int32(g_tmo), + EOD)) self.assertTrue(rc == '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() lv.update() new_pv = str(lv.LvCommon.Devices[0][0]) @@ -707,39 +848,47 @@ lv_p = self._create_lv() lv_p.update() - self.handle_return(lv_p.Lv.Deactivate(0, g_tmo, {})) + self.handle_return(lv_p.Lv.Deactivate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) lv_p.update() self.assertFalse(lv_p.LvCommon.Active) - self.assertEqual(self._refresh(), 0) + self._check_consistency() - self.handle_return(lv_p.Lv.Activate(0, g_tmo, {})) + self.handle_return(lv_p.Lv.Activate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) lv_p.update() self.assertTrue(lv_p.LvCommon.Active) - self.assertEqual(self._refresh(), 0) + self._check_consistency() # Try control flags for i in range(0, 5): - self.handle_return(lv_p.Lv.Activate(1 << i, g_tmo, {})) + self.handle_return(lv_p.Lv.Activate( + dbus.UInt64(1 << i), + dbus.Int32(g_tmo), + EOD)) self.assertTrue(lv_p.LvCommon.Active) - self.assertEqual(self._refresh(), 0) + self._check_consistency() def test_move(self): lv = self._create_lv() # Test moving without being LV specific - vg = ClientProxy(self.bus, lv.LvCommon.Vg).Vg + vg = ClientProxy(self.bus, lv.LvCommon.Vg, interfaces=(VG_INT, )).Vg pv_to_move = str(lv.LvCommon.Devices[0][0]) - rc = self.handle_return(vg.Move( - pv_to_move, (0, 0), dbus.Array([], '(oii)'), 0, {})) + rc = self.handle_return( + vg.Move( + dbus.ObjectPath(pv_to_move), + dbus.Struct((0, 0), signature='tt'), + dbus.Array([], '(ott)'), + dbus.Int32(0), + EOD)) self.assertEqual(rc, '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() - # Test Vg.Move - # TODO Test this more! vg.update() lv.update() @@ -751,15 +900,18 @@ dst = p # Fetch the destination - pv = ClientProxy(self.bus, dst).Pv + pv = ClientProxy(self.bus, dst, interfaces=(PV_INT, )).Pv # Test range, move it to the middle of the new destination job = self.handle_return( vg.Move( - location, (0, 0), - [(dst, pv.PeCount / 2, 0), ], g_tmo, {})) + dbus.ObjectPath(location), + dbus.Struct((0, 0), signature='tt'), + dbus.Array([(dst, pv.PeCount / 2, 0), ], '(ott)'), + dbus.Int32(g_tmo), + EOD)) self.assertEqual(job, '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() def test_job_handling(self): pv_paths = [] @@ -770,8 +922,10 @@ # Test getting a job right away vg_path, vg_job = self.objs[MANAGER_INT][0].Manager.VgCreate( - vg_name, pv_paths, - 0, {}) + dbus.String(vg_name), + dbus.Array(pv_paths, 'o'), + dbus.Int32(0), + EOD) self.assertTrue(vg_path == '/') self.assertTrue(vg_job and len(vg_job) > 0) @@ -796,7 +950,11 @@ if vg_proxy.Vg.FreeCount > 0: job = self.handle_return( vg_proxy.Vg.LvCreateLinear( - lv_n(), mib(4), False, g_tmo, {})) + dbus.String(lv_n()), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) self.assertTrue(job != '/') else: # We ran out of space, test will probably fail @@ -805,7 +963,7 @@ # Make sure that we are honoring the timeout start = time.time() - remove_job = vg_proxy.Vg.Remove(1, {}) + remove_job = vg_proxy.Vg.Remove(dbus.Int32(1), EOD) end = time.time() @@ -854,12 +1012,16 @@ # Get the PVs for p in vg.Pvs: - pvs.append(ClientProxy(self.bus, p).Pv) + pvs.append(ClientProxy(self.bus, p, interfaces=(PV_INT, )).Pv) for tags_value in [['hello'], ['foo', 'bar']]: rc = self.handle_return( - vg.PvTagsAdd(vg.Pvs, tags_value, g_tmo, {})) + vg.PvTagsAdd( + dbus.Array(vg.Pvs, 'o'), + dbus.Array(tags_value, 's'), + dbus.Int32(g_tmo), + EOD)) self.assertTrue(rc == '/') for p in pvs: @@ -867,7 +1029,11 @@ self.assertTrue(sorted(tags_value) == p.Tags) rc = self.handle_return( - vg.PvTagsDel(vg.Pvs, tags_value, g_tmo, {})) + vg.PvTagsDel( + dbus.Array(vg.Pvs, 'o'), + dbus.Array(tags_value, 's'), + dbus.Int32(g_tmo), + EOD)) self.assertEqual(rc, '/') for p in pvs: @@ -879,12 +1045,20 @@ t = ['Testing', 'tags'] - self.handle_return(vg.TagsAdd(t, g_tmo, {})) + self.handle_return( + vg.TagsAdd( + dbus.Array(t, 's'), + dbus.Int32(g_tmo), + EOD)) vg.update() self.assertTrue(t == vg.Tags) - self.handle_return(vg.TagsDel(t, g_tmo, {})) + self.handle_return( + vg.TagsDel( + dbus.Array(t, 's'), + dbus.Int32(g_tmo), + EOD)) vg.update() self.assertTrue([] == vg.Tags) @@ -892,18 +1066,26 @@ vg = self._vg_create().Vg lv = self._test_lv_create( vg.LvCreateLinear, - (lv_n(), mib(4), False, g_tmo, {}), - vg) + (dbus.String(lv_n()), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD), + vg, LV_BASE_INT) t = ['Testing', 'tags'] self.handle_return( - lv.Lv.TagsAdd(t, g_tmo, {})) + lv.Lv.TagsAdd( + dbus.Array(t, 's'), dbus.Int32(g_tmo), EOD)) lv.update() self.assertTrue(t == lv.LvCommon.Tags) self.handle_return( - lv.Lv.TagsDel(t, g_tmo, {})) + lv.Lv.TagsDel( + dbus.Array(t, 's'), + dbus.Int32(g_tmo), + EOD)) lv.update() self.assertTrue([] == lv.LvCommon.Tags) @@ -912,7 +1094,8 @@ for p in ['anywhere', 'contiguous', 'cling', 'normal']: rc = self.handle_return( - vg.AllocationPolicySet(p, g_tmo, {})) + vg.AllocationPolicySet( + dbus.String(p), dbus.Int32(g_tmo), EOD)) self.assertEqual(rc, '/') vg.update() @@ -927,7 +1110,8 @@ # TODO: Add a test back for larger values here when bug is resolved for p in [0, 1, 10, 100, 100, 1024, 2 ** 32 - 1]: rc = self.handle_return( - vg.MaxPvSet(p, g_tmo, {})) + vg.MaxPvSet( + dbus.UInt64(p), dbus.Int32(g_tmo), EOD)) self.assertEqual(rc, '/') vg.update() self.assertTrue( @@ -940,7 +1124,9 @@ # BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1280496 # TODO: Add a test back for larger values here when bug is resolved for p in [0, 1, 10, 100, 100, 1024, 2 ** 32 - 1]: - rc = self.handle_return(vg.MaxLvSet(p, g_tmo, {})) + rc = self.handle_return( + vg.MaxLvSet( + dbus.UInt64(p), dbus.Int32(g_tmo), EOD)) self.assertEqual(rc, '/') vg.update() self.assertTrue( @@ -948,62 +1134,80 @@ "Expected %s != Actual %s" % (str(p), str(vg.MaxLv))) def test_vg_uuid_gen(self): - # TODO renable test case when - # https://bugzilla.redhat.com/show_bug.cgi?id=1264169 gets fixed - # This was tested with lvmetad disabled and we passed - std_err_print("\nSkipping Vg.UuidGenerate until BZ: 1264169 resolved\n") - - if False: - vg = self._vg_create().Vg - prev_uuid = vg.Uuid - rc = self.handle_return(vg.UuidGenerate(g_tmo, {})) - self.assertEqual(rc, '/') - vg.update() - self.assertTrue( - vg.Uuid != prev_uuid, - "Expected %s != Actual %s" % (vg.Uuid, prev_uuid)) + vg = self._vg_create().Vg + prev_uuid = vg.Uuid + rc = self.handle_return( + vg.UuidGenerate( + dbus.Int32(g_tmo), + EOD)) + self.assertEqual(rc, '/') + vg.update() + self.assertTrue( + vg.Uuid != prev_uuid, + "Expected %s != Actual %s" % (vg.Uuid, prev_uuid)) def test_vg_activate_deactivate(self): vg = self._vg_create().Vg self._test_lv_create( - vg.LvCreateLinear, - (lv_n(), mib(4), False, g_tmo, {}), - vg) + vg.LvCreateLinear, ( + dbus.String(lv_n()), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD), + vg, LV_BASE_INT) vg.update() - rc = self.handle_return(vg.Deactivate(0, g_tmo, {})) + rc = self.handle_return( + vg.Deactivate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) self.assertEqual(rc, '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() - rc = self.handle_return(vg.Activate(0, g_tmo, {})) + rc = self.handle_return( + vg.Activate( + dbus.UInt64(0), dbus.Int32(g_tmo), EOD)) self.assertEqual(rc, '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() # Try control flags for i in range(0, 5): - self.handle_return(vg.Activate(1 << i, g_tmo, {})) + self.handle_return( + vg.Activate( + dbus.UInt64(1 << i), + dbus.Int32(g_tmo), + EOD)) def test_pv_resize(self): self.assertTrue(len(self.objs[PV_INT]) > 0) if len(self.objs[PV_INT]) > 0: - pv = ClientProxy(self.bus, self.objs[PV_INT][0].object_path).Pv + pv = ClientProxy(self.bus, self.objs[PV_INT][0].object_path, + interfaces=(PV_INT, )).Pv original_size = pv.SizeBytes new_size = original_size / 2 - self.handle_return(pv.ReSize(new_size, g_tmo, {})) + self.handle_return( + pv.ReSize( + dbus.UInt64(new_size), + dbus.Int32(g_tmo), + EOD)) - self.assertEqual(self._refresh(), 0) + self._check_consistency() pv.update() self.assertTrue(pv.SizeBytes != original_size) - self.handle_return(pv.ReSize(0, g_tmo, {})) - self.assertEqual(self._refresh(), 0) + self.handle_return( + pv.ReSize( + dbus.UInt64(0), + dbus.Int32(g_tmo), + EOD)) + self._check_consistency() pv.update() self.assertTrue(pv.SizeBytes == original_size) @@ -1015,20 +1219,32 @@ vg = self._vg_create(pv_paths).Vg - pv = ClientProxy(self.bus, vg.Pvs[0]).Pv + pv = ClientProxy(self.bus, vg.Pvs[0], interfaces=(PV_INT, )).Pv - self.handle_return(pv.AllocationEnabled(False, g_tmo, {})) + self.handle_return( + pv.AllocationEnabled( + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) pv.update() self.assertFalse(pv.Allocatable) - self.handle_return(pv.AllocationEnabled(True, g_tmo, {})) + self.handle_return( + pv.AllocationEnabled( + dbus.Boolean(True), + dbus.Int32(g_tmo), + EOD)) - self.handle_return(pv.AllocationEnabled(True, g_tmo, {})) + self.handle_return( + pv.AllocationEnabled( + dbus.Boolean(True), + dbus.Int32(g_tmo), + EOD)) pv.update() self.assertTrue(pv.Allocatable) - self.assertEqual(self._refresh(), 0) + self._check_consistency() @staticmethod def _get_devices(): @@ -1043,18 +1259,25 @@ self.assertEqual( self.handle_return( mgr.PvScan( - False, True, dbus.Array([], 's'), - dbus.Array([], '(ii)'), g_tmo, {})), '/') + dbus.Boolean(False), + dbus.Boolean(True), + dbus.Array([], 's'), + dbus.Array([], '(ii)'), + dbus.Int32(g_tmo), + EOD)), '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() self.assertEqual( self.handle_return( mgr.PvScan( - False, False, + dbus.Boolean(False), + dbus.Boolean(False), dbus.Array([], 's'), - dbus.Array([], '(ii)'), g_tmo, {})), '/') + dbus.Array([], '(ii)'), + dbus.Int32(g_tmo), + EOD)), '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() block_path = [] for d in devices: @@ -1063,11 +1286,14 @@ self.assertEqual( self.handle_return( mgr.PvScan( - False, True, - block_path, - dbus.Array([], '(ii)'), g_tmo, {})), '/') + dbus.Boolean(False), + dbus.Boolean(True), + dbus.Array(block_path, 's'), + dbus.Array([], '(ii)'), + dbus.Int32(g_tmo), + EOD)), '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() mm = [] for d in devices: @@ -1075,17 +1301,26 @@ self.assertEqual( self.handle_return( - mgr.PvScan(False, True, block_path, mm, g_tmo, {})), '/') + mgr.PvScan( + dbus.Boolean(False), + dbus.Boolean(True), + dbus.Array(block_path, 's'), + dbus.Array(mm, '(ii)'), + dbus.Int32(g_tmo), + EOD)), '/') - self.assertEqual(self._refresh(), 0) + self._check_consistency() self.assertEqual( self.handle_return( mgr.PvScan( - False, True, + dbus.Boolean(False), + dbus.Boolean(True), dbus.Array([], 's'), - mm, g_tmo, {})), '/') - self.assertEqual(self._refresh(), 0) + dbus.Array(mm, '(ii)'), + dbus.Int32(g_tmo), + EOD)), '/') + self._check_consistency() @staticmethod def _write_some_data(device_path, size): @@ -1106,14 +1341,22 @@ ss_name = lv_p.LvCommon.Name + '_snap' snapshot_path = self.handle_return( - lv_p.Lv.Snapshot(ss_name, ss_size, g_tmo, {})) + lv_p.Lv.Snapshot( + dbus.String(ss_name), + dbus.UInt64(ss_size), + dbus.Int32(g_tmo), + EOD)) - ss = ClientProxy(self.bus, snapshot_path) + ss = ClientProxy(self.bus, snapshot_path, + interfaces=(LV_COMMON_INT, LV_INT, SNAPSHOT_INT, )) # Write some data to snapshot so merge takes some time TestDbusService._write_some_data(ss.LvCommon.Path, ss_size / 2) - job_path = self.handle_return(ss.Snapshot.Merge(g_tmo, {})) + job_path = self.handle_return( + ss.Snapshot.Merge( + dbus.Int32(g_tmo), + EOD)) self.assertEqual(job_path, '/') def test_snapshot_merge_thin(self): @@ -1122,17 +1365,28 @@ thin_path = self.handle_return( tp.ThinPool.LvCreate( - lv_n('_thin_lv'), mib(10), g_tmo, {})) + dbus.String(lv_n('_thin_lv')), + dbus.UInt64(mib(10)), + dbus.Int32(g_tmo), + EOD)) - lv_p = ClientProxy(self.bus, thin_path) + lv_p = ClientProxy(self.bus, thin_path, + interfaces=(LV_INT, LV_COMMON_INT)) ss_name = lv_p.LvCommon.Name + '_snap' snapshot_path = self.handle_return( - lv_p.Lv.Snapshot(ss_name, 0, g_tmo, {})) + lv_p.Lv.Snapshot( + dbus.String(ss_name), + dbus.UInt64(0), + dbus.Int32(g_tmo), + EOD)) + + ss = ClientProxy(self.bus, snapshot_path, + interfaces=(LV_INT, LV_COMMON_INT, SNAPSHOT_INT)) - ss = ClientProxy(self.bus, snapshot_path) job_path = self.handle_return( - ss.Snapshot.Merge(g_tmo, {}) + ss.Snapshot.Merge( + dbus.Int32(g_tmo), EOD) ) self.assertTrue(job_path == '/') @@ -1146,9 +1400,13 @@ cache_pool_path = self.handle_return( vg.CreateCachePool( - md.object_path, data.object_path, g_tmo, {})) + dbus.ObjectPath(md.object_path), + dbus.ObjectPath(data.object_path), + dbus.Int32(g_tmo), + EOD)) - cp = ClientProxy(self.bus, cache_pool_path) + cp = ClientProxy(self.bus, cache_pool_path, + interfaces=(CACHE_POOL_INT, )) return vg, cp @@ -1168,29 +1426,39 @@ c_lv_path = self.handle_return( cache_pool.CachePool.CacheLv( - lv_to_cache.object_path, g_tmo, {})) - - cached_lv = ClientProxy(self.bus, c_lv_path) + dbus.ObjectPath(lv_to_cache.object_path), + dbus.Int32(g_tmo), + EOD)) + + cached_lv = ClientProxy(self.bus, c_lv_path, + interfaces=(LV_COMMON_INT, LV_INT, + CACHE_LV_INT)) uncached_lv_path = self.handle_return( - cached_lv.CachedLv.DetachCachePool(destroy_cache, g_tmo, {})) + cached_lv.CachedLv.DetachCachePool( + dbus.Boolean(destroy_cache), + dbus.Int32(g_tmo), + EOD)) self.assertTrue( '/com/redhat/lvmdbus1/Lv' in uncached_lv_path) - rc = self.handle_return(vg.Remove(g_tmo, {})) + rc = self.handle_return( + vg.Remove(dbus.Int32(g_tmo), EOD)) self.assertTrue(rc == '/') def test_vg_change(self): vg_proxy = self._vg_create() result = self.handle_return(vg_proxy.Vg.Change( - g_tmo, {'-a': 'ay'})) + dbus.Int32(g_tmo), + dbus.Dictionary({'-a': 'ay'}, 'sv'))) self.assertTrue(result == '/') result = self.handle_return( - vg_proxy.Vg.Change(g_tmo, {'-a': 'n'}) - ) + vg_proxy.Vg.Change( + dbus.Int32(g_tmo), + dbus.Dictionary({'-a': 'n'}, 'sv'))) self.assertTrue(result == '/') @staticmethod @@ -1205,7 +1473,10 @@ # Pv device path with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( - mgr.PvCreate("/dev/space in name", g_tmo, {})) + mgr.PvCreate( + dbus.String("/dev/space in name"), + dbus.Int32(g_tmo), + EOD)) # VG Name testing... # Go through all bad characters @@ -1214,32 +1485,51 @@ for c in bad_chars: with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( - mgr.VgCreate("name%s" % (c), pv_paths, g_tmo, {})) + mgr.VgCreate( + dbus.String("name%s" % (c)), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) # Bad names for bad in [".", ".."]: with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( - mgr.VgCreate(bad, pv_paths, g_tmo, {})) + mgr.VgCreate( + dbus.String(bad), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) # Exceed name length for i in [128, 1024, 4096]: with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( - mgr.VgCreate('T' * i, pv_paths, g_tmo, {})) + mgr.VgCreate( + dbus.String('T' * i), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) # Create a VG and try to create LVs with different bad names vg_path = self.handle_return( - mgr.VgCreate("test", pv_paths, g_tmo, {})) + mgr.VgCreate( + dbus.String(vg_n()), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) - vg_proxy = ClientProxy(self.bus, vg_path) + vg_proxy = ClientProxy(self.bus, vg_path, interfaces=(VG_INT, )) for c in bad_chars: with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( vg_proxy.Vg.LvCreateLinear( - lv_n() + c, - mib(4), False, g_tmo, {})) + dbus.String(lv_n() + c), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) for reserved in ( "_cdata", "_cmeta", "_corig", "_mimage", "_mlog", @@ -1248,15 +1538,21 @@ with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( vg_proxy.Vg.LvCreateLinear( - lv_n() + reserved, - mib(4), False, g_tmo, {})) + dbus.String(lv_n() + reserved), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) for reserved in ("snapshot", "pvmove"): with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( vg_proxy.Vg.LvCreateLinear( - reserved + lv_n(), - mib(4), False, g_tmo, {})) + dbus.String(reserved + lv_n()), + dbus.UInt64(mib(4)), + dbus.Boolean(False), + dbus.Int32(g_tmo), + EOD)) _ALLOWABLE_TAG_CH = string.ascii_letters + string.digits + "._-+/=!:&#" @@ -1269,34 +1565,49 @@ pv_paths = [self.objs[PV_INT][0].object_path] vg_path = self.handle_return( - mgr.VgCreate("test", pv_paths, g_tmo, {})) - vg_proxy = ClientProxy(self.bus, vg_path) + mgr.VgCreate( + dbus.String(vg_n()), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) + vg_proxy = ClientProxy(self.bus, vg_path, interfaces=(VG_INT, )) for c in self._invalid_tag_characters(): with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( vg_proxy.Vg.TagsAdd( - [c], g_tmo, {})) + dbus.Array([c], 's'), + dbus.Int32(g_tmo), + EOD)) for c in self._invalid_tag_characters(): with self.assertRaises(dbus.exceptions.DBusException): self.handle_return( vg_proxy.Vg.TagsAdd( - ["a%sb" % (c)], g_tmo, {})) + dbus.Array(["a%sb" % (c)], 's'), + dbus.Int32(g_tmo), + EOD)) def test_tag_names(self): mgr = self.objs[MANAGER_INT][0].Manager pv_paths = [self.objs[PV_INT][0].object_path] vg_path = self.handle_return( - mgr.VgCreate("test", pv_paths, g_tmo, {})) - vg_proxy = ClientProxy(self.bus, vg_path) + mgr.VgCreate( + dbus.String(vg_n()), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) + vg_proxy = ClientProxy(self.bus, vg_path, interfaces=(VG_INT, )) for i in range(1, 64): tag = rs(i, "", self._ALLOWABLE_TAG_CH) tmp = self.handle_return( - vg_proxy.Vg.TagsAdd([tag], g_tmo, {})) + vg_proxy.Vg.TagsAdd( + dbus.Array([tag], 's'), + dbus.Int32(g_tmo), + EOD)) self.assertTrue(tmp == '/') vg_proxy.update() @@ -1313,14 +1624,20 @@ pv_paths = [self.objs[PV_INT][0].object_path] vg_path = self.handle_return( - mgr.VgCreate("test", pv_paths, g_tmo, {})) - vg_proxy = ClientProxy(self.bus, vg_path) + mgr.VgCreate( + dbus.String(vg_n()), + dbus.Array(pv_paths, 'o'), + dbus.Int32(g_tmo), + EOD)) + vg_proxy = ClientProxy(self.bus, vg_path, interfaces=(VG_INT, )) tag = '--h/K.6g0A4FOEatf3+k_nI/Yp&L_u2oy-=j649x:+dUcYWPEo6.IWT0c' tmp = self.handle_return( - vg_proxy.Vg.TagsAdd([tag], g_tmo, {}) - ) + vg_proxy.Vg.TagsAdd( + dbus.Array([tag], 's'), + dbus.Int32(g_tmo), + EOD)) self.assertTrue(tmp == '/') vg_proxy.update() @@ -1350,32 +1667,30 @@ if __name__ == '__main__': r = AggregateResults() + mode = int(test_shell) - # Test forking & exec new each time - test_shell = os.getenv('LVM_DBUS_TEST_SHELL', 1) - - # Default to no lvm shell - set_execution(False) - - if int(test_shell) == 0: - std_err_print('\n Running only lvm fork & exec test ***\n') - r.register_result(unittest.main(exit=False)) + if mode == 0: + std_err_print('\n*** Testing only lvm fork & exec test mode ***\n') + elif mode == 1: + std_err_print('\n*** Testing fork & exec & lvm shell mode ***\n') else: - std_err_print('\n *** Testing with lvm fork & exec *** \n') - r.register_result(unittest.main(exit=False)) - g_tmo = 15 - r.register_result(unittest.main(exit=False)) - # Test lvm shell - std_err_print('\n *** Testing with lvm shell *** \n') - if set_execution(True): - g_tmo = 0 - r.register_result(unittest.main(exit=False)) - g_tmo = 15 - r.register_result(unittest.main(exit=False)) + std_err_print('\n*** Testing only lvm shell mode ***\n') + + for g_tmo in [0, 15]: + if mode == 0: + if set_execution(False, r): + r.register_result(unittest.main(exit=False)) + elif mode == 2: + if set_execution(True, r): + r.register_result(unittest.main(exit=False)) else: - r.register_fail() - std_err_print( - "ERROR: Unable to dynamically configure service to use " - "lvm shell!") + if set_execution(False, r): + r.register_result(unittest.main(exit=False)) + # Test lvm shell + if set_execution(True, r): + r.register_result(unittest.main(exit=False)) + + if not r.no_errors: + break r.exit_run() diff -Nru lvm2-2.02.167/test/dbus/testlib.py lvm2-2.02.168/test/dbus/testlib.py --- lvm2-2.02.167/test/dbus/testlib.py 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/dbus/testlib.py 2016-11-30 23:17:31.000000000 +0000 @@ -14,23 +14,28 @@ import xml.etree.ElementTree as Et from collections import OrderedDict import dbus +import os +import sys -BUSNAME = "com.redhat.lvmdbus1" -MANAGER_INT = BUSNAME + '.Manager' -MANAGER_OBJ = '/' + BUSNAME.replace('.', '/') + '/Manager' -PV_INT = BUSNAME + ".Pv" -VG_INT = BUSNAME + ".Vg" -LV_INT = BUSNAME + ".Lv" -THINPOOL_INT = BUSNAME + ".ThinPool" -SNAPSHOT_INT = BUSNAME + ".Snapshot" -LV_COMMON_INT = BUSNAME + ".LvCommon" -JOB_INT = BUSNAME + ".Job" -CACHE_POOL_INT = BUSNAME + ".CachePool" -CACHE_LV_INT = BUSNAME + ".CachedLv" - +BUS_NAME = os.getenv('LVM_DBUS_NAME', 'com.redhat.lvmdbus1') +BASE_INTERFACE = 'com.redhat.lvmdbus1' +MANAGER_INT = BASE_INTERFACE + '.Manager' +MANAGER_OBJ = '/' + BASE_INTERFACE.replace('.', '/') + '/Manager' +PV_INT = BASE_INTERFACE + ".Pv" +VG_INT = BASE_INTERFACE + ".Vg" +LV_INT = BASE_INTERFACE + ".Lv" +THINPOOL_INT = BASE_INTERFACE + ".ThinPool" +SNAPSHOT_INT = BASE_INTERFACE + ".Snapshot" +LV_COMMON_INT = BASE_INTERFACE + ".LvCommon" +JOB_INT = BASE_INTERFACE + ".Job" +CACHE_POOL_INT = BASE_INTERFACE + ".CachePool" +CACHE_LV_INT = BASE_INTERFACE + ".CachedLv" THINPOOL_LV_PATH = '/' + THINPOOL_INT.replace('.', '/') +validate_introspection = True + + def rs(length, suffix, character_set=string.ascii_lowercase): return ''.join(random.choice(character_set) for _ in range(length)) + suffix @@ -39,6 +44,11 @@ return 1024 * 1024 * s +def std_err_print(*args): + sys.stderr.write(' '.join(map(str, args)) + '\n') + sys.stderr.flush() + + class DbusIntrospection(object): @staticmethod def introspect(xml_representation): @@ -152,19 +162,14 @@ (dbus_str_rep, actual_str_rep, str(type(value)))) -class RemoteObject(object): +class RemoteInterface(object): def _set_props(self, props=None): - # print 'Fetching properties' if not props: - # prop_fetch = dbus.Interface(self.bus.get_object( - # BUSNAME, self.object_path), 'org.freedesktop.DBus.Properties') - - for i in range(0, 3): + for _ in range(0, 3): try: - prop_fetch = dbus.Interface(self.bus.get_object( - BUSNAME, self.object_path), + prop_interface = dbus.Interface(self.dbus_object, 'org.freedesktop.DBus.Properties') - props = prop_fetch.GetAll(self.interface) + props = prop_interface.GetAll(self.interface) break except dbus.exceptions.DBusException as dbe: if "GetAll" not in str(dbe): @@ -172,42 +177,42 @@ if props: for kl, vl in list(props.items()): # Verify type is correct! - verify_type( - vl, - self.introspect[self.interface]['properties'][kl]['p_type']) + if self.introspect: + verify_type(vl, self.introspect[self.interface] + ['properties'][kl]['p_type']) setattr(self, kl, vl) + @property + def object_path(self): + return self.dbus_object.object_path + def __init__( - self, specified_bus, object_path, interface, introspect, + self, dbus_object, interface, introspect, properties=None): - self.object_path = object_path + self.dbus_object = dbus_object self.interface = interface - self.bus = specified_bus self.introspect = introspect - self.dbus_method = dbus.Interface(specified_bus.get_object( - BUSNAME, self.object_path), self.interface) - + self.dbus_interface = dbus.Interface(self.dbus_object, self.interface) self._set_props(properties) def __getattr__(self, item): - if hasattr(self.dbus_method, item): + if hasattr(self.dbus_interface, item): return functools.partial(self._wrapper, item) else: return functools.partial(self, item) def _wrapper(self, _method_name, *args, **kwargs): - result = getattr(self.dbus_method, _method_name)(*args, **kwargs) - # print("DEBUG: %s.%s result %s" % - # (self.interface, _method_name, str(type(result)))) - - if 'RETURN_VALUE' in self.introspect[ - self.interface]['methods'][_method_name]: - r_type = self.introspect[ - self.interface]['methods'][ - _method_name]['RETURN_VALUE']['a_type'] + result = getattr(self.dbus_interface, _method_name)(*args, **kwargs) + + if self.introspect: + if 'RETURN_VALUE' in self.introspect[ + self.interface]['methods'][_method_name]: + r_type = self.introspect[ + self.interface]['methods'][ + _method_name]['RETURN_VALUE']['a_type'] - verify_type(result, r_type) + verify_type(result, r_type) return result @@ -220,36 +225,55 @@ def _intf_short_name(nm): return nm.split('.')[-1:][0] - def __init__(self, specified_bus, object_path, interface=None, props=None): - i = dbus.Interface(specified_bus.get_object( - BUSNAME, object_path), 'org.freedesktop.DBus.Introspectable') - - introspection_xml = i.Introspect() - - # import xml.dom.minidom - # - # xml = xml.dom.minidom.parseString(introspection_xml) - # print(xml.toprettyxml()) - - self.intro_spect = DbusIntrospection.introspect(introspection_xml) - - for k in self.intro_spect.keys(): - sn = ClientProxy._intf_short_name(k) - # print('Client proxy has interface: %s %s' % (k, sn)) - - if interface and interface == k and props is not None: - ro = RemoteObject( - specified_bus, object_path, k, self.intro_spect, props) - else: - ro = RemoteObject( - specified_bus, object_path, k, self.intro_spect) - - setattr(self, sn, ro) + def get_introspect(self): + i = dbus.Interface( + self.dbus_object, + 'org.freedesktop.DBus.Introspectable') + + return DbusIntrospection.introspect(i.Introspect()) + + def _common(self, interface, introspect, properties): + short_name = ClientProxy._intf_short_name(interface) + self.short_interface_names.append(short_name) + ro = RemoteInterface(self.dbus_object, interface, introspect, + properties) + setattr(self, short_name, ro) + def __init__(self, bus, object_path, interface_prop_hash=None, + interfaces=None): self.object_path = object_path + self.short_interface_names = [] + self.dbus_object = bus.get_object( + BUS_NAME, self.object_path, introspect=False) + + if interface_prop_hash: + assert interfaces is None + if interfaces: + assert interface_prop_hash is None + + if interface_prop_hash and not validate_introspection: + # We have everything including the values of the properties + for i, props in interface_prop_hash.items(): + self._common(i, None, props) + elif interfaces and not validate_introspection: + # We are retrieving the values of the properties + for i in interfaces: + self._common(i, None, None) + else: + # We need to query the interfaces and gather all the properties + # for each interface, as we have the introspection data we + # will also utilize it to verify what we get back verifies + introspect = self.get_introspect() + + if interface_prop_hash: + introspect_interfaces = list(introspect.keys()) + for object_manager_key in interface_prop_hash.keys(): + assert object_manager_key in introspect_interfaces + + for i in list(introspect.keys()): + self._common(i, introspect, None) def update(self): # Go through all interfaces and update them - for int_f in self.intro_spect.keys(): - sn = ClientProxy._intf_short_name(int_f) + for sn in self.short_interface_names: getattr(self, sn).update() diff -Nru lvm2-2.02.167/test/lib/aux.sh lvm2-2.02.168/test/lib/aux.sh --- lvm2-2.02.167/test/lib/aux.sh 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/lib/aux.sh 2016-11-30 23:17:31.000000000 +0000 @@ -1063,7 +1063,7 @@ cat > "$config_values" <<-EOF activation/checks = 1 activation/monitoring = 0 -activation/polling_interval = 0 +activation/polling_interval = 1 activation/retry_deactivation = 1 activation/snapshot_autoextend_percent = 50 activation/snapshot_autoextend_threshold = 50 diff -Nru lvm2-2.02.167/test/Makefile.in lvm2-2.02.168/test/Makefile.in --- lvm2-2.02.167/test/Makefile.in 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/Makefile.in 2016-11-30 23:17:31.000000000 +0000 @@ -77,6 +77,9 @@ @echo " check_cluster Run tests with cluster daemon." @echo " check_lvmetad Run tests with lvmetad daemon." @echo " check_lvmpolld Run tests with lvmpolld daemon." + @echo " check_cluster_lvmpolld Run tests with clvmd and lvmpolld daemon." + @echo " check_lvmetad_lvmpolld Run tests with lvmetad and lvmpolld daemon." + @echo " check_all_lvmpolld Run all tests with lvmpolld daemon." @echo " check_lvmlockd_sanlock Run tests with lvmlockd and sanlock." @echo " check_lvmlockd_dlm Run tests with lvmlockd and dlm." @echo " check_lvmlockd_test Run tests with lvmlockd --test." @@ -146,6 +149,21 @@ check_lvmpolld: .tests-stamp VERBOSE=$(VERBOSE) ./lib/runner \ --testdir . --outdir results \ + --flavours ndev-lvmpolld --only $(T) --skip $(S) + +check_cluster_lvmpolld: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir results \ + --flavours ndev-cluster-lvmpolld --only $(T) --skip $(S) + +check_lvmetad_lvmpolld: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir results \ + --flavours ndev-lvmetad-lvmpolld --only $(T) --skip $(S) + +check_all_lvmpolld: .tests-stamp + VERBOSE=$(VERBOSE) ./lib/runner \ + --testdir . --outdir results \ --flavours ndev-lvmpolld,ndev-cluster-lvmpolld,ndev-lvmetad-lvmpolld --only $(T) --skip $(S) endif @@ -215,7 +233,7 @@ dm-version-expected \ version-expected \ $(DATADIR)/lib - @for i in cache-mq cache-smq thin-performance ; do \ + @for i in cache-mq cache-smq thin-performance lvmdbusd ; do \ echo "$(INSTALL_DATA) $(abs_top_srcdir)/conf/$$i.profile $(DATADIR)/lib"; \ $(INSTALL_DATA) $(abs_top_srcdir)/conf/$$i.profile $(DATADIR)/lib; done cd lib && $(INSTALL_SCRIPT) $(LIB_SHARED) $(DATADIR)/lib @@ -277,14 +295,12 @@ $(RM) $@-t cat lib/paths-common > $@-t echo 'installed_testsuite=1' >> $@-t - echo 'test_data_dir="@datadir@/lvm2-testsuite"' >> $@-t echo 'export PATH=@libexecdir@/lvm2-testsuite:@datadir@/lvm2-testsuite/lib:@datadir@/lvm2-testsuite/api:$$PATH' >> $@-t mv $@-t $@ lib/paths: lib/paths-common $(RM) $@-t cat lib/paths-common > $@-t - echo 'test_data_dir="$(abs_top_builddir)/test"' >> $@-t echo 'top_srcdir="$(top_srcdir)"' >> $@-t echo 'abs_top_builddir="$(abs_top_builddir)"' >> $@-t echo 'abs_top_srcdir="$(abs_top_srcdir)"' >> $@-t @@ -320,6 +336,7 @@ daemons/lvmpolld/lvmpolld ; do \ $(LN_S) -f $(abs_top_builddir)/$$i lib/; done $(LN_S) -f $(abs_top_builddir)/tools/dmsetup lib/dmstats + $(LN_S) -f $(abs_top_srcdir)/conf/lvmdbusd.profile lib/ $(LN_S) -f $(abs_top_srcdir)/conf/thin-performance.profile lib/ $(LN_S) -f $(abs_top_srcdir)/scripts/fsadm.sh lib/fsadm test "$(srcdir)" = . || for i in $(LIB_LVMLOCKD_CONF); do \ @@ -333,7 +350,7 @@ CLEAN_TARGETS += .lib-dir-stamp .tests-stamp $(LIB) $(addprefix lib/,\ $(CMDS) clvmd dmeventd dmsetup dmstats lvmetad lvmpolld \ - harness thin-performance.profile fsadm \ + harness lvmdbusd.profile thin-performance.profile fsadm \ dm-version-expected version-expected \ paths-installed paths-installed-t paths-common paths-common-t) diff -Nru lvm2-2.02.167/test/shell/lvconvert-repair-cache.sh lvm2-2.02.168/test/shell/lvconvert-repair-cache.sh --- lvm2-2.02.167/test/shell/lvconvert-repair-cache.sh 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/shell/lvconvert-repair-cache.sh 2016-11-30 23:17:32.000000000 +0000 @@ -25,7 +25,8 @@ # # Main # -aux have_cache 1 5 0 || skip +# older versions of cache target reported unreliably write failures +aux have_cache 1 7 0 || skip aux prepare_vg 4 diff -Nru lvm2-2.02.167/test/shell/lvcreate-raid-nosync.sh lvm2-2.02.168/test/shell/lvcreate-raid-nosync.sh --- lvm2-2.02.167/test/shell/lvcreate-raid-nosync.sh 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/shell/lvcreate-raid-nosync.sh 2016-11-30 23:17:32.000000000 +0000 @@ -24,12 +24,12 @@ # Delay 1st leg so that rebuilding status characters # can be read before resync finished too quick. -aux delay_dev "$dev1" 0 10 $(get first_extent_sector "$dev1") +aux delay_dev "$dev1" 0 50 $(get first_extent_sector "$dev1") # raid0/raid0_meta don't support resynchronization for r in raid0 raid0_meta do - lvcreate --yes --type raid0 -i 3 -l 1 -n $lv1 $vg + lvcreate --yes --type $r -i 3 -l 1 -n $lv1 $vg check raid_leg_status $vg $lv1 "AAA" lvremove --yes $vg/$lv1 done @@ -47,7 +47,7 @@ lvremove --yes $vg/$lv1 for r in $segtypes -do +do # raid4/5 support resynchronization lvcreate --yes --type $r -i 3 -l 2 -n $lv1 $vg check raid_leg_status $vg $lv1 "aaaa" diff -Nru lvm2-2.02.167/test/shell/pvmove-resume-2.sh lvm2-2.02.168/test/shell/pvmove-resume-2.sh --- lvm2-2.02.167/test/shell/pvmove-resume-2.sh 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/shell/pvmove-resume-2.sh 2016-11-30 23:17:32.000000000 +0000 @@ -76,7 +76,7 @@ aux enable_dev "$dev2" i=0 - while get lv_field $vg name -a | grep "^pvmove"; do + while get lv_field $vg name -a | egrep "^\[?pvmove"; do # wait for 30 secs at max test $i -ge 300 && die "Pvmove is too slow or does not progress." sleep .1 diff -Nru lvm2-2.02.167/test/shell/pvmove-resume-multiseg.sh lvm2-2.02.168/test/shell/pvmove-resume-multiseg.sh --- lvm2-2.02.167/test/shell/pvmove-resume-multiseg.sh 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/shell/pvmove-resume-multiseg.sh 2016-11-30 23:17:32.000000000 +0000 @@ -89,7 +89,7 @@ aux enable_dev "$dev5" i=0 - while get lv_field $vg name -a | grep "^\[?pvmove"; do + while get lv_field $vg name -a | egrep "^\[?pvmove"; do # wait for 30 secs at max test $i -ge 300 && die "Pvmove is too slow or does not progress." sleep .1 diff -Nru lvm2-2.02.167/test/shell/snapshot-merge-stack.sh lvm2-2.02.168/test/shell/snapshot-merge-stack.sh --- lvm2-2.02.167/test/shell/snapshot-merge-stack.sh 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/shell/snapshot-merge-stack.sh 2016-11-30 23:17:32.000000000 +0000 @@ -40,13 +40,14 @@ kill $SLEEP_PID aux delay_dev "$dev1" 0 200 $(get first_extent_sector "$dev1"): - lvchange --refresh $vg/$lv1 + lvchange --poll n --refresh $vg/$lv1 dmsetup table lvs -a -o+lv_merging,lv_merge_failed $vg sleep 1 check lv_attr_bit state $vg/$lv1 "a" check lv_attr_bit state $vg/$lv2 "a" aux error_dev "$dev2" $(get first_extent_sector "$dev2"): + aux enable_dev "$dev1" # delay to let snapshot merge 'discover' failing COW device sleep 1 sync @@ -56,7 +57,7 @@ check lv_attr_bit state $vg/$lv2 "m" # device OK and running in full speed - aux enable_dev "$dev1" "$dev2" + aux enable_dev "$dev2" # reactivate so merge can finish lvchange -an $vg diff -Nru lvm2-2.02.167/test/shell/thin-foreign-dmeventd.sh lvm2-2.02.168/test/shell/thin-foreign-dmeventd.sh --- lvm2-2.02.167/test/shell/thin-foreign-dmeventd.sh 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/test/shell/thin-foreign-dmeventd.sh 2016-11-30 23:17:32.000000000 +0000 @@ -39,7 +39,7 @@ # Use our mkfs config file to get approximately same results # TODO: maybe use it for all test via some 'prepare' function -export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf" +export MKE2FS_CONFIG="$TESTOLDPWD/lib/mke2fs.conf" aux prepare_dmeventd aux prepare_pvs 2 64 diff -Nru lvm2-2.02.167/tools/dmsetup.c lvm2-2.02.168/tools/dmsetup.c --- lvm2-2.02.167/tools/dmsetup.c 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/tools/dmsetup.c 2016-11-30 23:17:32.000000000 +0000 @@ -691,9 +691,11 @@ if (usleep(this_interval / NSEC_PER_USEC)) { if (errno == EINTR) log_error("Report interval interrupted by signal."); - if (errno == EINVAL) + else if (errno == EINVAL) log_error("Report interval too short."); - return_0; + else + stack; /* other reason */ + return 0; } if (_count == 2) { @@ -6798,7 +6800,7 @@ if (_switches[COLS_ARG]) { if (!_report_init(cmd, subcommand)) ret = 1; - if (!_report) + if (ret || !_report) goto_out; } @@ -6864,5 +6866,5 @@ if (_initial_timestamp) dm_timestamp_destroy(_initial_timestamp); - return ret; + return (_switches[HELP_ARG] || _switches[VERSION_ARG]) ? 0 : ret; } diff -Nru lvm2-2.02.167/tools/lvconvert.c lvm2-2.02.168/tools/lvconvert.c --- lvm2-2.02.167/tools/lvconvert.c 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/tools/lvconvert.c 2016-11-30 23:17:32.000000000 +0000 @@ -37,19 +37,72 @@ * deprecated. (The same is still needed for --merge.) */ +typedef enum { + /* Merge: + * If merge_snapshot is also set: + * merge thin snapshot LV into its origin + * merge old snapshot COW into its origin + * or if merge_mirror is also set + * merge LV previously split from mirror back into mirror + */ + CONV_MERGE = 1, + + /* Split: + * For a snapshot, split it apart into COW and origin for future recombination + * For a cached LV, split it apart into the cached LV and its pool + * For a mirrored or raid LV, split mirror into two mirrors, optionally tracking + * future changes to the main mirror to allow future recombination. + */ + CONV_SPLIT = 2, + CONV_SPLIT_SNAPSHOT = 3, + CONV_SPLIT_CACHE = 4, + CONV_SPLIT_MIRRORS = 5, + + /* Start to cache an LV */ + CONV_CACHE = 6, + + /* Destroy the cache attached to a cached LV */ + CONV_UNCACHE = 7, + + /* Reconstruct a snapshot from its origin and COW */ + CONV_SNAPSHOT = 8, + + /* Replace devices in a raid LV with alternatives */ + CONV_REPLACE = 9, + + /* Repair a mirror, raid or thin LV */ + CONV_REPAIR = 10, + + /* Convert normal LV into one in a thin pool */ + CONV_THIN = 11, + + /* Every other segment type or mirror log conversion we haven't separated out */ + CONV_OTHER = 12, +} conversion_type_t; + struct lvconvert_params { /* Exactly one of these 12 command categories is determined */ - int merge; /* Either merge_snapshot or merge_mirror is also set */ - int cache; - int keep_mimages; /* --splitmirrors */ - int repair; - int replace; - int snapshot; - int split; - int splitcache; - int splitsnapshot; - int thin; - int uncache; + int merge; /* 1 */ + int split; /* 2 */ + int splitsnapshot; /* 3 */ + int splitcache; /* 4 */ + int keep_mimages; /* 5 */ /* --splitmirrors */ + int cache; /* 6 */ + int uncache; /* 7 */ + int snapshot; /* 8 */ + int replace; /* 9 */ + int repair; /* 10 */ + int thin; /* 11 */ + /* other */ /* 12 */ + + /* FIXME Eliminate all cases where more than one of the above are set then use conv_type instead */ + conversion_type_t conv_type; + + int merge_snapshot; /* CONV_MERGE is set */ + int merge_mirror; /* CONV_MERGE is set */ + + int track_changes; /* CONV_SPLIT_MIRRORS is set */ + int corelog; /* Equivalent to --mirrorlog core */ int mirrorlog; /* Only one of corelog and mirrorlog may be set */ @@ -59,11 +112,6 @@ const struct segment_type *segtype; /* Holds what segment type you will get */ - int merge_snapshot; /* merge is also set */ - int merge_mirror; /* merge is also set */ - - int track_changes; /* keep_mimages is also set (--splitmirrors) */ - int poolmetadataspare; int force; int yes; @@ -124,6 +172,15 @@ unsigned is_merging_origin_thin:1; }; +/* FIXME Temporary function until the enum replaces the separate variables */ +static void _set_conv_type(struct lvconvert_params *lp, int conv_type) +{ + if (lp->conv_type != CONV_OTHER) + log_error(INTERNAL_ERROR "Changing conv_type from %d to %d.", lp->conv_type, conv_type); + + lp->conv_type = conv_type; +} + static int _lvconvert_validate_names(struct lvconvert_params *lp) { unsigned i, j; @@ -472,23 +529,18 @@ -1)) return_0; lp->merge = 1; - } - - /* If --repair, check for incompatible args. */ - if (arg_is_set(cmd, repair_ARG)) { + _set_conv_type(lp, CONV_MERGE); + } else if (arg_is_set(cmd, repair_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --repair", repair_ARG, alloc_ARG, usepolicies_ARG, + background_ARG, interval_ARG, force_ARG, noudevsync_ARG, test_ARG, -1)) return_0; lp->repair = 1; - } - - if (arg_is_set(cmd, replace_ARG)) - lp->replace = 1; - - if (arg_is_set(cmd, split_ARG)) { + _set_conv_type(lp, CONV_REPAIR); + } else if (arg_is_set(cmd, split_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --split", split_ARG, name_ARG, @@ -496,40 +548,40 @@ -1)) return_0; lp->split = 1; - } - - if (arg_is_set(cmd, splitcache_ARG)) { + _set_conv_type(lp, CONV_SPLIT); + } else if (arg_is_set(cmd, splitcache_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --splitcache", splitcache_ARG, force_ARG, noudevsync_ARG, test_ARG, -1)) return_0; lp->splitcache = 1; - } - - if (arg_is_set(cmd, splitsnapshot_ARG)) { + _set_conv_type(lp, CONV_SPLIT_CACHE); + } else if (arg_is_set(cmd, splitsnapshot_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --splitsnapshot", splitsnapshot_ARG, force_ARG, noudevsync_ARG, test_ARG, -1)) return_0; lp->splitsnapshot = 1; - } - - if (arg_is_set(cmd, trackchanges_ARG)) - lp->track_changes = 1; - - if (arg_is_set(cmd, uncache_ARG)) { + _set_conv_type(lp, CONV_SPLIT_SNAPSHOT); + } else if (arg_is_set(cmd, uncache_ARG)) { if (arg_outside_list_is_set(cmd, "cannot be used with --uncache", uncache_ARG, force_ARG, noudevsync_ARG, test_ARG, -1)) return_0; lp->uncache = 1; + _set_conv_type(lp, CONV_UNCACHE); + } else if (arg_is_set(cmd, replace_ARG)) { + lp->replace = 1; + _set_conv_type(lp, CONV_REPLACE); } - if (arg_is_set(cmd, cache_ARG)) + if (arg_is_set(cmd, cache_ARG)) { lp->cache = 1; + _set_conv_type(lp, CONV_CACHE); + } if (!strcmp(lp->type_str, SEG_TYPE_NAME_CACHE)) lp->cache = 1; @@ -541,8 +593,10 @@ lp->type_str = SEG_TYPE_NAME_CACHE; } - if (arg_is_set(cmd, thin_ARG)) + if (arg_is_set(cmd, thin_ARG)) { lp->thin = 1; + _set_conv_type(lp, CONV_THIN); + } if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN)) lp->thin = 1; @@ -554,6 +608,9 @@ lp->type_str = SEG_TYPE_NAME_THIN; } + if (arg_is_set(cmd, trackchanges_ARG)) + lp->track_changes = 1; + if (!_read_pool_params(cmd, &argc, &argv, lp)) return_0; @@ -563,6 +620,7 @@ return 0; } lp->snapshot = 1; + _set_conv_type(lp, CONV_SNAPSHOT); } if (lp->split) { @@ -588,6 +646,7 @@ lp->lv_split_name = arg_str_value(cmd, name_ARG, NULL); lp->keep_mimages = 1; + _set_conv_type(lp, CONV_SPLIT_MIRRORS); lp->mirrors = arg_uint_value(cmd, splitmirrors_ARG, 0); lp->mirrors_sign = SIGN_MINUS; } else { @@ -642,6 +701,7 @@ return 0; } + /* * Final checking of each case: * lp->merge @@ -658,23 +718,18 @@ * --type mirror|raid lp->mirrorlog lp->corelog * --type raid0|striped */ - if (lp->merge) /* Snapshot or mirror merge */ - ; - else if (lp->splitsnapshot) /* Destroy snapshot retaining cow as separate LV */ - ; - else if (lp->splitcache) - ; - else if (lp->split) - ; - else if (lp->uncache) - ; - else if (lp->cache) - ; - else if (lp->thin) - ; - else if (lp->keep_mimages) /* --splitmirrors */ - ; - else if (lp->snapshot) { /* Snapshot creation from pre-existing cow */ + switch(lp->conv_type) { + case CONV_MERGE: /* Snapshot or mirror merge */ + case CONV_SPLIT: + case CONV_SPLIT_CACHE: + case CONV_SPLIT_MIRRORS: + case CONV_SPLIT_SNAPSHOT: /* Destroy snapshot retaining cow as separate LV */ + case CONV_CACHE: + case CONV_UNCACHE: + case CONV_THIN: + case CONV_REPAIR: + break; + case CONV_SNAPSHOT: /* Snapshot creation from pre-existing cow */ if (!argc) { log_error("Please provide logical volume path for snapshot origin."); return 0; @@ -708,8 +763,9 @@ log_verbose("Setting chunk size to %s.", display_size(cmd, lp->chunk_size)); lp->type_str = SEG_TYPE_NAME_SNAPSHOT; + break; - } else if (lp->replace) { /* RAID device replacement */ + case CONV_REPLACE: /* RAID device replacement */ lp->replace_pv_count = arg_count(cmd, replace_ARG); lp->replace_pvs = dm_pool_alloc(cmd->mem, sizeof(char *) * lp->replace_pv_count); if (!lp->replace_pvs) @@ -729,72 +785,73 @@ tmp_str))) return_0; } - } else if (lp->repair) - ; - else if (_mirror_or_raid_type_requested(cmd, lp->type_str) || - lp->mirrorlog || lp->corelog) { /* Mirrors (and some RAID functions) */ - if (arg_is_set(cmd, chunksize_ARG)) { - log_error("--chunksize is only available with snapshots or pools."); - return 0; - } + break; - if (arg_is_set(cmd, zero_ARG)) { - log_error("--zero is only available with snapshots or thin pools."); - return 0; - } - - /* - * --regionsize is only valid if converting an LV into a mirror. - * Checked when we know the state of the LV being converted. - */ - if (arg_is_set(cmd, regionsize_ARG)) { - if (arg_sign_value(cmd, regionsize_ARG, SIGN_NONE) == - SIGN_MINUS) { - log_error("Negative regionsize is invalid."); + case CONV_OTHER: + if (_mirror_or_raid_type_requested(cmd, lp->type_str) || + lp->mirrorlog || lp->corelog) { /* Mirrors (and some RAID functions) */ + if (arg_is_set(cmd, chunksize_ARG)) { + log_error("--chunksize is only available with snapshots or pools."); return 0; } - lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0); - } else { - region_size = get_default_region_size(cmd); - if (region_size < 0) { - log_error("Negative regionsize in " - "configuration file is invalid."); + + if (arg_is_set(cmd, zero_ARG)) { + log_error("--zero is only available with snapshots or thin pools."); return 0; } - lp->region_size = region_size; - } - - if (lp->region_size % (pagesize >> SECTOR_SHIFT)) { - log_error("Region size (%" PRIu32 ") must be " - "a multiple of machine memory " - "page size (%d).", - lp->region_size, pagesize >> SECTOR_SHIFT); - return 0; - } - if (!is_power_of_2(lp->region_size)) { - log_error("Region size (%" PRIu32 - ") must be a power of 2.", lp->region_size); - return 0; - } + /* + * --regionsize is only valid if converting an LV into a mirror. + * Checked when we know the state of the LV being converted. + */ + if (arg_is_set(cmd, regionsize_ARG)) { + if (arg_sign_value(cmd, regionsize_ARG, SIGN_NONE) == + SIGN_MINUS) { + log_error("Negative regionsize is invalid."); + return 0; + } + lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0); + } else { + region_size = get_default_region_size(cmd); + if (region_size < 0) { + log_error("Negative regionsize in " + "configuration file is invalid."); + return 0; + } + lp->region_size = region_size; + } - if (!lp->region_size) { - log_error("Non-zero region size must be supplied."); - return 0; - } + if (lp->region_size % (pagesize >> SECTOR_SHIFT)) { + log_error("Region size (%" PRIu32 ") must be " + "a multiple of machine memory " + "page size (%d).", + lp->region_size, pagesize >> SECTOR_SHIFT); + return 0; + } - /* FIXME man page says in one place that --type and --mirrors can't be mixed */ - if (lp->mirrors_supplied && !lp->mirrors) - /* down-converting to linear/stripe? */ - lp->type_str = SEG_TYPE_NAME_STRIPED; + if (!is_power_of_2(lp->region_size)) { + log_error("Region size (%" PRIu32 + ") must be a power of 2.", lp->region_size); + return 0; + } - } else if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str)) { /* striped or linear or raid0 */ - if (arg_from_list_is_set(cmd, "cannot be used with --type raid0 or --type striped or --type linear", - chunksize_ARG, corelog_ARG, mirrors_ARG, mirrorlog_ARG, regionsize_ARG, zero_ARG, - -1)) - return_0; + if (!lp->region_size) { + log_error("Non-zero region size must be supplied."); + return 0; + } - } /* else segtype will default to current type */ + /* FIXME man page says in one place that --type and --mirrors can't be mixed */ + if (lp->mirrors_supplied && !lp->mirrors) + /* down-converting to linear/stripe? */ + lp->type_str = SEG_TYPE_NAME_STRIPED; + + } else if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str)) { /* striped or linear or raid0 */ + if (arg_from_list_is_set(cmd, "cannot be used with --type raid0 or --type striped or --type linear", + chunksize_ARG, corelog_ARG, mirrors_ARG, mirrorlog_ARG, regionsize_ARG, zero_ARG, + -1)) + return_0; + } /* else segtype will default to current type */ + } lp->force = arg_count(cmd, force_ARG); lp->yes = arg_count(cmd, yes_ARG); @@ -1427,7 +1484,8 @@ */ if (lv_is_origin(lv)) { log_error("Can't add additional mirror images to " - "mirrors that are under snapshots,"); + "mirror %s which is under snapshots.", + display_lvname(lv)); return 0; } @@ -1465,10 +1523,9 @@ MIRROR_BY_LV)) { layer_lv = seg_lv(first_seg(lv), 0); if (!remove_layer_from_lv(lv, layer_lv) || - (lv_is_active(layer_lv) && - !deactivate_lv(cmd, layer_lv)) || - !lv_remove(layer_lv) || !vg_write(lv->vg) || - !vg_commit(lv->vg)) { + !deactivate_lv(cmd, layer_lv) || + !lv_remove(layer_lv) || + !vg_write(lv->vg) || !vg_commit(lv->vg)) { log_error("ABORTING: Failed to remove " "temporary mirror layer %s.", display_lvname(layer_lv)); @@ -1710,13 +1767,12 @@ uint32_t new_log_count; if ((lp->corelog || lp->mirrorlog) && *lp->type_str && strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR)) { - log_error("--corelog and --mirrorlog are only compatible with mirror devices"); + log_error("--corelog and --mirrorlog are only compatible with mirror devices."); return 0; } if (lp->merge_mirror) { - log_error("Unable to merge mirror images" - "of segment type 'mirror'."); + log_error("Unable to merge mirror images of segment type 'mirror'."); return 0; } @@ -1750,7 +1806,7 @@ if (!_lvconvert_mirrors_parse_params(cmd, lv, lp, &old_mimage_count, &old_log_count, &new_mimage_count, &new_log_count)) - return 0; + return_0; if (((old_mimage_count < new_mimage_count && old_log_count > new_log_count) || (old_mimage_count > new_mimage_count && old_log_count < new_log_count)) && @@ -1771,7 +1827,9 @@ if (!_lvconvert_mirrors_aux(cmd, lv, lp, NULL, new_mimage_count, new_log_count)) - return 0; + return_0; + + backup(lv->vg); if (!lp->need_polling) log_print_unless_silent("Logical volume %s converted.", @@ -1780,8 +1838,6 @@ log_print_unless_silent("Logical volume %s being converted.", display_lvname(lv)); - backup(lv->vg); - return 1; } @@ -1972,7 +2028,7 @@ /* Activation is required later which precludes existing supported raid4 segment */ if (!_raid4_conversion_supported(lv, lp)) - return 0; + return_0; /* Activation is required later which precludes existing supported raid10 segment */ if ((seg_is_raid10(seg) || segtype_is_raid10(lp->segtype)) && @@ -2011,6 +2067,9 @@ return 0; } + if (!lv_check_transient(lv)) /* TODO check this in lib for all commands? */ + stack; /* TODO: break here upon fail or always try to fix it? */ + _lvconvert_raid_repair_ask(cmd, lp, &replace); if (replace) { @@ -4693,6 +4752,7 @@ int poll_ret, ret; struct convert_poll_id_list *idl; struct lvconvert_params lp = { + .conv_type = CONV_OTHER, .target_attr = ~0, .idls = DM_LIST_HEAD_INIT(lp.idls), }; diff -Nru lvm2-2.02.167/tools/lvcreate.c lvm2-2.02.168/tools/lvcreate.c --- lvm2-2.02.167/tools/lvcreate.c 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/tools/lvcreate.c 2016-11-30 23:17:32.000000000 +0000 @@ -1591,12 +1591,12 @@ if (vg->lock_type && !strcmp(vg->lock_type, "sanlock")) { if (!handle_sanlock_lv(cmd, vg)) { log_error("No space for sanlock lock, extend the internal lvmlock LV."); - goto_out; + goto out; } } if (seg_is_thin_volume(lp)) - log_verbose("Making thin LV %s in pool %s in VG %s%s%s using segtype %s", + log_verbose("Making thin LV %s in pool %s in VG %s%s%s using segtype %s.", lp->lv_name ? : "with generated name", lp->pool_name ? : "with generated name", lp->vg_name, lp->snapshot ? " as snapshot of " : "", diff -Nru lvm2-2.02.167/tools/pvmove.c lvm2-2.02.168/tools/pvmove.c --- lvm2-2.02.167/tools/pvmove.c 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/tools/pvmove.c 2016-11-30 23:17:32.000000000 +0000 @@ -187,12 +187,12 @@ if (!(sublv = find_lv(lv->vg, sublv_name))) { log_error("Can't find sub LV %s?", sublv_name); - return_0; + return 0; } if (!get_pv_list_for_lv(lv->vg->cmd->mem, sublv, &untrim_list)) { log_error("Can't find PVs for sub LV %s?", sublv_name); - return_0; + return 0; } dm_list_iterate(pvh1, &untrim_list) { diff -Nru lvm2-2.02.167/tools/toollib.c lvm2-2.02.168/tools/toollib.c --- lvm2-2.02.167/tools/toollib.c 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/tools/toollib.c 2016-11-30 23:17:32.000000000 +0000 @@ -451,17 +451,16 @@ { struct pe_range *per; - log_debug("Adding PE range: start PE %" PRIu32 " length %" PRIu32 - " on %s.", start, count, pvname); + log_debug("Adding PE range: start PE " FMTu32 " length " FMTu32 " on %s.", + start, count, pvname); /* Ensure no overlap with existing areas */ dm_list_iterate_items(per, pe_ranges) { if (((start < per->start) && (start + count - 1 >= per->start)) || ((start >= per->start) && (per->start + per->count - 1) >= start)) { - log_error("Overlapping PE ranges specified (%" PRIu32 - "-%" PRIu32 ", %" PRIu32 "-%" PRIu32 ")" - " on %s.", + log_error("Overlapping PE ranges specified (" FMTu32 + "-" FMTu32 ", " FMTu32 "-" FMTu32 ") on %s.", start, start + count - 1, per->start, per->start + per->count - 1, pvname); return 0; @@ -579,18 +578,18 @@ pvname = pv_dev_name(pvl->pv); if (allocatable_only && !(pvl->pv->status & ALLOCATABLE_PV)) { - log_warn("Physical volume %s not allocatable.", pvname); + log_warn("WARNING: Physical volume %s not allocatable.", pvname); return 1; } if (allocatable_only && is_missing_pv(pvl->pv)) { - log_warn("Physical volume %s is missing.", pvname); + log_warn("WARNING: Physical volume %s is missing.", pvname); return 1; } if (allocatable_only && (pvl->pv->pe_count == pvl->pv->pe_alloc_count)) { - log_warn("No free extents on physical volume \"%s\".", pvname); + log_warn("WARNING: No free extents on physical volume \"%s\".", pvname); return 1; } @@ -637,7 +636,7 @@ /* Build up list of PVs */ if (!(r = dm_pool_alloc(mem, sizeof(*r)))) { - log_error("Allocation of list failed"); + log_error("Allocation of list failed."); return NULL; } dm_list_init(r); @@ -2474,7 +2473,7 @@ if (!(final_lvl = dm_pool_zalloc(cmd->mem, sizeof(struct lv_list)))) { log_error("Failed to allocate final LV list item."); ret_max = ECMD_FAILED; - goto_out; + goto out; } final_lvl->lv = lvl->lv; dm_list_add(&final_lvs, &final_lvl->list); @@ -4710,7 +4709,7 @@ if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE, NULL)) { log_error("Can't get lock for orphan PVs."); - goto_out; + goto out; } /* @@ -4742,7 +4741,7 @@ if (dm_list_empty(&pp->arg_process)) { log_debug("No devices to process."); - goto_bad; + goto bad; } do_command: @@ -4789,7 +4788,7 @@ if (!(orphan_vg = vg_read_internal(cmd, pp->orphan_vg_name, NULL, 0, &consistent))) { log_error("Cannot read orphans VG %s.", pp->orphan_vg_name); - goto_bad; + goto bad; } dm_list_iterate_items_safe(pd, pd2, &pp->arg_create) { diff -Nru lvm2-2.02.167/tools/vgimportclone.c lvm2-2.02.168/tools/vgimportclone.c --- lvm2-2.02.167/tools/vgimportclone.c 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/tools/vgimportclone.c 2016-11-30 23:17:32.000000000 +0000 @@ -75,12 +75,12 @@ if (vg_is_exported(vg) && !vp->import_vg) { log_error("VG %s is exported, use the --import option.", vg->name); - goto_bad; + goto bad; } if (vg_status(vg) & PARTIAL_VG) { log_error("VG %s is partial, it must be complete.", vg->name); - goto_bad; + goto bad; } /* @@ -121,7 +121,7 @@ log_error("PV with UUID %s is part of VG %s, but is not included in the devices to import.", uuid, vg->name); log_error("All PVs in the VG must be imported together."); - goto_bad; + goto bad; } } @@ -130,7 +130,7 @@ /* device arg is not in the VG. */ log_error("Device %s was not found in VG %s.", dev_name(vd->dev), vg->name); log_error("The devices to import must match the devices in the VG."); - goto_bad; + goto bad; } } @@ -245,7 +245,7 @@ if (vp.found_args != argc) { log_error("Failed to find all devices."); - goto_out; + goto out; } /* @@ -256,12 +256,12 @@ dm_list_iterate_items(vd, &vp.arg_import) { if (!(info = lvmcache_info_from_pvid(vd->dev->pvid, NULL, 0))) { log_error("Failed to find PVID for device %s in lvmcache.", dev_name(vd->dev)); - goto_out; + goto out; } if (!(vgname = lvmcache_vgname_from_info(info))) { log_error("Failed to find VG name for device %s in lvmcache.", dev_name(vd->dev)); - goto_out; + goto out; } if (!vp.old_vgname) { @@ -270,7 +270,7 @@ } else { if (strcmp(vp.old_vgname, vgname)) { log_error("Devices must be from the same VG."); - goto_out; + goto out; } } } @@ -360,4 +360,3 @@ return ret; } - diff -Nru lvm2-2.02.167/tools/vgreduce.c lvm2-2.02.168/tools/vgreduce.c --- lvm2-2.02.167/tools/vgreduce.c 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/tools/vgreduce.c 2016-11-30 23:17:32.000000000 +0000 @@ -26,19 +26,19 @@ char uuid[64] __attribute__((aligned(8))); if (vg->pv_count == 1) { - log_error("Volume Groups must always contain at least one PV"); + log_error("Volume Groups must always contain at least one PV."); return 0; } if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid))) return_0; - log_verbose("Removing PV with UUID %s from VG %s", uuid, vg->name); + log_verbose("Removing PV with UUID %s from VG %s.", uuid, vg->name); if (pvl->pv->pe_alloc_count) { if (!silent) log_error("LVs still present on PV with UUID %s: " - "Can't remove from VG %s", uuid, vg->name); + "Can't remove from VG %s.", uuid, vg->name); return 0; } @@ -67,7 +67,7 @@ cmd->handles_missing_pvs = 1; log_error("There are still partial LVs in VG %s.", vg->name); log_error("To remove them unconditionally use: vgreduce --removemissing --force."); - log_warn("Proceeding to remove empty missing PVs."); + log_warn("WARNING: Proceeding to remove empty missing PVs."); } dm_list_iterate_items(pvl, &vg->pvs) { @@ -114,7 +114,9 @@ if (!lv_is_visible(lv)) continue; - log_warn("Removing partial LV %s.", lv->name); + + log_warn("WARNING: Removing partial LV %s.", display_lvname(lv)); + if (!lv_remove_with_dependencies(cmd, lv, DONT_PROMPT, 0)) return_0; goto restart; @@ -183,33 +185,33 @@ if (!argc && !repairing) { log_error("Please give volume group name and " - "physical volume paths"); + "physical volume paths."); return EINVALID_CMD_LINE; } if (!argc) { /* repairing */ - log_error("Please give volume group name"); + log_error("Please give volume group name."); return EINVALID_CMD_LINE; } if (arg_is_set(cmd, mirrorsonly_ARG) && !repairing) { - log_error("--mirrorsonly requires --removemissing"); + log_error("--mirrorsonly requires --removemissing."); return EINVALID_CMD_LINE; } if (argc == 1 && !arg_is_set(cmd, all_ARG) && !repairing) { - log_error("Please enter physical volume paths or option -a"); + log_error("Please enter physical volume paths or option -a."); return EINVALID_CMD_LINE; } if (argc > 1 && arg_is_set(cmd, all_ARG)) { log_error("Option -a and physical volume paths mutually " - "exclusive"); + "exclusive."); return EINVALID_CMD_LINE; } if (argc > 1 && repairing) { - log_error("Please only specify the volume group"); + log_error("Please only specify the volume group."); return EINVALID_CMD_LINE; } @@ -250,10 +252,10 @@ 0, handle, &_vgreduce_repair_single); if (vp.already_consistent) { - log_print_unless_silent("Volume group \"%s\" is already consistent", vg_name); + log_print_unless_silent("Volume group \"%s\" is already consistent.", vg_name); ret = ECMD_PROCESSED; } else if (vp.fixed) { - log_print_unless_silent("Wrote out consistent volume group %s", vg_name); + log_print_unless_silent("Wrote out consistent volume group %s.", vg_name); ret = ECMD_PROCESSED; } else ret = ECMD_FAILED; diff -Nru lvm2-2.02.167/VERSION lvm2-2.02.168/VERSION --- lvm2-2.02.167/VERSION 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/VERSION 2016-11-30 23:17:33.000000000 +0000 @@ -1 +1 @@ -2.02.167(2) (2016-11-05) +2.02.168(2) (2016-11-30) diff -Nru lvm2-2.02.167/VERSION_DM lvm2-2.02.168/VERSION_DM --- lvm2-2.02.167/VERSION_DM 2016-11-05 01:06:49.000000000 +0000 +++ lvm2-2.02.168/VERSION_DM 2016-11-30 23:17:33.000000000 +0000 @@ -1 +1 @@ -1.02.136 (2016-11-05) +1.02.137 (2016-11-30) diff -Nru lvm2-2.02.167/WHATS_NEW lvm2-2.02.168/WHATS_NEW --- lvm2-2.02.167/WHATS_NEW 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/WHATS_NEW 2016-11-30 23:17:28.000000000 +0000 @@ -1,3 +1,18 @@ +Version 2.02.168 - 30th November 2016 +===================================== + Display correct sync_percent on large RaidLVs + lvmdbusd --blackboxsize added, used to override default size of 16 + Allow a transiently failed RaidLV to be refreshed + Use lv_update_and_reload() inside mirror code where it applies. + Preserve mirrored status for temporary layered mirrors. + Use transient raid check before repairing raid volume. + Implement transient status check for raid volumes. + Only log msg as debug if lvm2-lvmdbusd unit missing for D-Bus notification. + Avoid duplicated underscore in name of extracted LV image. + Missing stripe filler now could be also 'zero'. + lvconvert --repair accepts --interval and --background option. + More efficiently prepare _rmeta devices when creating a new raid LV. + Version 2.02.167 - 5th November 2016 ==================================== Use log_error in regex and sysfs filter to describe reason of failure. diff -Nru lvm2-2.02.167/WHATS_NEW_DM lvm2-2.02.168/WHATS_NEW_DM --- lvm2-2.02.167/WHATS_NEW_DM 2016-11-05 01:06:47.000000000 +0000 +++ lvm2-2.02.168/WHATS_NEW_DM 2016-11-30 23:17:28.000000000 +0000 @@ -1,3 +1,8 @@ +Version 1.02.137 - 30th November 2016 +===================================== + Document raid status values. + Always exit dmsetup with success when asked to display help/version. + Version 1.02.136 - 5th November 2016 ==================================== Log failure of raid device with log_error level.