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
This commit is contained in:
Marek Marczykowski-Górecki 2017-10-13 01:11:55 +02:00
parent ec4c7d7263
commit 021047f950
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -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: