From 021047f950b0f8c2f147d75bd4dcc056f6757441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 13 Oct 2017 01:11:55 +0200 Subject: [PATCH] storage/lvm: remove old volume only after successfully cloning new one In some cases, it may happen that new volume (`self._vid_snap`) does not exists. This is normally an error, but even in such a case, do not remove the only remaining instance of volume (`self.vid`). Instead, rename it temporarily and remove only after new volume is successfully cloned. Fixes QubesOS/qubes-issues#3164 --- qubes/storage/lvm.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index 4f121f6c..e67b0ccf 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -271,10 +271,22 @@ class ThinVolume(qubes.storage.Volume): qubes_lvm(cmd, self.log) self._remove_revisions() - cmd = ['remove', self.vid] - qubes_lvm(cmd, self.log) - cmd = ['clone', self._vid_snap, self.vid] + # TODO: when converting this function to coroutine, this _must_ be + # under a lock + # remove old volume only after _successful_ clone of the new one + cmd = ['rename', self.vid, self.vid + '-tmp'] qubes_lvm(cmd, self.log) + try: + cmd = ['clone', self._vid_snap, self.vid] + qubes_lvm(cmd, self.log) + except: + # restore original volume + cmd = ['rename', self.vid + '-tmp', self.vid] + qubes_lvm(cmd, self.log) + raise + else: + cmd = ['remove', self.vid + '-tmp'] + qubes_lvm(cmd, self.log) def create(self): @@ -494,6 +506,8 @@ def qubes_lvm(cmd, log=logging.getLogger('qubes.storage.lvm')): lvm_cmd = ["lvextend", "-L%s" % size, cmd[1]] elif action == 'activate': lvm_cmd = ['lvchange', '-ay', cmd[1]] + elif action == 'rename': + lvm_cmd = ['lvrename', cmd[1], cmd[2]] else: raise NotImplementedError('unsupported action: ' + action) if lvm_is_very_old: