|
|
f01d01 |
From 433d863cd8a57e5fc30948ff905e6a477ed5f17c Mon Sep 17 00:00:00 2001
|
|
|
f01d01 |
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
|
f01d01 |
Date: Tue, 14 Jul 2020 11:27:08 +0200
|
|
|
f01d01 |
Subject: [PATCH 1/4] Add support for XFS format grow
|
|
|
f01d01 |
|
|
|
f01d01 |
---
|
|
|
f01d01 |
blivet/formats/fs.py | 2 ++
|
|
|
f01d01 |
blivet/tasks/availability.py | 1 +
|
|
|
f01d01 |
blivet/tasks/fsresize.py | 54 ++++++++++++++++++++++++++++++++++++
|
|
|
f01d01 |
3 files changed, 57 insertions(+)
|
|
|
f01d01 |
|
|
|
f01d01 |
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
|
|
|
f01d01 |
index eee15aaa..12cb9885 100644
|
|
|
f01d01 |
--- a/blivet/formats/fs.py
|
|
|
f01d01 |
+++ b/blivet/formats/fs.py
|
|
|
f01d01 |
@@ -1089,11 +1089,13 @@ class XFS(FS):
|
|
|
f01d01 |
_formattable = True
|
|
|
f01d01 |
_linux_native = True
|
|
|
f01d01 |
_supported = True
|
|
|
f01d01 |
+ _resizable = True
|
|
|
f01d01 |
_packages = ["xfsprogs"]
|
|
|
f01d01 |
_info_class = fsinfo.XFSInfo
|
|
|
f01d01 |
_mkfs_class = fsmkfs.XFSMkfs
|
|
|
f01d01 |
_readlabel_class = fsreadlabel.XFSReadLabel
|
|
|
f01d01 |
_size_info_class = fssize.XFSSize
|
|
|
f01d01 |
+ _resize_class = fsresize.XFSResize
|
|
|
f01d01 |
_sync_class = fssync.XFSSync
|
|
|
f01d01 |
_writelabel_class = fswritelabel.XFSWriteLabel
|
|
|
f01d01 |
_writeuuid_class = fswriteuuid.XFSWriteUUID
|
|
|
f01d01 |
diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py
|
|
|
f01d01 |
index b6b5955a..df62780c 100644
|
|
|
f01d01 |
--- a/blivet/tasks/availability.py
|
|
|
f01d01 |
+++ b/blivet/tasks/availability.py
|
|
|
f01d01 |
@@ -455,5 +455,6 @@ TUNE2FS_APP = application_by_version("tune2fs", E2FSPROGS_VERSION)
|
|
|
f01d01 |
XFSADMIN_APP = application("xfs_admin")
|
|
|
f01d01 |
XFSDB_APP = application("xfs_db")
|
|
|
f01d01 |
XFSFREEZE_APP = application("xfs_freeze")
|
|
|
f01d01 |
+XFSRESIZE_APP = application("xfs_growfs")
|
|
|
f01d01 |
|
|
|
f01d01 |
MOUNT_APP = application("mount")
|
|
|
f01d01 |
diff --git a/blivet/tasks/fsresize.py b/blivet/tasks/fsresize.py
|
|
|
f01d01 |
index e7e26984..12c0367f 100644
|
|
|
f01d01 |
--- a/blivet/tasks/fsresize.py
|
|
|
f01d01 |
+++ b/blivet/tasks/fsresize.py
|
|
|
f01d01 |
@@ -20,7 +20,10 @@
|
|
|
f01d01 |
# Red Hat Author(s): Anne Mulhern <amulhern@redhat.com>
|
|
|
f01d01 |
|
|
|
f01d01 |
import abc
|
|
|
f01d01 |
+import os
|
|
|
f01d01 |
+import tempfile
|
|
|
f01d01 |
|
|
|
f01d01 |
+from contextlib import contextmanager
|
|
|
f01d01 |
from six import add_metaclass
|
|
|
f01d01 |
|
|
|
f01d01 |
from ..errors import FSError
|
|
|
f01d01 |
@@ -32,6 +35,9 @@ from . import task
|
|
|
f01d01 |
from . import fstask
|
|
|
f01d01 |
from . import dfresize
|
|
|
f01d01 |
|
|
|
f01d01 |
+import logging
|
|
|
f01d01 |
+log = logging.getLogger("blivet")
|
|
|
f01d01 |
+
|
|
|
f01d01 |
|
|
|
f01d01 |
@add_metaclass(abc.ABCMeta)
|
|
|
f01d01 |
class FSResizeTask(fstask.FSTask):
|
|
|
f01d01 |
@@ -115,6 +121,54 @@ class NTFSResize(FSResize):
|
|
|
f01d01 |
]
|
|
|
f01d01 |
|
|
|
f01d01 |
|
|
|
f01d01 |
+class XFSResize(FSResize):
|
|
|
f01d01 |
+ ext = availability.XFSRESIZE_APP
|
|
|
f01d01 |
+ unit = B
|
|
|
f01d01 |
+ size_fmt = None
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ @contextmanager
|
|
|
f01d01 |
+ def _do_temp_mount(self):
|
|
|
f01d01 |
+ if self.fs.status:
|
|
|
f01d01 |
+ yield
|
|
|
f01d01 |
+ else:
|
|
|
f01d01 |
+ dev_name = os.path.basename(self.fs.device)
|
|
|
f01d01 |
+ tmpdir = tempfile.mkdtemp(prefix="xfs-tempmount-%s" % dev_name)
|
|
|
f01d01 |
+ log.debug("mounting XFS on '%s' to '%s' for resize", self.fs.device, tmpdir)
|
|
|
f01d01 |
+ try:
|
|
|
f01d01 |
+ self.fs.mount(mountpoint=tmpdir)
|
|
|
f01d01 |
+ except FSError as e:
|
|
|
f01d01 |
+ raise FSError("Failed to mount XFS filesystem for resize: %s" % str(e))
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ try:
|
|
|
f01d01 |
+ yield
|
|
|
f01d01 |
+ finally:
|
|
|
f01d01 |
+ util.umount(mountpoint=tmpdir)
|
|
|
f01d01 |
+ os.rmdir(tmpdir)
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def _get_block_size(self):
|
|
|
f01d01 |
+ if self.fs._current_info:
|
|
|
f01d01 |
+ # this should be set by update_size_info()
|
|
|
f01d01 |
+ for line in self.fs._current_info.split("\n"):
|
|
|
f01d01 |
+ if line.startswith("blocksize ="):
|
|
|
f01d01 |
+ return int(line.split("=")[-1])
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ raise FSError("Failed to get XFS filesystem block size for resize")
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def size_spec(self):
|
|
|
f01d01 |
+ # size for xfs_growfs is in blocks
|
|
|
f01d01 |
+ return str(self.fs.target_size.convert_to(self.unit) / self._get_block_size())
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ @property
|
|
|
f01d01 |
+ def args(self):
|
|
|
f01d01 |
+ return [self.fs.system_mountpoint, "-D", self.size_spec()]
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def do_task(self):
|
|
|
f01d01 |
+ """ Resizes the XFS format. """
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ with self._do_temp_mount():
|
|
|
f01d01 |
+ super(XFSResize, self).do_task()
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+
|
|
|
f01d01 |
class TmpFSResize(FSResize):
|
|
|
f01d01 |
|
|
|
f01d01 |
ext = availability.MOUNT_APP
|
|
|
f01d01 |
--
|
|
|
f01d01 |
2.26.2
|
|
|
f01d01 |
|
|
|
f01d01 |
|
|
|
f01d01 |
From 56d05334231c30699a9c77dedbc23fdb021b9dee Mon Sep 17 00:00:00 2001
|
|
|
f01d01 |
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
|
f01d01 |
Date: Tue, 14 Jul 2020 11:27:51 +0200
|
|
|
f01d01 |
Subject: [PATCH 2/4] Add tests for XFS resize
|
|
|
f01d01 |
|
|
|
f01d01 |
XFS supports only grow so we can't reuse most of the fstesting
|
|
|
f01d01 |
code and we also need to test the resize on partition because
|
|
|
f01d01 |
XFS won't allow grow to size bigger than the underlying block
|
|
|
f01d01 |
device.
|
|
|
f01d01 |
---
|
|
|
f01d01 |
tests/formats_test/fs_test.py | 91 +++++++++++++++++++++++++++++++++
|
|
|
f01d01 |
tests/formats_test/fstesting.py | 33 ++++++------
|
|
|
f01d01 |
2 files changed, 107 insertions(+), 17 deletions(-)
|
|
|
f01d01 |
|
|
|
f01d01 |
diff --git a/tests/formats_test/fs_test.py b/tests/formats_test/fs_test.py
|
|
|
f01d01 |
index 15fc0c35..9bc5d20d 100644
|
|
|
f01d01 |
--- a/tests/formats_test/fs_test.py
|
|
|
f01d01 |
+++ b/tests/formats_test/fs_test.py
|
|
|
f01d01 |
@@ -2,8 +2,13 @@ import os
|
|
|
f01d01 |
import tempfile
|
|
|
f01d01 |
import unittest
|
|
|
f01d01 |
|
|
|
f01d01 |
+import parted
|
|
|
f01d01 |
+
|
|
|
f01d01 |
import blivet.formats.fs as fs
|
|
|
f01d01 |
from blivet.size import Size, ROUND_DOWN
|
|
|
f01d01 |
+from blivet.errors import DeviceFormatError
|
|
|
f01d01 |
+from blivet.formats import get_format
|
|
|
f01d01 |
+from blivet.devices import PartitionDevice, DiskDevice
|
|
|
f01d01 |
|
|
|
f01d01 |
from tests import loopbackedtestcase
|
|
|
f01d01 |
|
|
|
f01d01 |
@@ -50,6 +55,92 @@ class ReiserFSTestCase(fstesting.FSAsRoot):
|
|
|
f01d01 |
class XFSTestCase(fstesting.FSAsRoot):
|
|
|
f01d01 |
_fs_class = fs.XFS
|
|
|
f01d01 |
|
|
|
f01d01 |
+ def can_resize(self, an_fs):
|
|
|
f01d01 |
+ resize_tasks = (an_fs._resize, an_fs._size_info)
|
|
|
f01d01 |
+ return not any(t.availability_errors for t in resize_tasks)
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def _create_partition(self, disk, size):
|
|
|
f01d01 |
+ disk.format = get_format("disklabel", device=disk.path, label_type="msdos")
|
|
|
f01d01 |
+ disk.format.create()
|
|
|
f01d01 |
+ pstart = disk.format.alignment.grainSize
|
|
|
f01d01 |
+ pend = pstart + int(Size(size) / disk.format.parted_device.sectorSize)
|
|
|
f01d01 |
+ disk.format.add_partition(pstart, pend, parted.PARTITION_NORMAL)
|
|
|
f01d01 |
+ disk.format.parted_disk.commit()
|
|
|
f01d01 |
+ part = disk.format.parted_disk.getPartitionBySector(pstart)
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ device = PartitionDevice(os.path.basename(part.path))
|
|
|
f01d01 |
+ device.disk = disk
|
|
|
f01d01 |
+ device.exists = True
|
|
|
f01d01 |
+ device.parted_partition = part
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ return device
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def _remove_partition(self, partition, disk):
|
|
|
f01d01 |
+ disk.format.remove_partition(partition.parted_partition)
|
|
|
f01d01 |
+ disk.format.parted_disk.commit()
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def test_resize(self):
|
|
|
f01d01 |
+ an_fs = self._fs_class()
|
|
|
f01d01 |
+ if not an_fs.formattable:
|
|
|
f01d01 |
+ self.skipTest("can not create filesystem %s" % an_fs.name)
|
|
|
f01d01 |
+ an_fs.device = self.loop_devices[0]
|
|
|
f01d01 |
+ self.assertIsNone(an_fs.create())
|
|
|
f01d01 |
+ an_fs.update_size_info()
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ self._test_sizes(an_fs)
|
|
|
f01d01 |
+ # CHECKME: target size is still 0 after updated_size_info is called.
|
|
|
f01d01 |
+ self.assertEqual(an_fs.size, Size(0) if an_fs.resizable else an_fs._size)
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ if not self.can_resize(an_fs):
|
|
|
f01d01 |
+ self.assertFalse(an_fs.resizable)
|
|
|
f01d01 |
+ # Not resizable, so can not do resizing actions.
|
|
|
f01d01 |
+ with self.assertRaises(DeviceFormatError):
|
|
|
f01d01 |
+ an_fs.target_size = Size("64 MiB")
|
|
|
f01d01 |
+ with self.assertRaises(DeviceFormatError):
|
|
|
f01d01 |
+ an_fs.do_resize()
|
|
|
f01d01 |
+ else:
|
|
|
f01d01 |
+ disk = DiskDevice(os.path.basename(self.loop_devices[0]))
|
|
|
f01d01 |
+ part = self._create_partition(disk, Size("50 MiB"))
|
|
|
f01d01 |
+ an_fs = self._fs_class()
|
|
|
f01d01 |
+ an_fs.device = part.path
|
|
|
f01d01 |
+ self.assertIsNone(an_fs.create())
|
|
|
f01d01 |
+ an_fs.update_size_info()
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ self.assertTrue(an_fs.resizable)
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ # grow the partition so we can grow the filesystem
|
|
|
f01d01 |
+ self._remove_partition(part, disk)
|
|
|
f01d01 |
+ part = self._create_partition(disk, size=part.size + Size("40 MiB"))
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ # Try a reasonable target size
|
|
|
f01d01 |
+ TARGET_SIZE = Size("64 MiB")
|
|
|
f01d01 |
+ an_fs.target_size = TARGET_SIZE
|
|
|
f01d01 |
+ self.assertEqual(an_fs.target_size, TARGET_SIZE)
|
|
|
f01d01 |
+ self.assertNotEqual(an_fs._size, TARGET_SIZE)
|
|
|
f01d01 |
+ self.assertIsNone(an_fs.do_resize())
|
|
|
f01d01 |
+ ACTUAL_SIZE = TARGET_SIZE.round_to_nearest(an_fs._resize.unit, rounding=ROUND_DOWN)
|
|
|
f01d01 |
+ self.assertEqual(an_fs.size, ACTUAL_SIZE)
|
|
|
f01d01 |
+ self.assertEqual(an_fs._size, ACTUAL_SIZE)
|
|
|
f01d01 |
+ self._test_sizes(an_fs)
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ self._remove_partition(part, disk)
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ # and no errors should occur when checking
|
|
|
f01d01 |
+ self.assertIsNone(an_fs.do_check())
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def test_shrink(self):
|
|
|
f01d01 |
+ self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def test_too_small(self):
|
|
|
f01d01 |
+ self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def test_no_explicit_target_size2(self):
|
|
|
f01d01 |
+ self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def test_too_big2(self):
|
|
|
f01d01 |
+ # XXX this tests assumes that resizing to max size - 1 B will fail, but xfs_grow won't
|
|
|
f01d01 |
+ self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
+
|
|
|
f01d01 |
|
|
|
f01d01 |
class HFSTestCase(fstesting.FSAsRoot):
|
|
|
f01d01 |
_fs_class = fs.HFS
|
|
|
f01d01 |
diff --git a/tests/formats_test/fstesting.py b/tests/formats_test/fstesting.py
|
|
|
f01d01 |
index 62f806f9..86b2a116 100644
|
|
|
f01d01 |
--- a/tests/formats_test/fstesting.py
|
|
|
f01d01 |
+++ b/tests/formats_test/fstesting.py
|
|
|
f01d01 |
@@ -11,16 +11,6 @@ from blivet.size import Size, ROUND_DOWN
|
|
|
f01d01 |
from blivet.formats import fs
|
|
|
f01d01 |
|
|
|
f01d01 |
|
|
|
f01d01 |
-def can_resize(an_fs):
|
|
|
f01d01 |
- """ Returns True if this filesystem has all necessary resizing tools
|
|
|
f01d01 |
- available.
|
|
|
f01d01 |
-
|
|
|
f01d01 |
- :param an_fs: a filesystem object
|
|
|
f01d01 |
- """
|
|
|
f01d01 |
- resize_tasks = (an_fs._resize, an_fs._size_info, an_fs._minsize)
|
|
|
f01d01 |
- return not any(t.availability_errors for t in resize_tasks)
|
|
|
f01d01 |
-
|
|
|
f01d01 |
-
|
|
|
f01d01 |
@add_metaclass(abc.ABCMeta)
|
|
|
f01d01 |
class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
|
|
|
f01d01 |
@@ -32,6 +22,15 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
def __init__(self, methodName='run_test'):
|
|
|
f01d01 |
super(FSAsRoot, self).__init__(methodName=methodName, device_spec=[self._DEVICE_SIZE])
|
|
|
f01d01 |
|
|
|
f01d01 |
+ def can_resize(self, an_fs):
|
|
|
f01d01 |
+ """ Returns True if this filesystem has all necessary resizing tools
|
|
|
f01d01 |
+ available.
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ :param an_fs: a filesystem object
|
|
|
f01d01 |
+ """
|
|
|
f01d01 |
+ resize_tasks = (an_fs._resize, an_fs._size_info, an_fs._minsize)
|
|
|
f01d01 |
+ return not any(t.availability_errors for t in resize_tasks)
|
|
|
f01d01 |
+
|
|
|
f01d01 |
def _test_sizes(self, an_fs):
|
|
|
f01d01 |
""" Test relationships between different size values.
|
|
|
f01d01 |
|
|
|
f01d01 |
@@ -190,7 +189,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
# CHECKME: target size is still 0 after updated_size_info is called.
|
|
|
f01d01 |
self.assertEqual(an_fs.size, Size(0) if an_fs.resizable else an_fs._size)
|
|
|
f01d01 |
|
|
|
f01d01 |
- if not can_resize(an_fs):
|
|
|
f01d01 |
+ if not self.can_resize(an_fs):
|
|
|
f01d01 |
self.assertFalse(an_fs.resizable)
|
|
|
f01d01 |
# Not resizable, so can not do resizing actions.
|
|
|
f01d01 |
with self.assertRaises(DeviceFormatError):
|
|
|
f01d01 |
@@ -221,7 +220,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
# in constructor call behavior would be different.
|
|
|
f01d01 |
|
|
|
f01d01 |
an_fs = self._fs_class()
|
|
|
f01d01 |
- if not can_resize(an_fs):
|
|
|
f01d01 |
+ if not self.can_resize(an_fs):
|
|
|
f01d01 |
self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
if not an_fs.formattable:
|
|
|
f01d01 |
self.skipTest("can not create filesystem %s" % an_fs.name)
|
|
|
f01d01 |
@@ -244,7 +243,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
"""
|
|
|
f01d01 |
SIZE = Size("64 MiB")
|
|
|
f01d01 |
an_fs = self._fs_class(size=SIZE)
|
|
|
f01d01 |
- if not can_resize(an_fs):
|
|
|
f01d01 |
+ if not self.can_resize(an_fs):
|
|
|
f01d01 |
self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
if not an_fs.formattable:
|
|
|
f01d01 |
self.skipTest("can not create filesystem %s" % an_fs.name)
|
|
|
f01d01 |
@@ -264,7 +263,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
|
|
|
f01d01 |
def test_shrink(self):
|
|
|
f01d01 |
an_fs = self._fs_class()
|
|
|
f01d01 |
- if not can_resize(an_fs):
|
|
|
f01d01 |
+ if not self.can_resize(an_fs):
|
|
|
f01d01 |
self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
if not an_fs.formattable:
|
|
|
f01d01 |
self.skipTest("can not create filesystem %s" % an_fs.name)
|
|
|
f01d01 |
@@ -296,7 +295,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
|
|
|
f01d01 |
def test_too_small(self):
|
|
|
f01d01 |
an_fs = self._fs_class()
|
|
|
f01d01 |
- if not can_resize(an_fs):
|
|
|
f01d01 |
+ if not self.can_resize(an_fs):
|
|
|
f01d01 |
self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
if not an_fs.formattable:
|
|
|
f01d01 |
self.skipTest("can not create or resize filesystem %s" % an_fs.name)
|
|
|
f01d01 |
@@ -315,7 +314,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
|
|
|
f01d01 |
def test_too_big(self):
|
|
|
f01d01 |
an_fs = self._fs_class()
|
|
|
f01d01 |
- if not can_resize(an_fs):
|
|
|
f01d01 |
+ if not self.can_resize(an_fs):
|
|
|
f01d01 |
self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
if not an_fs.formattable:
|
|
|
f01d01 |
self.skipTest("can not create filesystem %s" % an_fs.name)
|
|
|
f01d01 |
@@ -334,7 +333,7 @@ class FSAsRoot(loopbackedtestcase.LoopBackedTestCase):
|
|
|
f01d01 |
|
|
|
f01d01 |
def test_too_big2(self):
|
|
|
f01d01 |
an_fs = self._fs_class()
|
|
|
f01d01 |
- if not can_resize(an_fs):
|
|
|
f01d01 |
+ if not self.can_resize(an_fs):
|
|
|
f01d01 |
self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
if not an_fs.formattable:
|
|
|
f01d01 |
self.skipTest("can not create filesystem %s" % an_fs.name)
|
|
|
f01d01 |
--
|
|
|
f01d01 |
2.26.2
|
|
|
f01d01 |
|
|
|
f01d01 |
|
|
|
f01d01 |
From 51acc04f4639f143b55789a06a68aae988a91296 Mon Sep 17 00:00:00 2001
|
|
|
f01d01 |
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
|
f01d01 |
Date: Wed, 15 Jul 2020 12:59:04 +0200
|
|
|
f01d01 |
Subject: [PATCH 3/4] Add support for checking and fixing XFS using xfs_repair
|
|
|
f01d01 |
|
|
|
f01d01 |
---
|
|
|
f01d01 |
blivet/formats/fs.py | 1 +
|
|
|
f01d01 |
blivet/tasks/availability.py | 1 +
|
|
|
f01d01 |
blivet/tasks/fsck.py | 12 ++++++++++++
|
|
|
f01d01 |
tests/formats_test/fs_test.py | 6 +++---
|
|
|
f01d01 |
4 files changed, 17 insertions(+), 3 deletions(-)
|
|
|
f01d01 |
|
|
|
f01d01 |
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
|
|
|
f01d01 |
index 12cb9885..06fbdf10 100644
|
|
|
f01d01 |
--- a/blivet/formats/fs.py
|
|
|
f01d01 |
+++ b/blivet/formats/fs.py
|
|
|
f01d01 |
@@ -1091,6 +1091,7 @@ class XFS(FS):
|
|
|
f01d01 |
_supported = True
|
|
|
f01d01 |
_resizable = True
|
|
|
f01d01 |
_packages = ["xfsprogs"]
|
|
|
f01d01 |
+ _fsck_class = fsck.XFSCK
|
|
|
f01d01 |
_info_class = fsinfo.XFSInfo
|
|
|
f01d01 |
_mkfs_class = fsmkfs.XFSMkfs
|
|
|
f01d01 |
_readlabel_class = fsreadlabel.XFSReadLabel
|
|
|
f01d01 |
diff --git a/blivet/tasks/availability.py b/blivet/tasks/availability.py
|
|
|
f01d01 |
index df62780c..f3b76650 100644
|
|
|
f01d01 |
--- a/blivet/tasks/availability.py
|
|
|
f01d01 |
+++ b/blivet/tasks/availability.py
|
|
|
f01d01 |
@@ -456,5 +456,6 @@ XFSADMIN_APP = application("xfs_admin")
|
|
|
f01d01 |
XFSDB_APP = application("xfs_db")
|
|
|
f01d01 |
XFSFREEZE_APP = application("xfs_freeze")
|
|
|
f01d01 |
XFSRESIZE_APP = application("xfs_growfs")
|
|
|
f01d01 |
+XFSREPAIR_APP = application("xfs_repair")
|
|
|
f01d01 |
|
|
|
f01d01 |
MOUNT_APP = application("mount")
|
|
|
f01d01 |
diff --git a/blivet/tasks/fsck.py b/blivet/tasks/fsck.py
|
|
|
f01d01 |
index 5274f13a..8477f5f8 100644
|
|
|
f01d01 |
--- a/blivet/tasks/fsck.py
|
|
|
f01d01 |
+++ b/blivet/tasks/fsck.py
|
|
|
f01d01 |
@@ -123,6 +123,18 @@ class Ext2FSCK(FSCK):
|
|
|
f01d01 |
return "\n".join(msgs) or None
|
|
|
f01d01 |
|
|
|
f01d01 |
|
|
|
f01d01 |
+class XFSCK(FSCK):
|
|
|
f01d01 |
+ _fsck_errors = {1: "Runtime error encountered during repair operation.",
|
|
|
f01d01 |
+ 2: "XFS repair was unable to proceed due to a dirty log."}
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ ext = availability.XFSREPAIR_APP
|
|
|
f01d01 |
+ options = []
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+ def _error_message(self, rc):
|
|
|
f01d01 |
+ msgs = (self._fsck_errors[c] for c in self._fsck_errors.keys() if rc & c)
|
|
|
f01d01 |
+ return "\n".join(msgs) or None
|
|
|
f01d01 |
+
|
|
|
f01d01 |
+
|
|
|
f01d01 |
class HFSPlusFSCK(FSCK):
|
|
|
f01d01 |
_fsck_errors = {3: "Quick check found a dirty filesystem; no repairs done.",
|
|
|
f01d01 |
4: "Root filesystem was dirty. System should be rebooted.",
|
|
|
f01d01 |
diff --git a/tests/formats_test/fs_test.py b/tests/formats_test/fs_test.py
|
|
|
f01d01 |
index 9bc5d20d..8fb099fd 100644
|
|
|
f01d01 |
--- a/tests/formats_test/fs_test.py
|
|
|
f01d01 |
+++ b/tests/formats_test/fs_test.py
|
|
|
f01d01 |
@@ -123,10 +123,10 @@ class XFSTestCase(fstesting.FSAsRoot):
|
|
|
f01d01 |
self.assertEqual(an_fs._size, ACTUAL_SIZE)
|
|
|
f01d01 |
self._test_sizes(an_fs)
|
|
|
f01d01 |
|
|
|
f01d01 |
- self._remove_partition(part, disk)
|
|
|
f01d01 |
+ # and no errors should occur when checking
|
|
|
f01d01 |
+ self.assertIsNone(an_fs.do_check())
|
|
|
f01d01 |
|
|
|
f01d01 |
- # and no errors should occur when checking
|
|
|
f01d01 |
- self.assertIsNone(an_fs.do_check())
|
|
|
f01d01 |
+ self._remove_partition(part, disk)
|
|
|
f01d01 |
|
|
|
f01d01 |
def test_shrink(self):
|
|
|
f01d01 |
self.skipTest("Not checking resize for this test category.")
|
|
|
f01d01 |
--
|
|
|
f01d01 |
2.26.2
|
|
|
f01d01 |
|
|
|
f01d01 |
|
|
|
f01d01 |
From 2a6947098e66f880193f3bac2282a6c7857ca5f7 Mon Sep 17 00:00:00 2001
|
|
|
f01d01 |
From: Vojtech Trefny <vtrefny@redhat.com>
|
|
|
f01d01 |
Date: Thu, 16 Jul 2020 09:05:35 +0200
|
|
|
f01d01 |
Subject: [PATCH 4/4] Use xfs_db in read-only mode when getting XFS information
|
|
|
f01d01 |
|
|
|
f01d01 |
This way it will also work on mounted filesystems.
|
|
|
f01d01 |
---
|
|
|
f01d01 |
blivet/tasks/fsinfo.py | 2 +-
|
|
|
f01d01 |
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
f01d01 |
|
|
|
f01d01 |
diff --git a/blivet/tasks/fsinfo.py b/blivet/tasks/fsinfo.py
|
|
|
f01d01 |
index af208f5d..41ff700f 100644
|
|
|
f01d01 |
--- a/blivet/tasks/fsinfo.py
|
|
|
f01d01 |
+++ b/blivet/tasks/fsinfo.py
|
|
|
f01d01 |
@@ -95,7 +95,7 @@ class ReiserFSInfo(FSInfo):
|
|
|
f01d01 |
|
|
|
f01d01 |
class XFSInfo(FSInfo):
|
|
|
f01d01 |
ext = availability.XFSDB_APP
|
|
|
f01d01 |
- options = ["-c", "sb 0", "-c", "p dblocks", "-c", "p blocksize"]
|
|
|
f01d01 |
+ options = ["-c", "sb 0", "-c", "p dblocks", "-c", "p blocksize", "-r"]
|
|
|
f01d01 |
|
|
|
f01d01 |
|
|
|
f01d01 |
class UnimplementedFSInfo(fstask.UnimplementedFSTask):
|
|
|
f01d01 |
--
|
|
|
f01d01 |
2.26.2
|
|
|
f01d01 |
|