From 8ceac4c75e670ce2c17f8386ce22f936cd6bff0c Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Wed, 17 May 2023 19:48:29 +0200 Subject: [PATCH] Allow resizing of inactive LVs with latest LVM (#2188830) --- ...zing-of-inactive-LVs-with-latest-LVM.patch | 171 ++++++++++++++++++ libblockdev.spec | 8 +- 2 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 0001-Allow-resizing-of-inactive-LVs-with-latest-LVM.patch diff --git a/0001-Allow-resizing-of-inactive-LVs-with-latest-LVM.patch b/0001-Allow-resizing-of-inactive-LVs-with-latest-LVM.patch new file mode 100644 index 0000000..f6424cb --- /dev/null +++ b/0001-Allow-resizing-of-inactive-LVs-with-latest-LVM.patch @@ -0,0 +1,171 @@ +From 1536c3fcc0e887a2116ff035bda187a4eab4ef47 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 17 May 2023 15:49:14 +0200 +Subject: [PATCH] Allow resizing of inactive LVs with latest LVM + +Latest LVM doesn't allow resizing of inactive LVs without the +"--fs ignore" option to protect users from corrupting their +filesystems. As a low level API we don't really want to offer this +kind of protection and we should allow to resize an inactive LV. +--- + src/plugins/lvm-dbus.c | 28 +++++++++++++++++++++++++++- + src/plugins/lvm.c | 30 +++++++++++++++++++++++++++--- + tests/lvm_dbus_tests.py | 4 ++++ + tests/lvm_test.py | 4 ++++ + tests/skip.yml | 6 ++++++ + 5 files changed, 68 insertions(+), 4 deletions(-) + +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index 51572c9a..1408236a 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -63,6 +63,8 @@ static gchar *global_config_str = NULL; + #define METHOD_CALL_TIMEOUT 5000 + #define PROGRESS_WAIT 500 * 1000 /* microseconds */ + ++#define LVM_VERSION_FSRESIZE "2.03.19" ++ + #define UNUSED __attribute__((unused)) + + static GDBusConnection *bus = NULL; +@@ -2102,6 +2104,15 @@ gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 si + GVariantBuilder builder; + GVariantType *type = NULL; + GVariant *params = NULL; ++ GVariant *extra_params = NULL; ++ gboolean success = FALSE; ++ BDLVMLVdata *lvinfo = NULL; ++ GError *l_error = NULL; ++ ++ lvinfo = bd_lvm_lvinfo (vg_name, lv_name, error); ++ if (!lvinfo) ++ /* error is already populated */ ++ return FALSE; + + g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE); + g_variant_builder_add_value (&builder, g_variant_new ("t", size)); +@@ -2111,7 +2122,22 @@ gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 si + params = g_variant_builder_end (&builder); + g_variant_builder_clear (&builder); + +- call_lv_method_sync (vg_name, lv_name, "Resize", params, NULL, extra, TRUE, error); ++ if (lvinfo->attr[4] != 'a') { ++ /* starting with 2.03.19 we need to add extra option to allow resizing of inactive LVs */ ++ success = bd_utils_check_util_version ("lvm", LVM_VERSION_FSRESIZE, ++ "version", "LVM version:\\s+([\\d\\.]+)", &l_error); ++ if (success) { ++ g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY); ++ g_variant_builder_add (&builder, "{sv}", "--fs", g_variant_new ("s", "ignore")); ++ extra_params = g_variant_builder_end (&builder); ++ g_variant_builder_clear (&builder); ++ } ++ g_clear_error (&l_error); ++ } ++ ++ bd_lvm_lvdata_free (lvinfo); ++ ++ call_lv_method_sync (vg_name, lv_name, "Resize", params, extra_params, extra, TRUE, error); + return (*error == NULL); + } + +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 26af0d19..a07db65b 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -31,6 +31,8 @@ + #define SECTOR_SIZE 512 + #define VDO_POOL_SUFFIX "vpool" + ++#define LVM_VERSION_FSRESIZE "2.03.19" ++ + static GMutex global_config_lock; + static gchar *global_config_str = NULL; + +@@ -1583,15 +1585,37 @@ gboolean bd_lvm_lvrename (const gchar *vg_name, const gchar *lv_name, const gcha + * Tech category: %BD_LVM_TECH_BASIC-%BD_LVM_TECH_MODE_MODIFY + */ + gboolean bd_lvm_lvresize (const gchar *vg_name, const gchar *lv_name, guint64 size, const BDExtraArg **extra, GError **error) { +- const gchar *args[6] = {"lvresize", "--force", "-L", NULL, NULL, NULL}; ++ const gchar *args[8] = {"lvresize", "--force", "-L", NULL, NULL, NULL, NULL, NULL}; + gboolean success = FALSE; ++ guint8 next_arg = 4; ++ g_autofree gchar *lvspec = NULL; ++ BDLVMLVdata *lvinfo = NULL; ++ GError *l_error = NULL; ++ ++ lvinfo = bd_lvm_lvinfo (vg_name, lv_name, error); ++ if (!lvinfo) ++ /* error is already populated */ ++ return FALSE; + + args[3] = g_strdup_printf ("%"G_GUINT64_FORMAT"K", size/1024); +- args[4] = g_strdup_printf ("%s/%s", vg_name, lv_name); ++ if (lvinfo->attr[4] != 'a') { ++ /* starting with 2.03.19 we need to add extra option to allow resizing of inactive LVs */ ++ success = bd_utils_check_util_version (deps[DEPS_LVM].name, LVM_VERSION_FSRESIZE, ++ deps[DEPS_LVM].ver_arg, deps[DEPS_LVM].ver_regexp, &l_error); ++ if (success) { ++ args[next_arg++] = "--fs"; ++ args[next_arg++] = "ignore"; ++ } ++ g_clear_error (&l_error); ++ } ++ ++ bd_lvm_lvdata_free (lvinfo); ++ ++ lvspec = g_strdup_printf ("%s/%s", vg_name, lv_name); ++ args[next_arg++] = lvspec; + + success = call_lvm_and_report_error (args, extra, TRUE, error); + g_free ((gchar *) args[3]); +- g_free ((gchar *) args[4]); + + return success; + } +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 3fb7946a..b9493642 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -901,6 +901,10 @@ class LvmTestLVresize(LvmPVVGLVTestCase): + succ = BlockDev.lvm_lvdeactivate("testVG", "testLV", None) + self.assertTrue(succ) + ++ # try to shrink when deactivated ++ succ = BlockDev.lvm_lvresize("testVG", "testLV", 400 * 1024**2, None) ++ self.assertTrue(succ) ++ + @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") + class LvmTestLVrename(LvmPVVGLVTestCase): + def test_lvrename(self): +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 7be8f1ab..8baae513 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -830,6 +830,10 @@ class LvmTestLVresize(LvmPVVGLVTestCase): + succ = BlockDev.lvm_lvdeactivate("testVG", "testLV", None) + self.assertTrue(succ) + ++ # try to shrink when deactivated ++ succ = BlockDev.lvm_lvresize("testVG", "testLV", 400 * 1024**2, None) ++ self.assertTrue(succ) ++ + class LvmTestLVrename(LvmPVVGLVTestCase): + def test_lvrename(self): + """Verify that it's possible to rename an LV""" +diff --git a/tests/skip.yml b/tests/skip.yml +index b06d05da..543d1396 100644 +--- a/tests/skip.yml ++++ b/tests/skip.yml +@@ -143,3 +143,9 @@ + - distro: "centos" + version: "9" + reason: "Creating RAID 1 LV on CentOS/RHEL 9 causes a system deadlock" ++ ++- test: (lvm_test|lvm_dbus_tests).LvmTestLVresize.test_lvresize ++ skip_on: ++ - distro: "centos" ++ version: "9" ++ reason: "LVM >= 2.03.19 is not yet available breaking our check for LVM resize on CentOS 9 Stream" +-- +2.40.1 + diff --git a/libblockdev.spec b/libblockdev.spec index 769b094..8d74b69 100644 --- a/libblockdev.spec +++ b/libblockdev.spec @@ -125,11 +125,12 @@ Name: libblockdev Version: 2.28 -Release: 5%{?dist} +Release: 6%{?dist} Summary: A library for low-level manipulation with block devices License: LGPL-2.1-or-later URL: https://github.com/storaged-project/libblockdev Source0: https://github.com/storaged-project/libblockdev/releases/download/%{version}-%{release}/%{name}-%{version}.tar.gz +Patch0: 0001-Allow-resizing-of-inactive-LVs-with-latest-LVM.patch BuildRequires: make BuildRequires: glib2-devel @@ -673,7 +674,7 @@ A meta-package that pulls all the libblockdev plugins as dependencies. %prep -%setup -q -n %{name}-%{version} +%autosetup -n %{name}-%{version} -p1 %build autoreconf -ivf @@ -977,6 +978,9 @@ find %{buildroot} -type f -name "*.la" | xargs %{__rm} %files plugins-all %changelog +* Wed May 17 2023 Vojtech Trefny - 2.28-6 +- Allow resizing of inactive LVs with latest LVM (#2188830) + * Fri Mar 17 2023 Vojtech Trefny - 2.28-5 - Stop building dm plugin with dmraid support on Fedora >= 38