From c1bba6108f88208f5f0a7c0fda7fd7c4f1c14c62 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Mon, 21 Oct 2024 12:14:33 +0200 Subject: [PATCH 1/3] fs: Add suport for getting VFAT filesystem info and size --- blivet/formats/fs.py | 2 ++ blivet/tasks/fsinfo.py | 7 +++++++ blivet/tasks/fssize.py | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index 1f7e81fdb..eea4efc91 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1015,6 +1015,8 @@ class FATFS(FS): _max_size = Size("1 TiB") _packages = ["dosfstools"] _fsck_class = fsck.DosFSCK + _info_class = fsinfo.FATFSInfo + _size_info_class = fssize.FATFSSize _mkfs_class = fsmkfs.FATFSMkfs _mount_class = fsmount.FATFSMount _readlabel_class = fsreadlabel.DosFSReadLabel diff --git a/blivet/tasks/fsinfo.py b/blivet/tasks/fsinfo.py index a1387a18f..a6e86c394 100644 --- a/blivet/tasks/fsinfo.py +++ b/blivet/tasks/fsinfo.py @@ -81,5 +81,12 @@ def _get_info(self): return BlockDev.fs.xfs_get_info(self.fs.device) +class FATFSInfo(FSInfo): + ext = availability.BLOCKDEV_VFAT_INFO + + def _get_info(self): + return BlockDev.fs.vfat_get_info(self.fs.device) + + class UnimplementedFSInfo(fstask.UnimplementedFSTask): pass diff --git a/blivet/tasks/fssize.py b/blivet/tasks/fssize.py index a23e6d9cf..504a7eabb 100644 --- a/blivet/tasks/fssize.py +++ b/blivet/tasks/fssize.py @@ -81,6 +81,11 @@ def _get_size(self): return Size(self.fs._current_info.block_size * self.fs._current_info.block_count) +class FATFSSize(FSSize): + def _get_size(self): + return Size(self.fs._current_info.cluster_size * self.fs._current_info.cluster_count) + + class TmpFSSize(fstask.FSTask): description = "current filesystem size" From fcf32279b34bdf2c0f5a8adb786c424fb06bb607 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Mon, 21 Oct 2024 13:20:15 +0200 Subject: [PATCH 2/3] fs: Add support for resizing FAT filesystem --- blivet/formats/fs.py | 4 ++++ blivet/tasks/availability.py | 1 + blivet/tasks/fsminsize.py | 18 ++++++++++++++++++ blivet/tasks/fsresize.py | 16 +++++++++++++++- tests/storage_tests/formats_test/fstesting.py | 2 +- 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index eea4efc91..353a9ef38 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -1012,10 +1012,14 @@ class FATFS(FS): _uuidfs = fsuuid.FATFSUUID() _supported = True _formattable = True + _resizable = True + _resize_support = FSResize.OFFLINE_GROW | FSResize.OFFLINE_SHRINK _max_size = Size("1 TiB") _packages = ["dosfstools"] _fsck_class = fsck.DosFSCK _info_class = fsinfo.FATFSInfo + _minsize_class = fsminsize.FATFSMinSize + _resize_class = fsresize.FATFSResize _size_info_class = fssize.FATFSSize _mkfs_class = fsmkfs.FATFSMkfs _mount_class = fsmount.FATFSMount diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py index bde29c727..d5f3aa850 100644 --- a/blivet/tasks/availability.py +++ b/blivet/tasks/availability.py @@ -553,6 +553,7 @@ class FSOperation(): BLOCKDEV_EXT_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "ext2")) BLOCKDEV_XFS_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "xfs")) BLOCKDEV_NTFS_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "ntfs")) +BLOCKDEV_VFAT_RESIZE = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.RESIZE, blockdev.fs.can_resize, "vfat")) BLOCKDEV_EXT_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "ext2")) BLOCKDEV_XFS_INFO = blockdev_fs_plugin_operation(BlockDevFSMethod(FSOperation.INFO, blockdev.fs.can_get_size, "xfs")) diff --git a/blivet/tasks/fsminsize.py b/blivet/tasks/fsminsize.py index 74e02ef84..dd8248f6a 100644 --- a/blivet/tasks/fsminsize.py +++ b/blivet/tasks/fsminsize.py @@ -80,5 +80,23 @@ def do_task(self): # pylint: disable=arguments-differ return min_size +class FATFSMinSize(FSMinSize): + ext = availability.BLOCKDEV_VFAT_INFO + + def do_task(self): # pylint: disable=arguments-differ + error_msgs = self.availability_errors + if error_msgs: + raise FSError("\n".join(error_msgs)) + + try: + info = BlockDev.fs.vfat_get_info(self.fs.device) + except BlockDev.FSError as e: + raise FSError("failed to get fs min size: %s" % e) + min_size = Size((info.free_cluster_count - info.free_cluster_count) * info.cluster_size) + # resizing below 32 MiB would require changing from VFAT/FAT32 to FAT16 which is not + # currently supported by libparted which libblockdev uses for FAT resize + return max(min_size, Size("32 MiB")) + + class UnimplementedFSMinSize(fstask.UnimplementedFSTask): pass diff --git a/blivet/tasks/fsresize.py b/blivet/tasks/fsresize.py index e420fe966..ca6ef5a35 100644 --- a/blivet/tasks/fsresize.py +++ b/blivet/tasks/fsresize.py @@ -47,6 +47,10 @@ class FSResize(task.BasicApplication, FSResizeTask): # IMPLEMENTATION methods + @property + def fs_type(self): + return self.fs.type + def do_task(self): # pylint: disable=arguments-differ """ Resize the device. @@ -57,7 +61,7 @@ def do_task(self): # pylint: disable=arguments-differ raise FSError("\n".join(error_msgs)) try: - BlockDev.fs.resize(self.fs.device, self.fs.target_size.convert_to(B), self.fs.type) + BlockDev.fs.resize(self.fs.device, self.fs.target_size.convert_to(B), self.fs_type) except BlockDev.FSError as e: raise FSError(str(e)) @@ -77,6 +81,16 @@ class XFSResize(FSResize): unit = B +class FATFSResize(FSResize): + ext = availability.BLOCKDEV_VFAT_RESIZE + unit = B + + @property + def fs_type(self): + # we don't want 'efi' to be used for EFIFS + return "vfat" + + class TmpFSResize(FSResize): ext = availability.BLOCKDEV_FS_PLUGIN unit = MiB diff --git a/tests/storage_tests/formats_test/fstesting.py b/tests/storage_tests/formats_test/fstesting.py index 16d6dba45..ee158bbae 100644 --- a/tests/storage_tests/formats_test/fstesting.py +++ b/tests/storage_tests/formats_test/fstesting.py @@ -278,7 +278,7 @@ def test_shrink(self): an_fs.target_size = TARGET_SIZE self.assertIsNone(an_fs.do_resize()) - TARGET_SIZE = TARGET_SIZE / 2 + TARGET_SIZE = TARGET_SIZE - Size("10 MiB") self.assertTrue(TARGET_SIZE > an_fs.min_size) an_fs.target_size = TARGET_SIZE self.assertEqual(an_fs.target_size, TARGET_SIZE) From 58bdab9ef997fd861e52d8151ef7026e5fd0e6c2 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Mon, 21 Oct 2024 14:00:57 +0200 Subject: [PATCH 3/3] misc: Add libblockdev-tools to test dependencies The 'vfat-resize' tool is in this package. --- misc/install-test-dependencies.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/misc/install-test-dependencies.yml b/misc/install-test-dependencies.yml index 273780646..3a09f9da5 100644 --- a/misc/install-test-dependencies.yml +++ b/misc/install-test-dependencies.yml @@ -57,6 +57,7 @@ - gfs2-utils - stratisd - stratis-cli + - libblockdev-tools when: ansible_distribution == 'Fedora' and test_dependencies|bool ####### CentOS 9/10 @@ -103,6 +104,7 @@ - iscsi-initiator-utils - stratisd - stratis-cli + - libblockdev-tools when: ansible_distribution == 'CentOS' and test_dependencies|bool - name: Install additional test dependencies (CentOS 9) @@ -175,6 +177,7 @@ - targetcli-fb - open-iscsi - gfs2-utils + - libblockdev-tools when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu' and test_dependencies|bool - name: Install libmount (Debian/Ubuntu)