From 5aaf30fc68cc9e325f97fd6afdc675205c144284 Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Fri, 1 Apr 2022 14:06:25 -0400 Subject: [PATCH] lvm2 pool: Export immutable snapshot of volume Volumes returned by `export()` must be immutable, since otherwise the backup will be inconsistent. Ensure this by exporting a snapshot of the volume, no the volume itself. Fixes QubesOS/qubes-issues#7198. FIXME: tests --- qubes/storage/lvm.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index 023800cb3..1216ffc2a 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -292,6 +292,9 @@ def __init__(self, volume_group, **kwargs): self._vid_snap = self.vid + '-snap' if self.save_on_stop: self._vid_import = self.vid + '-import' + path_export = self._path_export + if os.path.exists(path_export): + subprocess.check_call(_get_lvm_cmdline(['remove', path_export])) @property def path(self): @@ -470,13 +473,27 @@ async def remove(self): # pylint: disable=protected-access self.pool._volume_objects_cache.pop(self.vid, None) - async def export(self): + @property + def _vid_export(self) -> str: + return self.vid + '+export' + + @property + def _path_export(self) -> str: + return '/dev/' + self._vid_export + + async def export(self) -> str: ''' Returns an object that can be `open()`. ''' # make sure the device node is available - cmd = ['activate', self.path] - await qubes_lvm_coro(cmd, self.log) - devpath = self.path - return devpath + vid_export = self._vid_export + export_path = self._path_export + if not os.path.exists(export_path): + cmd = ['clone', self._vid_current, vid_export] + await qubes_lvm_coro(cmd, self.log) + return export_path + + async def export_end(self, path: str) -> None: + assert path == self._vid_export, 'Refusing to remove incorrect path' + await qubes_lvm_coro(['remove', path], self.log) @qubes.storage.Volume.locked async def import_volume(self, src_volume):