diff --git a/qubes/storage/file.py b/qubes/storage/file.py index ec4648917..7fc9903ba 100644 --- a/qubes/storage/file.py +++ b/qubes/storage/file.py @@ -362,14 +362,6 @@ def resize(self, size): # pylint: disable=invalid-overridden-method ) raise qubes.exc.StoragePoolException(msg) - if size < self.size: - raise qubes.exc.StoragePoolException( - "For your own safety, shrinking of %s is" - " disabled. If you really know what you" - " are doing, use `truncate` on %s manually." - % (self.name, self.vid) - ) - with open(self.path, "a+b") as fd: fd.truncate(size) diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index bed1def06..c9977f9b4 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -719,27 +719,19 @@ async def resize(self, size): msg = "Can not resize readonly volume {!s}".format(self) raise qubes.exc.StoragePoolException(msg) - if size < self.size: - raise qubes.exc.StoragePoolException( - "For your own safety, shrinking of %s is" - " disabled (%d < %d). If you really know what you" - " are doing, use `lvresize` on %s manually." - % (self.name, size, self.size, self.vid) - ) - if size == self.size: return if self.is_dirty() or self.snap_on_start: - cmd = ["extend", self._vid_snap, str(size)] + cmd = ["resize", self._vid_snap, str(size)] await qubes_lvm_coro(cmd, self.log) elif hasattr(self, "_vid_import") and os.path.exists( "/dev/" + self._vid_import ): - cmd = ["extend", self._vid_import, str(size)] + cmd = ["resize", self._vid_import, str(size)] await qubes_lvm_coro(cmd, self.log) elif self.save_on_stop and not self.snap_on_start: - cmd = ["extend", self._vid_current, str(size)] + cmd = ["resize", self._vid_current, str(size)] await qubes_lvm_coro(cmd, self.log) self._size = size @@ -909,9 +901,9 @@ def _get_lvm_cmdline(cmd): "--", cmd[1], ] - elif action == "extend": - assert len(cmd) == 3, "wrong number of arguments for extend" - lvm_cmd = ["lvextend", "--size=" + cmd[2] + "B", "--", cmd[1]] + elif action == "resize": + assert len(cmd) == 3, "wrong number of arguments for resize" + lvm_cmd = ["lvresize", "--size=" + cmd[2] + "B", "--", cmd[1]] elif action == "activate": assert len(cmd) == 2, "wrong number of arguments for activate" lvm_cmd = ["lvchange", "--activate=y", "--", cmd[1]] diff --git a/qubes/storage/zfs.py b/qubes/storage/zfs.py index 1862e62ca..9784f0138 100644 --- a/qubes/storage/zfs.py +++ b/qubes/storage/zfs.py @@ -1412,11 +1412,9 @@ async def resize_volume_async( log: logging.Logger, ) -> None: """ - Enlarge a volume to the specified size. + Resize a volume to the specified size. The volume must exist. - - An error will be raised if size is < current size. """ assert dataset_in_root(volume, self.root) async with self._cache.locked(): @@ -2681,33 +2679,12 @@ def is_dirty(self) -> bool: @qubes.storage.Volume.locked # type: ignore async def resize(self, size: int) -> None: """ - Expands volume. - - Throws - :py:class:`qubst.storage.qubes.storage.StoragePoolException` if - given size is less than current_size. - """ - # FIXME: there does not seem to be a pathway to, but there - # should be a pathway to, reducing the storage size of a - # volume, whether it be by having to stop the VM first and - # then making a non-atomic clone / partial copy / rename - # of a zvol. It is annoying that ZFS prevents volumes from - # being reduced in size. It is further annoying that - # reduction of a volume requires the file system in it to - # be reduced first, which can only be done while the qube - # is running, but a Towers-of-Hanoi operation with datasets - # can only be performed with the qube off. Perhaps in the - # future we can have a qvm feature exposed that allows dom0 - # to coordinate shrinking the file system and defers the - # Towers-of-Hanoi operation to after the qube has powered off. + Resizes volume. + """ self.log.debug("Resizing %s to %s", self.volume, size) mysize = self.size if size == mysize: return - if size < mysize: - raise qubes.exc.StoragePoolException( - "Shrinking of ZFS volume %s is not possible" % (self.volume,) - ) if await self.pool.accessor.volume_exists_async( self.volume, log=self.log, diff --git a/qubes/tests/storage_zfs.py b/qubes/tests/storage_zfs.py index 764a70174..a531ac3fc 100644 --- a/qubes/tests/storage_zfs.py +++ b/qubes/tests/storage_zfs.py @@ -418,7 +418,7 @@ def test_012_export_import(self) -> None: self.rc(volume.export_end(exported)) def test_013_resize_saveonstop(self) -> None: - """Test that a volume can be enlarged, but cannot be shrunk.""" + """Test that a volume can be enlarged and shrunk.""" volume = self.get_vol(ONEMEG_SAVE_ON_STOP) self.rc(volume.create()) @@ -431,10 +431,13 @@ def test_013_resize_saveonstop(self) -> None: f"volume.size {volume.size} != newsize {newsize}", ) - # Fail at shrinking. - self.assertRaises( - qubes.exc.StoragePoolException, - lambda: self.rc(volume.resize(1024 * 1024)), + # Shrink! + newsize = 1 * 1024 * 1024 + self.rc(volume.resize(newsize)) + self.assertEqual( + volume.size, + newsize, + f"volume.size {volume.size} != newsize {newsize}", ) def test_014_snaponstart_forgets_data(self) -> None: