diff --git a/qubes/storage/lvm.py b/qubes/storage/lvm.py index 778de397..2d35f2fe 100644 --- a/qubes/storage/lvm.py +++ b/qubes/storage/lvm.py @@ -227,6 +227,8 @@ class ThinVolume(qubes.storage.Volume): @property def size(self): try: + if self.is_dirty(): + return qubes.storage.lvm.size_cache[self._vid_snap]['size'] return qubes.storage.lvm.size_cache[self.vid]['size'] except KeyError: return self._size @@ -427,18 +429,19 @@ class ThinVolume(qubes.storage.Volume): if size < self.size: raise qubes.storage.StoragePoolException( 'For your own safety, shrinking of %s is' - ' disabled. If you really know what you' + ' disabled (%d < %d). If you really know what you' ' are doing, use `lvresize` on %s manually.' % - (self.name, self.vid)) + (self.name, size, self.size, self.vid)) if size == self.size: return - cmd = ['extend', self.vid, str(size)] - qubes_lvm(cmd, self.log) if self.is_dirty(): cmd = ['extend', self._vid_snap, str(size)] qubes_lvm(cmd, self.log) + elif self.save_on_stop or not self.snap_on_start: + cmd = ['extend', self.vid, str(size)] + qubes_lvm(cmd, self.log) reset_cache() def _snapshot(self): diff --git a/qubes/tests/storage_lvm.py b/qubes/tests/storage_lvm.py index f6a4be69..2672a280 100644 --- a/qubes/tests/storage_lvm.py +++ b/qubes/tests/storage_lvm.py @@ -178,6 +178,60 @@ class TC_00_ThinPool(ThinPoolBase): pool_usage = float(pool_usage) self.assertEqual(usage, int(pool_size * pool_usage / 100)) + def _get_size(self, path): + if os.getuid() != 0: + return int( + subprocess.check_output( + ['sudo', 'blockdev', '--getsize64', path])) + fd = os.open(path, os.O_RDONLY) + try: + return os.lseek(fd, 0, os.SEEK_END) + finally: + os.close(fd) + + def test_006_resize(self): + config = { + 'name': 'root', + 'pool': self.pool.name, + 'rw': True, + 'save_on_stop': True, + 'size': 32 * 1024**2, + } + vm = qubes.tests.storage.TestVM(self) + volume = self.app.get_pool(self.pool.name).init_volume(vm, config) + volume.create() + self.addCleanup(volume.remove) + path = "/dev/%s" % volume.vid + new_size = 64 * 1024 ** 2 + volume.resize(new_size) + self.assertEqual(self._get_size(path), new_size) + self.assertEqual(volume.size, new_size) + + def test_007_resize_running(self): + old_size = 32 * 1024**2 + config = { + 'name': 'root', + 'pool': self.pool.name, + 'rw': True, + 'save_on_stop': True, + 'size': old_size, + } + vm = qubes.tests.storage.TestVM(self) + volume = self.app.get_pool(self.pool.name).init_volume(vm, config) + volume.create() + self.addCleanup(volume.remove) + volume.start() + path = "/dev/%s" % volume.vid + path2 = "/dev/%s" % volume._vid_snap + new_size = 64 * 1024 ** 2 + volume.resize(new_size) + self.assertEqual(self._get_size(path), old_size) + self.assertEqual(self._get_size(path2), new_size) + self.assertEqual(volume.size, new_size) + volume.stop() + self.assertEqual(self._get_size(path), new_size) + self.assertEqual(volume.size, new_size) + @skipUnlessLvmPoolExists class TC_01_ThinPool(ThinPoolBase, qubes.tests.SystemTestCase):