From bb62668d70ce486cc1b2c0d3cf8e602b800a5e3b Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Sep 22 2022 07:39:27 +0000 Subject: Rebase to the latest upstream release 2.28 Resolves: rhbz#2123346 Resolves: rhbz#2121072 Resolves: rhbz#2116544 --- diff --git a/.gitignore b/.gitignore index ae739c7..dfba974 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ /libblockdev-2.23.tar.gz /libblockdev-2.24.tar.gz /libblockdev-2.25.tar.gz +/libblockdev-2.28.tar.gz diff --git a/0001-Fix-comparing-DM-RAID-member-devices-UUID.patch b/0001-Fix-comparing-DM-RAID-member-devices-UUID.patch deleted file mode 100644 index 0c3eedc..0000000 --- a/0001-Fix-comparing-DM-RAID-member-devices-UUID.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 2da13152619ee7233650339797657b45088b2219 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 18 Aug 2020 09:44:29 +0200 -Subject: [PATCH] dm: Fix comparing DM RAID member devices UUID - -There is no "UUID" property in UDev we must use the "ID_FS_UUID" -one. -This comparison works only because most DM RAID members don't have -UUID so the check is skipped, but it fails for DDF RAID members -which have a special GUID/UUID in UDev database. ---- - src/plugins/dm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/plugins/dm.c b/src/plugins/dm.c -index a6412028..4ab0d2a4 100644 ---- a/src/plugins/dm.c -+++ b/src/plugins/dm.c -@@ -482,7 +482,7 @@ static gboolean raid_dev_matches_spec (struct raid_dev *raid_dev, const gchar *n - - context = udev_new (); - device = udev_device_new_from_subsystem_sysname (context, "block", dev_name); -- dev_uuid = udev_device_get_property_value (device, "UUID"); -+ dev_uuid = udev_device_get_property_value (device, "ID_FS_UUID"); - major_str = udev_device_get_property_value (device, "MAJOR"); - minor_str = udev_device_get_property_value (device, "MINOR"); - diff --git a/0001-lvm-devices-file-support.patch b/0001-lvm-devices-file-support.patch new file mode 100644 index 0000000..9e38b41 --- /dev/null +++ b/0001-lvm-devices-file-support.patch @@ -0,0 +1,1808 @@ +From 94d707dd225104ba14422eeb43c73b1f742b12da Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 13 Jul 2021 13:22:05 +0200 +Subject: [PATCH 1/7] lvm: Allow configuring global "device filter" for LVM + commands + +Starting with 2.03.12 LVM introduces a new system for telling LVM +which devices it should use. The old device filters in config are +no longer working and we need to use either the system.devices +config file in /etc/lvm/devices (default behaviour) or specify +all allowed devices using the new --devices option. Because this +option must be specified for every call which might be incovenient +for our users, this commit introduces a new function to configure +this globally, which we already do for the --config option. +--- + src/lib/plugin_apis/lvm.api | 23 +++ + src/plugins/lvm-dbus.c | 75 ++++++++- + src/plugins/lvm.c | 97 ++++++++++-- + src/plugins/lvm.h | 4 + + tests/library_test.py | 304 ++++++++++++++++++++---------------- + tests/lvm_dbus_tests.py | 47 +++++- + tests/lvm_test.py | 50 ++++++ + tests/overrides_test.py | 23 ++- + 8 files changed, 470 insertions(+), 153 deletions(-) + +diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api +index c695c111..23f68b81 100644 +--- a/src/lib/plugin_apis/lvm.api ++++ b/src/lib/plugin_apis/lvm.api +@@ -601,6 +601,7 @@ typedef enum { + BD_LVM_TECH_CACHE_CALCS, + BD_LVM_TECH_GLOB_CONF, + BD_LVM_TECH_VDO, ++ BD_LVM_TECH_DEVICES, + } BDLVMTech; + + typedef enum { +@@ -1214,6 +1215,28 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error); + */ + gchar* bd_lvm_get_global_config (GError **error); + ++/** ++ * bd_lvm_set_devices_filter: ++ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the devices filter was successfully set or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error); ++ ++/** ++ * bd_lvm_get_devices_filter: ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of ++ * the currently set LVM devices filter ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gchar** bd_lvm_get_devices_filter (GError **error); ++ + /** + * bd_lvm_cache_get_default_md_size: + * @cache_size: size of the cache to determine MD size for +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index 51572c9a..b47ed0ef 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -35,6 +35,8 @@ + static GMutex global_config_lock; + static gchar *global_config_str = NULL; + ++static gchar *global_devices_str = NULL; ++ + #define LVM_BUS_NAME "com.redhat.lvmdbus1" + #define LVM_OBJ_PREFIX "/com/redhat/lvmdbus1" + #define MANAGER_OBJ "/com/redhat/lvmdbus1/Manager" +@@ -241,11 +243,20 @@ static gboolean setup_dbus_connection (GError **error) { + return TRUE; + } + ++static volatile guint avail_deps = 0; + static volatile guint avail_dbus_deps = 0; + static volatile guint avail_features = 0; + static volatile guint avail_module_deps = 0; + static GMutex deps_check_lock; + ++#define DEPS_LVMDEVICES 0 ++#define DEPS_LVMDEVICES_MASK (1 << DEPS_LVMDEVICES) ++#define DEPS_LAST 1 ++ ++static const UtilDep deps[DEPS_LAST] = { ++ {"lvmdevices", NULL, NULL, NULL}, ++}; ++ + #define DBUS_DEPS_LVMDBUSD 0 + #define DBUS_DEPS_LVMDBUSD_MASK (1 << DBUS_DEPS_LVMDBUSD) + #define DBUS_DEPS_LAST 1 +@@ -378,6 +389,8 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) { + return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error) && + check_features (&avail_features, FEATURES_VDO_MASK, features, FEATURES_LAST, &deps_check_lock, error) && + check_module_deps (&avail_module_deps, MODULE_DEPS_VDO_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error); ++ case BD_LVM_TECH_DEVICES: ++ return check_deps (&avail_deps, DEPS_LVMDEVICES_MASK, deps, DEPS_LAST, &deps_check_lock, error); + default: + /* everything is supported by this implementation of the plugin */ + return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error); +@@ -515,6 +528,7 @@ static gboolean unbox_params_and_add (GVariant *params, GVariantBuilder *builder + + static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, guint64 *task_id, guint64 *progress_id, gboolean lock_config, GError **error) { + GVariant *config = NULL; ++ GVariant *devices = NULL; + GVariant *param = NULL; + GVariantIter iter; + GVariantBuilder builder; +@@ -536,8 +550,8 @@ static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gch + if (lock_config) + g_mutex_lock (&global_config_lock); + +- if (global_config_str || extra_params || extra_args) { +- if (global_config_str || extra_args) { ++ if (global_config_str || global_devices_str || extra_params || extra_args) { ++ if (global_config_str || global_devices_str || extra_args) { + /* add the global config to the extra_params */ + g_variant_builder_init (&extra_builder, G_VARIANT_TYPE_DICTIONARY); + +@@ -558,6 +572,11 @@ static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gch + g_variant_builder_add (&extra_builder, "{sv}", "--config", config); + added_extra = TRUE; + } ++ if (global_devices_str) { ++ devices = g_variant_new ("s", global_devices_str); ++ g_variant_builder_add (&extra_builder, "{sv}", "--devices", devices); ++ added_extra = TRUE; ++ } + + if (added_extra) + config_extra_params = g_variant_builder_end (&extra_builder); +@@ -2654,6 +2673,58 @@ gchar* bd_lvm_get_global_config (GError **error UNUSED) { + return ret; + } + ++/** ++ * bd_lvm_set_devices_filter: ++ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the devices filter was successfully set or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) { ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ g_mutex_lock (&global_config_lock); ++ ++ /* first free the old value */ ++ g_free (global_devices_str); ++ ++ /* now store the new one */ ++ if (!devices || !(*devices)) ++ global_devices_str = NULL; ++ else ++ global_devices_str = g_strjoinv (",", (gchar **) devices); ++ ++ g_mutex_unlock (&global_config_lock); ++ return TRUE; ++} ++ ++/** ++ * bd_lvm_get_devices_filter: ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of ++ * the currently set LVM devices filter ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gchar** bd_lvm_get_devices_filter (GError **error UNUSED) { ++ gchar **ret = NULL; ++ ++ g_mutex_lock (&global_config_lock); ++ ++ if (global_devices_str) ++ ret = g_strsplit (global_devices_str, ",", -1); ++ else ++ ret = NULL; ++ ++ g_mutex_unlock (&global_config_lock); ++ ++ return ret; ++} ++ + /** + * bd_lvm_cache_get_default_md_size: + * @cache_size: size of the cache to determine MD size for +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 26af0d19..42ee0f90 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -34,6 +34,8 @@ + static GMutex global_config_lock; + static gchar *global_config_str = NULL; + ++static gchar *global_devices_str = NULL; ++ + /** + * SECTION: lvm + * @short_description: plugin for operations with LVM +@@ -212,10 +214,13 @@ static GMutex deps_check_lock; + + #define DEPS_LVM 0 + #define DEPS_LVM_MASK (1 << DEPS_LVM) +-#define DEPS_LAST 1 ++#define DEPS_LVMDEVICES 1 ++#define DEPS_LVMDEVICES_MASK (1 << DEPS_LVMDEVICES) ++#define DEPS_LAST 2 + + static const UtilDep deps[DEPS_LAST] = { + {"lvm", LVM_MIN_VERSION, "version", "LVM version:\\s+([\\d\\.]+)"}, ++ {"lvmdevices", NULL, NULL, NULL}, + }; + + #define FEATURES_VDO 0 +@@ -327,6 +332,8 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) { + case BD_LVM_TECH_VDO: + return check_features (&avail_features, FEATURES_VDO_MASK, features, FEATURES_LAST, &deps_check_lock, error) && + check_module_deps (&avail_module_deps, MODULE_DEPS_VDO_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error); ++ case BD_LVM_TECH_DEVICES: ++ return check_deps (&avail_deps, DEPS_LVMDEVICES_MASK, deps, DEPS_LAST, &deps_check_lock, error); + default: + /* everything is supported by this implementation of the plugin */ + return check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error); +@@ -337,6 +344,8 @@ static gboolean call_lvm_and_report_error (const gchar **args, const BDExtraArg + gboolean success = FALSE; + guint i = 0; + guint args_length = g_strv_length ((gchar **) args); ++ g_autofree gchar *config_arg = NULL; ++ g_autofree gchar *devices_arg = NULL; + + if (!check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; +@@ -345,20 +354,26 @@ static gboolean call_lvm_and_report_error (const gchar **args, const BDExtraArg + if (lock_config) + g_mutex_lock (&global_config_lock); + +- /* allocate enough space for the args plus "lvm", "--config" and NULL */ +- const gchar **argv = g_new0 (const gchar*, args_length + 3); ++ /* allocate enough space for the args plus "lvm", "--config", "--devices" and NULL */ ++ const gchar **argv = g_new0 (const gchar*, args_length + 4); + + /* construct argv from args with "lvm" prepended */ + argv[0] = "lvm"; + for (i=0; i < args_length; i++) + argv[i+1] = args[i]; +- argv[args_length + 1] = global_config_str ? g_strdup_printf("--config=%s", global_config_str) : NULL; +- argv[args_length + 2] = NULL; ++ if (global_config_str) { ++ config_arg = g_strdup_printf("--config=%s", global_config_str); ++ argv[++args_length] = config_arg; ++ } ++ if (global_devices_str) { ++ devices_arg = g_strdup_printf("--devices=%s", global_devices_str); ++ argv[++args_length] = devices_arg; ++ } ++ argv[++args_length] = NULL; + + success = bd_utils_exec_and_report_error (argv, extra, error); + if (lock_config) + g_mutex_unlock (&global_config_lock); +- g_free ((gchar *) argv[args_length + 1]); + g_free (argv); + + return success; +@@ -368,6 +383,8 @@ static gboolean call_lvm_and_capture_output (const gchar **args, const BDExtraAr + gboolean success = FALSE; + guint i = 0; + guint args_length = g_strv_length ((gchar **) args); ++ g_autofree gchar *config_arg = NULL; ++ g_autofree gchar *devices_arg = NULL; + + if (!check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; +@@ -375,19 +392,25 @@ static gboolean call_lvm_and_capture_output (const gchar **args, const BDExtraAr + /* don't allow global config string changes during the run */ + g_mutex_lock (&global_config_lock); + +- /* allocate enough space for the args plus "lvm", "--config" and NULL */ +- const gchar **argv = g_new0 (const gchar*, args_length + 3); ++ /* allocate enough space for the args plus "lvm", "--config", "--devices" and NULL */ ++ const gchar **argv = g_new0 (const gchar*, args_length + 4); + + /* construct argv from args with "lvm" prepended */ + argv[0] = "lvm"; + for (i=0; i < args_length; i++) + argv[i+1] = args[i]; +- argv[args_length + 1] = global_config_str ? g_strdup_printf("--config=%s", global_config_str) : NULL; +- argv[args_length + 2] = NULL; ++ if (global_config_str) { ++ config_arg = g_strdup_printf("--config=%s", global_config_str); ++ argv[++args_length] = config_arg; ++ } ++ if (global_devices_str) { ++ devices_arg = g_strdup_printf("--devices=%s", global_devices_str); ++ argv[++args_length] = devices_arg; ++ } ++ argv[++args_length] = NULL; + + success = bd_utils_exec_and_capture_output (argv, extra, output, error); + g_mutex_unlock (&global_config_lock); +- g_free ((gchar *) argv[args_length + 1]); + g_free (argv); + + return success; +@@ -2033,6 +2056,58 @@ gchar* bd_lvm_get_global_config (GError **error UNUSED) { + return ret; + } + ++/** ++ * bd_lvm_set_devices_filter: ++ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the devices filter was successfully set or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) { ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ g_mutex_lock (&global_config_lock); ++ ++ /* first free the old value */ ++ g_free (global_devices_str); ++ ++ /* now store the new one */ ++ if (!devices || !(*devices)) ++ global_devices_str = NULL; ++ else ++ global_devices_str = g_strjoinv (",", (gchar **) devices); ++ ++ g_mutex_unlock (&global_config_lock); ++ return TRUE; ++} ++ ++/** ++ * bd_lvm_get_devices_filter: ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of ++ * the currently set LVM devices filter ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gchar** bd_lvm_get_devices_filter (GError **error UNUSED) { ++ gchar **ret = NULL; ++ ++ g_mutex_lock (&global_config_lock); ++ ++ if (global_devices_str) ++ ret = g_strsplit (global_devices_str, ",", -1); ++ else ++ ret = NULL; ++ ++ g_mutex_unlock (&global_config_lock); ++ ++ return ret; ++} ++ + /** + * bd_lvm_cache_get_default_md_size: + * @cache_size: size of the cache to determine MD size for +diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h +index 2162d769..8063693f 100644 +--- a/src/plugins/lvm.h ++++ b/src/plugins/lvm.h +@@ -216,6 +216,7 @@ typedef enum { + BD_LVM_TECH_CACHE_CALCS, + BD_LVM_TECH_GLOB_CONF, + BD_LVM_TECH_VDO, ++ BD_LVM_TECH_DEVICES, + } BDLVMTech; + + typedef enum { +@@ -289,6 +290,9 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name + gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error); + gchar* bd_lvm_get_global_config (GError **error); + ++gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error); ++gchar** bd_lvm_get_devices_filter (GError **error); ++ + guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error); + const gchar* bd_lvm_cache_get_mode_str (BDLVMCacheMode mode, GError **error); + BDLVMCacheMode bd_lvm_cache_get_mode_from_str (const gchar *mode_str, GError **error); +diff --git a/tests/library_test.py b/tests/library_test.py +index 08e44fdc..efd17bd2 100644 +--- a/tests/library_test.py ++++ b/tests/library_test.py +@@ -13,18 +13,178 @@ class LibraryOpsTestCase(unittest.TestCase): + # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all + # the dependencies on CentOS/Debian and we don't need them for this test + requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "dm", +- "kbd", "loop", "lvm", ++ "kbd", "loop", + "mdraid", "part", "swap")) + ++ @classmethod ++ def setUpClass(cls): ++ if not BlockDev.is_initialized(): ++ BlockDev.init(cls.requested_plugins, None) ++ else: ++ BlockDev.reinit(cls.requested_plugins, True, None) ++ ++ @classmethod ++ def tearDownClass(cls): ++ BlockDev.switch_init_checks(True) ++ ++ def my_log_func(self, level, msg): ++ # not much to verify here ++ self.assertTrue(isinstance(level, int)) ++ self.assertTrue(isinstance(msg, str)) ++ ++ self.log += msg + "\n" ++ ++ @tag_test(TestTags.CORE) ++ def test_logging_setup(self): ++ """Verify that setting up logging works as expected""" ++ ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self.my_log_func)) ++ ++ succ = BlockDev.utils_exec_and_report_error(["true"]) ++ self.assertTrue(succ) ++ ++ # reinit with no logging function should change nothing about logging ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, None)) ++ ++ succ, out = BlockDev.utils_exec_and_capture_output(["echo", "hi"]) ++ self.assertTrue(succ) ++ self.assertEqual(out, "hi\n") ++ ++ match = re.search(r'Running \[(\d+)\] true', self.log) ++ self.assertIsNot(match, None) ++ task_id1 = match.group(1) ++ match = re.search(r'Running \[(\d+)\] echo hi', self.log) ++ self.assertIsNot(match, None) ++ task_id2 = match.group(1) ++ ++ self.assertIn("...done [%s] (exit code: 0)" % task_id1, self.log) ++ self.assertIn("stdout[%s]:" % task_id1, self.log) ++ self.assertIn("stderr[%s]:" % task_id1, self.log) ++ ++ self.assertIn("stdout[%s]: hi" % task_id2, self.log) ++ self.assertIn("stderr[%s]:" % task_id2, self.log) ++ self.assertIn("...done [%s] (exit code: 0)" % task_id2, self.log) ++ ++ @tag_test(TestTags.CORE) ++ def test_require_plugins(self): ++ """Verify that loading only required plugins works as expected""" ++ ++ ps = BlockDev.PluginSpec() ++ ps.name = BlockDev.Plugin.SWAP ++ ps.so_name = "" ++ self.assertTrue(BlockDev.reinit([ps], True, None)) ++ self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ ++ @tag_test(TestTags.CORE) ++ def test_not_implemented(self): ++ """Verify that unloaded/unimplemented functions report errors""" ++ ++ # should be loaded and working ++ self.assertTrue(BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236")) ++ ++ ps = BlockDev.PluginSpec() ++ ps.name = BlockDev.Plugin.SWAP ++ ps.so_name = "" ++ self.assertTrue(BlockDev.reinit([ps], True, None)) ++ self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) ++ ++ # no longer loaded ++ with self.assertRaises(GLib.GError): ++ BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") ++ ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ ++ # loaded again ++ self.assertTrue(BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236")) ++ ++ def test_ensure_init(self): ++ """Verify that ensure_init just returns when already initialized""" ++ ++ # the library is already initialized, ensure_init() shonuld do nothing ++ avail_plugs = BlockDev.get_available_plugin_names() ++ self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) ++ self.assertEqual(avail_plugs, BlockDev.get_available_plugin_names()) ++ ++ # reinit with a subset of plugins ++ plugins = BlockDev.plugin_specs_from_names(["swap", "part"]) ++ self.assertTrue(BlockDev.reinit(plugins, True, None)) ++ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part"])) ++ ++ # ensure_init with the same subset -> nothing should change ++ self.assertTrue(BlockDev.ensure_init(plugins, None)) ++ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part"])) ++ ++ # ensure_init with more plugins -> extra plugins should be loaded ++ plugins = BlockDev.plugin_specs_from_names(["swap", "part", "crypto"]) ++ self.assertTrue(BlockDev.ensure_init(plugins, None)) ++ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part", "crypto"])) ++ ++ # reinit to unload all plugins ++ self.assertTrue(BlockDev.reinit([], True, None)) ++ self.assertEqual(BlockDev.get_available_plugin_names(), []) ++ ++ # ensure_init to load all plugins back ++ self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) ++ self.assertGreaterEqual(len(BlockDev.get_available_plugin_names()), 7) ++ ++ def test_try_reinit(self): ++ """Verify that try_reinit() works as expected""" ++ ++ # try reinitializing with only some utilities being available and thus ++ # only some plugins able to load ++ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "swaplabel"]): ++ succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None) ++ self.assertFalse(succ) ++ for plug_name in ("swap", "crypto"): ++ self.assertIn(plug_name, loaded) ++ ++ # reset back to all plugins ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ ++ # now the same with a subset of plugins requested ++ plugins = BlockDev.plugin_specs_from_names(["swap", "crypto"]) ++ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "swaplabel"]): ++ succ, loaded = BlockDev.try_reinit(plugins, True, None) ++ self.assertTrue(succ) ++ self.assertEqual(set(loaded), set(["swap", "crypto"])) ++ ++ def test_non_en_init(self): ++ """Verify that the library initializes with lang different from en_US""" ++ ++ orig_lang = os.environ.get("LANG") ++ os.environ["LANG"] = "cs.CZ_UTF-8" ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ if orig_lang: ++ os.environ["LANG"] = orig_lang ++ else: ++ del os.environ["LANG"] ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ ++ ++class PluginsTestCase(unittest.TestCase): ++ # only LVM plugin for this test ++ requested_plugins = BlockDev.plugin_specs_from_names(("lvm",)) ++ + orig_config_dir = "" + + @classmethod + def setUpClass(cls): ++ BlockDev.switch_init_checks(False) + if not BlockDev.is_initialized(): + BlockDev.init(cls.requested_plugins, None) + else: + BlockDev.reinit(cls.requested_plugins, True, None) + ++ try: ++ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) ++ except: ++ cls.devices_avail = False ++ ++ @classmethod ++ def tearDownClass(cls): ++ BlockDev.switch_init_checks(True) ++ + def setUp(self): + self.orig_config_dir = os.environ.get("LIBBLOCKDEV_CONFIG_DIR", "") + self.addCleanup(self._clean_up) +@@ -185,6 +345,12 @@ class LibraryOpsTestCase(unittest.TestCase): + def test_plugin_fallback(self): + """Verify that fallback when loading plugins works as expected""" + ++ if not self.devices_avail: ++ self.skipTest("skipping plugin fallback test: missing some LVM dependencies") ++ ++ BlockDev.switch_init_checks(True) ++ self.addCleanup(BlockDev.switch_init_checks, False) ++ + # library should be successfully initialized + self.assertTrue(BlockDev.is_initialized()) + +@@ -206,7 +372,7 @@ class LibraryOpsTestCase(unittest.TestCase): + + # now reinit the library with the config preferring the new build + orig_conf_dir = os.environ.get("LIBBLOCKDEV_CONFIG_DIR") +- os.environ["LIBBLOCKDEV_CONFIG_DIR"] = "tests/plugin_prio_conf.d" ++ os.environ["LIBBLOCKDEV_CONFIG_DIR"] = "tests/test_configs/plugin_prio_conf.d" + self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) + + # the original plugin should be loaded because the new one should fail +@@ -243,139 +409,9 @@ class LibraryOpsTestCase(unittest.TestCase): + + self.assertEqual(BlockDev.lvm_get_max_lv_size(), orig_max_size) + +- def my_log_func(self, level, msg): +- # not much to verify here +- self.assertTrue(isinstance(level, int)) +- self.assertTrue(isinstance(msg, str)) +- +- self.log += msg + "\n" +- +- @tag_test(TestTags.CORE) +- def test_logging_setup(self): +- """Verify that setting up logging works as expected""" +- +- self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self.my_log_func)) +- +- succ = BlockDev.utils_exec_and_report_error(["true"]) +- self.assertTrue(succ) +- +- # reinit with no logging function should change nothing about logging +- self.assertTrue(BlockDev.reinit(self.requested_plugins, False, None)) +- +- succ, out = BlockDev.utils_exec_and_capture_output(["echo", "hi"]) +- self.assertTrue(succ) +- self.assertEqual(out, "hi\n") +- +- match = re.search(r'Running \[(\d+)\] true', self.log) +- self.assertIsNot(match, None) +- task_id1 = match.group(1) +- match = re.search(r'Running \[(\d+)\] echo hi', self.log) +- self.assertIsNot(match, None) +- task_id2 = match.group(1) +- +- self.assertIn("...done [%s] (exit code: 0)" % task_id1, self.log) +- self.assertIn("stdout[%s]:" % task_id1, self.log) +- self.assertIn("stderr[%s]:" % task_id1, self.log) +- +- self.assertIn("stdout[%s]: hi" % task_id2, self.log) +- self.assertIn("stderr[%s]:" % task_id2, self.log) +- self.assertIn("...done [%s] (exit code: 0)" % task_id2, self.log) +- +- @tag_test(TestTags.CORE) +- def test_require_plugins(self): +- """Verify that loading only required plugins works as expected""" +- +- ps = BlockDev.PluginSpec() +- ps.name = BlockDev.Plugin.SWAP +- ps.so_name = "" +- self.assertTrue(BlockDev.reinit([ps], True, None)) +- self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +- +- @tag_test(TestTags.CORE) +- def test_not_implemented(self): +- """Verify that unloaded/unimplemented functions report errors""" +- +- # should be loaded and working +- self.assertTrue(BlockDev.lvm_get_max_lv_size() > 0) + +- ps = BlockDev.PluginSpec() +- ps.name = BlockDev.Plugin.SWAP +- ps.so_name = "" +- self.assertTrue(BlockDev.reinit([ps], True, None)) +- self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) +- +- # no longer loaded +- with self.assertRaises(GLib.GError): +- BlockDev.lvm_get_max_lv_size() +- +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +- +- # loaded again +- self.assertTrue(BlockDev.lvm_get_max_lv_size() > 0) +- +- def test_ensure_init(self): +- """Verify that ensure_init just returns when already initialized""" +- +- # the library is already initialized, ensure_init() shonuld do nothing +- avail_plugs = BlockDev.get_available_plugin_names() +- self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) +- self.assertEqual(avail_plugs, BlockDev.get_available_plugin_names()) +- +- # reinit with a subset of plugins +- plugins = BlockDev.plugin_specs_from_names(["swap", "lvm"]) +- self.assertTrue(BlockDev.reinit(plugins, True, None)) +- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm"])) +- +- # ensure_init with the same subset -> nothing should change +- self.assertTrue(BlockDev.ensure_init(plugins, None)) +- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm"])) +- +- # ensure_init with more plugins -> extra plugins should be loaded +- plugins = BlockDev.plugin_specs_from_names(["swap", "lvm", "crypto"]) +- self.assertTrue(BlockDev.ensure_init(plugins, None)) +- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm", "crypto"])) +- +- # reinit to unload all plugins +- self.assertTrue(BlockDev.reinit([], True, None)) +- self.assertEqual(BlockDev.get_available_plugin_names(), []) +- +- # ensure_init to load all plugins back +- self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) +- self.assertGreaterEqual(len(BlockDev.get_available_plugin_names()), 8) +- +- def test_try_reinit(self): +- """Verify that try_reinit() works as expected""" +- +- # try reinitializing with only some utilities being available and thus +- # only some plugins able to load +- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", "swaplabel"]): +- succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None) +- self.assertFalse(succ) +- for plug_name in ("swap", "lvm", "crypto"): +- self.assertIn(plug_name, loaded) +- +- # reset back to all plugins +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +- +- # now the same with a subset of plugins requested +- plugins = BlockDev.plugin_specs_from_names(["lvm", "swap", "crypto"]) +- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm","swaplabel"]): +- succ, loaded = BlockDev.try_reinit(plugins, True, None) +- self.assertTrue(succ) +- self.assertEqual(set(loaded), set(["swap", "lvm", "crypto"])) +- +- def test_non_en_init(self): +- """Verify that the library initializes with lang different from en_US""" +- +- orig_lang = os.environ.get("LANG") +- os.environ["LANG"] = "cs.CZ_UTF-8" +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +- if orig_lang: +- os.environ["LANG"] = orig_lang +- else: +- del os.environ["LANG"] +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++class DepChecksTestCase(unittest.TestCase): ++ requested_plugins = BlockDev.plugin_specs_from_names(( "swap",)) + + def test_dep_checks_disabled(self): + """Verify that disabling runtime dep checks works""" +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 3fb7946a..ae26c6d2 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -50,6 +50,11 @@ class LVMTestCase(unittest.TestCase): + else: + BlockDev.reinit([cls.ps, cls.ps2], True, None) + ++ try: ++ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) ++ except: ++ cls.devices_avail = False ++ + @classmethod + def _get_lvm_version(cls): + _ret, out, _err = run_command("lvm version") +@@ -61,8 +66,7 @@ class LVMTestCase(unittest.TestCase): + @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") + class LvmNoDevTestCase(LVMTestCase): + +- def __init__(self, *args, **kwargs): +- super(LvmNoDevTestCase, self).__init__(*args, **kwargs) ++ def setUp(self): + self._log = "" + + @tag_test(TestTags.NOSTORAGE) +@@ -250,6 +254,45 @@ class LvmNoDevTestCase(LVMTestCase): + succ = BlockDev.lvm_set_global_config(None) + self.assertTrue(succ) + ++ @tag_test(TestTags.NOSTORAGE) ++ def test_get_set_global_devices_filter(self): ++ """Verify that getting and setting LVM devices filter works as expected""" ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices filter test: not supported") ++ ++ # setup logging ++ self.assertTrue(BlockDev.reinit([self.ps], False, self._store_log)) ++ ++ # no global config set initially ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) ++ ++ # set and try to get back ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) ++ self.assertTrue(succ) ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sda"]) ++ ++ # reset and try to get back ++ succ = BlockDev.lvm_set_devices_filter(None) ++ self.assertTrue(succ) ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) ++ ++ # set twice and try to get back twice ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) ++ self.assertTrue(succ) ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb"]) ++ self.assertTrue(succ) ++ self.assertEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sdb"]) ++ ++ # set something sane and check it's really used ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb", "/dev/sdc"]) ++ BlockDev.lvm_pvscan() ++ self.assertIn("'--devices'", self._log) ++ self.assertIn("'/dev/sdb,/dev/sdc'", self._log) ++ ++ # reset back to default ++ succ = BlockDev.lvm_set_devices_filter(None) ++ self.assertTrue(succ) ++ + @tag_test(TestTags.NOSTORAGE) + def test_cache_get_default_md_size(self): + """Verify that default cache metadata size is calculated properly""" +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 7be8f1ab..11d8c94e 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -39,10 +39,17 @@ class LVMTestCase(unittest.TestCase): + ps.so_name = "libbd_lvm.so.2" + cls.requested_plugins = [ps] + ++ BlockDev.switch_init_checks(False) + if not BlockDev.is_initialized(): + BlockDev.init(cls.requested_plugins, None) + else: + BlockDev.reinit(cls.requested_plugins, True, None) ++ BlockDev.switch_init_checks(True) ++ ++ try: ++ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) ++ except: ++ cls.devices_avail = False + + @classmethod + def _get_lvm_version(cls): +@@ -56,6 +63,8 @@ class LVMTestCase(unittest.TestCase): + class LvmNoDevTestCase(LVMTestCase): + def __init__(self, *args, **kwargs): + super(LvmNoDevTestCase, self).__init__(*args, **kwargs) ++ ++ def setUp(self): + self._log = "" + + @tag_test(TestTags.NOSTORAGE) +@@ -236,6 +245,44 @@ class LvmNoDevTestCase(LVMTestCase): + succ = BlockDev.lvm_set_global_config(None) + self.assertTrue(succ) + ++ @tag_test(TestTags.NOSTORAGE) ++ def test_get_set_global_devices_filter(self): ++ """Verify that getting and setting LVM devices filter works as expected""" ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices filter test: not supported") ++ ++ # setup logging ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self._store_log)) ++ ++ # no global config set initially ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) ++ ++ # set and try to get back ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) ++ self.assertTrue(succ) ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sda"]) ++ ++ # reset and try to get back ++ succ = BlockDev.lvm_set_devices_filter(None) ++ self.assertTrue(succ) ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) ++ ++ # set twice and try to get back twice ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) ++ self.assertTrue(succ) ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb"]) ++ self.assertTrue(succ) ++ self.assertEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sdb"]) ++ ++ # set something sane and check it's really used ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb", "/dev/sdc"]) ++ BlockDev.lvm_lvs(None) ++ self.assertIn("--devices=/dev/sdb,/dev/sdc", self._log) ++ ++ # reset back to default ++ succ = BlockDev.lvm_set_devices_filter(None) ++ self.assertTrue(succ) ++ + @tag_test(TestTags.NOSTORAGE) + def test_cache_get_default_md_size(self): + """Verify that default cache metadata size is calculated properly""" +@@ -1406,6 +1453,9 @@ class LvmPVVGcachedThpoolstatsTestCase(LvmPVVGLVTestCase): + + class LVMUnloadTest(LVMTestCase): + def setUp(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM unload test: missing some LVM dependencies") ++ + # make sure the library is initialized with all plugins loaded for other + # tests + self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None) +diff --git a/tests/overrides_test.py b/tests/overrides_test.py +index 8e7f5a5a..d3faf3cf 100644 +--- a/tests/overrides_test.py ++++ b/tests/overrides_test.py +@@ -15,10 +15,12 @@ class OverridesTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): ++ BlockDev.switch_init_checks(False) + if not BlockDev.is_initialized(): + BlockDev.init(cls.requested_plugins, None) + else: + BlockDev.reinit(cls.requested_plugins, True, None) ++ BlockDev.switch_init_checks(True) + + class OverridesTestCase(OverridesTest): + @tag_test(TestTags.NOSTORAGE, TestTags.CORE) +@@ -65,7 +67,20 @@ class OverridesTestCase(OverridesTest): + self.assertEqual(BlockDev.lvm_get_thpool_padding(11 * 1024**2), + expected_padding) + +-class OverridesUnloadTestCase(OverridesTest): ++class OverridesUnloadTestCase(unittest.TestCase): ++ # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all ++ # the dependencies on CentOS/Debian and we don't need them for this test ++ requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "dm", ++ "kbd", "loop", ++ "mdraid", "part", "swap")) ++ ++ @classmethod ++ def setUpClass(cls): ++ if not BlockDev.is_initialized(): ++ BlockDev.init(cls.requested_plugins, None) ++ else: ++ BlockDev.reinit(cls.requested_plugins, True, None) ++ + def tearDown(self): + # make sure the library is initialized with all plugins loaded for other + # tests +@@ -80,7 +95,7 @@ class OverridesUnloadTestCase(OverridesTest): + + # no longer loaded + with self.assertRaises(BlockDev.BlockDevNotImplementedError): +- BlockDev.lvm.get_max_lv_size() ++ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") + + # load the plugins back + self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +@@ -92,9 +107,9 @@ class OverridesUnloadTestCase(OverridesTest): + + # the exception should be properly inherited from two classes + with self.assertRaises(NotImplementedError): +- BlockDev.lvm.get_max_lv_size() ++ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") + with self.assertRaises(BlockDev.BlockDevError): +- BlockDev.lvm.get_max_lv_size() ++ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") + + # load the plugins back + self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +-- +2.37.3 + + +From 707de091b8848b95cc78faa4299119844aab4172 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 13 Jul 2021 13:27:32 +0200 +Subject: [PATCH 2/7] lvm: Add functions for managing LVM devices file + +Currently covers only --adddev and --deldev from the lvmdevices +command. +--- + src/lib/plugin_apis/lvm.api | 26 +++++++++++++++ + src/plugins/lvm-dbus.c | 52 +++++++++++++++++++++++++++++ + src/plugins/lvm.c | 52 +++++++++++++++++++++++++++++ + src/plugins/lvm.h | 3 ++ + src/python/gi/overrides/BlockDev.py | 15 +++++++++ + tests/lvm_dbus_tests.py | 37 +++++++++++++++++++- + tests/lvm_test.py | 37 +++++++++++++++++++- + 7 files changed, 220 insertions(+), 2 deletions(-) + +diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api +index 23f68b81..b869afcc 100644 +--- a/src/lib/plugin_apis/lvm.api ++++ b/src/lib/plugin_apis/lvm.api +@@ -1685,4 +1685,30 @@ GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_n + */ + BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error); + ++/** ++ * bd_lvm_devices_add: ++ * @device: device (PV) to add to the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully added to @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); ++ ++/** ++ * bd_lvm_devices_delete: ++ * @device: device (PV) to delete from the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully removed from @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); ++ + #endif /* BD_LVM_API */ +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index b47ed0ef..86ca28ca 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -3950,3 +3950,55 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam + + return stats; + } ++ ++/** ++ * bd_lvm_devices_add: ++ * @device: device (PV) to add to the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully added to @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { ++ const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL}; ++ g_autofree gchar *devfile = NULL; ++ ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ if (devices_file) { ++ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); ++ args[3] = devfile; ++ } ++ ++ return bd_utils_exec_and_report_error (args, extra, error); ++} ++ ++/** ++ * bd_lvm_devices_delete: ++ * @device: device (PV) to delete from the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully removed from @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { ++ const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL}; ++ g_autofree gchar *devfile = NULL; ++ ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ if (devices_file) { ++ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); ++ args[3] = devfile; ++ } ++ ++ return bd_utils_exec_and_report_error (args, extra, error); ++} +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 42ee0f90..3bd8fae1 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -3250,3 +3250,55 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam + + return stats; + } ++ ++/** ++ * bd_lvm_devices_add: ++ * @device: device (PV) to add to the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully added to @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { ++ const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL}; ++ g_autofree gchar *devfile = NULL; ++ ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ if (devices_file) { ++ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); ++ args[3] = devfile; ++ } ++ ++ return bd_utils_exec_and_report_error (args, extra, error); ++} ++ ++/** ++ * bd_lvm_devices_delete: ++ * @device: device (PV) to delete from the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully removed from @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { ++ const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL}; ++ g_autofree gchar *devfile = NULL; ++ ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ if (devices_file) { ++ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); ++ args[3] = devfile; ++ } ++ ++ return bd_utils_exec_and_report_error (args, extra, error); ++} +diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h +index 8063693f..5ca2a9d7 100644 +--- a/src/plugins/lvm.h ++++ b/src/plugins/lvm.h +@@ -333,4 +333,7 @@ BDLVMVDOWritePolicy bd_lvm_get_vdo_write_policy_from_str (const gchar *policy_st + BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error); + GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_name, GError **error); + ++gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); ++gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); ++ + #endif /* BD_LVM */ +diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py +index ea059060..8574ab04 100644 +--- a/src/python/gi/overrides/BlockDev.py ++++ b/src/python/gi/overrides/BlockDev.py +@@ -724,6 +724,21 @@ def lvm_vdo_pool_convert(vg_name, lv_name, pool_name, virtual_size, index_memory + return _lvm_vdo_pool_convert(vg_name, lv_name, pool_name, virtual_size, index_memory, compression, deduplication, write_policy, extra) + __all__.append("lvm_vdo_pool_convert") + ++_lvm_devices_add = BlockDev.lvm_devices_add ++@override(BlockDev.lvm_devices_add) ++def lvm_devices_add(device, devices_file=None, extra=None, **kwargs): ++ extra = _get_extra(extra, kwargs) ++ return _lvm_devices_add(device, devices_file, extra) ++__all__.append("lvm_devices_add") ++ ++_lvm_devices_delete = BlockDev.lvm_devices_delete ++@override(BlockDev.lvm_devices_delete) ++def lvm_devices_delete(device, devices_file=None, extra=None, **kwargs): ++ extra = _get_extra(extra, kwargs) ++ return _lvm_devices_delete(device, devices_file, extra) ++__all__.append("lvm_devices_delete") ++ ++ + _md_get_superblock_size = BlockDev.md_get_superblock_size + @override(BlockDev.md_get_superblock_size) + def md_get_superblock_size(size, version=None): +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index ae26c6d2..82e4761d 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -12,7 +12,7 @@ from contextlib import contextmanager + from distutils.version import LooseVersion + from itertools import chain + +-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test ++from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test, read_file + from gi.repository import BlockDev, GLib + + import dbus +@@ -1785,3 +1785,38 @@ class LvmConfigTestPvremove(LvmPVonlyTestCase): + BlockDev.lvm_set_global_config("") + succ = BlockDev.lvm_pvremove(self.loop_dev) + self.assertTrue(succ) ++ ++ ++class LvmTestDevicesFile(LvmPVonlyTestCase): ++ devicefile = "bd_lvm_dbus_tests.devices" ++ ++ @classmethod ++ def tearDownClass(cls): ++ shutil.rmtree("/etc/lvm/devices/" + cls.devicefile, ignore_errors=True) ++ ++ super(LvmTestDevicesFile, cls).tearDownClass() ++ ++ def test_devices_add_delete(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices file test: not supported") ++ ++ succ = BlockDev.lvm_pvcreate(self.loop_dev) ++ self.assertTrue(succ) ++ ++ with self.assertRaises(GLib.GError): ++ BlockDev.lvm_devices_add("/non/existing/device", self.devicefile) ++ ++ with self.assertRaises(GLib.GError): ++ BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) ++ ++ succ = BlockDev.lvm_devices_add(self.loop_dev, self.devicefile) ++ self.assertTrue(succ) ++ ++ dfile = read_file("/etc/lvm/devices/" + self.devicefile) ++ self.assertIn(self.loop_dev, dfile) ++ ++ succ = BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) ++ self.assertTrue(succ) ++ ++ dfile = read_file("/etc/lvm/devices/" + self.devicefile) ++ self.assertNotIn(self.loop_dev, dfile) +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 11d8c94e..6ddeaa6a 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -11,7 +11,7 @@ import time + from contextlib import contextmanager + from distutils.version import LooseVersion + +-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command ++from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command, read_file + from gi.repository import BlockDev, GLib + + +@@ -1765,3 +1765,38 @@ class LvmConfigTestPvremove(LvmPVonlyTestCase): + BlockDev.lvm_set_global_config("") + succ = BlockDev.lvm_pvremove(self.loop_dev) + self.assertTrue(succ) ++ ++ ++class LvmTestDevicesFile(LvmPVonlyTestCase): ++ devicefile = "bd_lvm_test.devices" ++ ++ @classmethod ++ def tearDownClass(cls): ++ shutil.rmtree("/etc/lvm/devices/" + cls.devicefile, ignore_errors=True) ++ ++ super(LvmTestDevicesFile, cls).tearDownClass() ++ ++ def test_devices_add_delete(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices file test: not supported") ++ ++ succ = BlockDev.lvm_pvcreate(self.loop_dev) ++ self.assertTrue(succ) ++ ++ with self.assertRaises(GLib.GError): ++ BlockDev.lvm_devices_add("/non/existing/device", self.devicefile) ++ ++ with self.assertRaises(GLib.GError): ++ BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) ++ ++ succ = BlockDev.lvm_devices_add(self.loop_dev, self.devicefile) ++ self.assertTrue(succ) ++ ++ dfile = read_file("/etc/lvm/devices/" + self.devicefile) ++ self.assertIn(self.loop_dev, dfile) ++ ++ succ = BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) ++ self.assertTrue(succ) ++ ++ dfile = read_file("/etc/lvm/devices/" + self.devicefile) ++ self.assertNotIn(self.loop_dev, dfile) +-- +2.37.3 + + +From 4c832576df8918c269db8fe2cb7eb74e45628d6c Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 15 Oct 2021 13:18:54 +0200 +Subject: [PATCH 3/7] lvm: Report special error when system.devices file is not + enabled + +This can be disabled either in LVM by a compile time option or +by a lvm.conf option so we should report a specific error for this +case so users can distinguish between the feature not being enabled +and not being supported at all. +--- + src/lib/plugin_apis/lvm.api | 1 + + src/plugins/lvm-dbus.c | 70 +++++++++++++++++++++++++++++++++++++ + src/plugins/lvm.c | 60 +++++++++++++++++++++++++++++++ + src/plugins/lvm.h | 1 + + tests/lvm_dbus_tests.py | 15 ++++++++ + tests/lvm_test.py | 15 ++++++++ + 6 files changed, 162 insertions(+) + +diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api +index b869afcc..b8cde70b 100644 +--- a/src/lib/plugin_apis/lvm.api ++++ b/src/lib/plugin_apis/lvm.api +@@ -44,6 +44,7 @@ typedef enum { + BD_LVM_ERROR_FAIL, + BD_LVM_ERROR_NOT_SUPPORTED, + BD_LVM_ERROR_VDO_POLICY_INVAL, ++ BD_LVM_ERROR_DEVICES_DISABLED, + } BDLVMError; + + typedef enum { +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index 86ca28ca..7f48e422 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -3951,6 +3951,64 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam + return stats; + } + ++/* check whether the LVM devices file is enabled by LVM ++ * we use the existence of the "lvmdevices" command to check whether the feature is available ++ * or not, but this can still be disabled either in LVM or in lvm.conf ++ */ ++static gboolean _lvm_devices_enabled () { ++ const gchar *args[6] = {"lvmconfig", "--typeconfig", NULL, "devices/use_devicesfile", NULL, NULL}; ++ gboolean ret = FALSE; ++ GError *loc_error = NULL; ++ gchar *output = NULL; ++ gboolean enabled = FALSE; ++ gint scanned = 0; ++ g_autofree gchar *config_arg = NULL; ++ ++ /* try current config first -- if we get something from this it means the feature is ++ explicitly enabled or disabled by system lvm.conf or using the --config option */ ++ args[2] = "current"; ++ ++ /* make sure to include the global config from us when getting the current config value */ ++ g_mutex_lock (&global_config_lock); ++ if (global_config_str) { ++ config_arg = g_strdup_printf ("--config=%s", global_config_str); ++ args[4] = config_arg; ++ } ++ ++ ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error); ++ g_mutex_unlock (&global_config_lock); ++ if (ret) { ++ scanned = sscanf (output, "use_devicesfile=%u", &enabled); ++ g_free (output); ++ if (scanned != 1) ++ return FALSE; ++ ++ return enabled; ++ } else { ++ g_clear_error (&loc_error); ++ g_free (output); ++ } ++ ++ output = NULL; ++ ++ /* now try default */ ++ args[2] = "default"; ++ ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error); ++ if (ret) { ++ scanned = sscanf (output, "# use_devicesfile=%u", &enabled); ++ g_free (output); ++ if (scanned != 1) ++ return FALSE; ++ ++ return enabled; ++ } else { ++ g_clear_error (&loc_error); ++ g_free (output); ++ } ++ ++ return FALSE; ++} ++ + /** + * bd_lvm_devices_add: + * @device: device (PV) to add to the devices file +@@ -3969,6 +4027,12 @@ gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, con + if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) + return FALSE; + ++ if (!_lvm_devices_enabled ()) { ++ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, ++ "LVM devices file not enabled."); ++ return FALSE; ++ } ++ + if (devices_file) { + devfile = g_strdup_printf ("--devicesfile=%s", devices_file); + args[3] = devfile; +@@ -3995,6 +4059,12 @@ gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, + if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) + return FALSE; + ++ if (!_lvm_devices_enabled ()) { ++ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, ++ "LVM devices file not enabled."); ++ return FALSE; ++ } ++ + if (devices_file) { + devfile = g_strdup_printf ("--devicesfile=%s", devices_file); + args[3] = devfile; +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 3bd8fae1..73d5005f 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -3251,6 +3251,54 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam + return stats; + } + ++/* check whether the LVM devices file is enabled by LVM ++ * we use the existence of the "lvmdevices" command to check whether the feature is available ++ * or not, but this can still be disabled either in LVM or in lvm.conf ++ */ ++static gboolean _lvm_devices_enabled () { ++ const gchar *args[5] = {"config", "--typeconfig", NULL, "devices/use_devicesfile", NULL}; ++ gboolean ret = FALSE; ++ GError *loc_error = NULL; ++ gchar *output = NULL; ++ gboolean enabled = FALSE; ++ gint scanned = 0; ++ ++ /* try current config first -- if we get something from this it means the feature is ++ explicitly enabled or disabled by system lvm.conf or using the --config option */ ++ args[2] = "current"; ++ ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); ++ if (ret) { ++ scanned = sscanf (output, "use_devicesfile=%u", &enabled); ++ g_free (output); ++ if (scanned != 1) ++ return FALSE; ++ ++ return enabled; ++ } else { ++ g_clear_error (&loc_error); ++ g_free (output); ++ } ++ ++ output = NULL; ++ ++ /* now try default */ ++ args[2] = "default"; ++ ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); ++ if (ret) { ++ scanned = sscanf (output, "# use_devicesfile=%u", &enabled); ++ g_free (output); ++ if (scanned != 1) ++ return FALSE; ++ ++ return enabled; ++ } else { ++ g_clear_error (&loc_error); ++ g_free (output); ++ } ++ ++ return FALSE; ++} ++ + /** + * bd_lvm_devices_add: + * @device: device (PV) to add to the devices file +@@ -3269,6 +3317,12 @@ gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, con + if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) + return FALSE; + ++ if (!_lvm_devices_enabled ()) { ++ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, ++ "LVM devices file not enabled."); ++ return FALSE; ++ } ++ + if (devices_file) { + devfile = g_strdup_printf ("--devicesfile=%s", devices_file); + args[3] = devfile; +@@ -3295,6 +3349,12 @@ gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, + if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) + return FALSE; + ++ if (!_lvm_devices_enabled ()) { ++ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, ++ "LVM devices file not enabled."); ++ return FALSE; ++ } ++ + if (devices_file) { + devfile = g_strdup_printf ("--devicesfile=%s", devices_file); + args[3] = devfile; +diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h +index 5ca2a9d7..fabf091f 100644 +--- a/src/plugins/lvm.h ++++ b/src/plugins/lvm.h +@@ -53,6 +53,7 @@ typedef enum { + BD_LVM_ERROR_FAIL, + BD_LVM_ERROR_NOT_SUPPORTED, + BD_LVM_ERROR_VDO_POLICY_INVAL, ++ BD_LVM_ERROR_DEVICES_DISABLED, + } BDLVMError; + + typedef enum { +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 82e4761d..792c1cc8 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1820,3 +1820,18 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) ++ ++ def test_devices_enabled(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices file test: not supported") ++ ++ self.addCleanup(BlockDev.lvm_set_global_config, "") ++ ++ # checking if the feature is enabled or disabled is hard so lets just disable ++ # the devices file using the global config and check lvm_devices_add fails ++ # with the correct exception message ++ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=0 }") ++ self.assertTrue(succ) ++ ++ with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): ++ BlockDev.lvm_devices_add("", self.devicefile) +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 6ddeaa6a..73fb1030 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1800,3 +1800,18 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) ++ ++ def test_devices_enabled(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices file test: not supported") ++ ++ self.addCleanup(BlockDev.lvm_set_global_config, "") ++ ++ # checking if the feature is enabled or disabled is hard so lets just disable ++ # the devices file using the global config and check lvm_devices_add fails ++ # with the correct exception message ++ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=0 }") ++ self.assertTrue(succ) ++ ++ with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): ++ BlockDev.lvm_devices_add("", self.devicefile) +-- +2.37.3 + + +From 2fdec5f7e42de869d4b2ec80dce597d22dd57617 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 15 Oct 2021 14:21:03 +0200 +Subject: [PATCH 4/7] lvm: Force enable LVM devices file for LvmTestDevicesFile + +This feauture might be disabled in lvm.conf so to be able to test +it we need to override this. The correct handling of the disabled +state is checked in a separate test case. +--- + tests/lvm_dbus_tests.py | 8 ++++++++ + tests/lvm_test.py | 8 ++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 792c1cc8..e55535cc 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1800,6 +1800,12 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + ++ self.addCleanup(BlockDev.lvm_set_global_config, "") ++ ++ # force-enable the feature, it might be disabled by default ++ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") ++ self.assertTrue(succ) ++ + succ = BlockDev.lvm_pvcreate(self.loop_dev) + self.assertTrue(succ) + +@@ -1821,6 +1827,8 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) + ++ BlockDev.lvm_set_global_config("") ++ + def test_devices_enabled(self): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 73fb1030..907b4f59 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1780,6 +1780,12 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + ++ self.addCleanup(BlockDev.lvm_set_global_config, "") ++ ++ # force-enable the feature, it might be disabled by default ++ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") ++ self.assertTrue(succ) ++ + succ = BlockDev.lvm_pvcreate(self.loop_dev) + self.assertTrue(succ) + +@@ -1801,6 +1807,8 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) + ++ BlockDev.lvm_set_global_config("") ++ + def test_devices_enabled(self): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") +-- +2.37.3 + + +From 1809a41c0b2b99c8d6a077b5aa70834686980181 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 12 Nov 2021 14:51:39 +0100 +Subject: [PATCH 5/7] tests: Fix resetting global LVM config after LVM devices + file test + +We need to set the config to None/NULL not to an empty string. +--- + tests/lvm_dbus_tests.py | 6 +++--- + tests/lvm_test.py | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index e55535cc..8ae670d5 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1800,7 +1800,7 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + +- self.addCleanup(BlockDev.lvm_set_global_config, "") ++ self.addCleanup(BlockDev.lvm_set_global_config, None) + + # force-enable the feature, it might be disabled by default + succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") +@@ -1827,13 +1827,13 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) + +- BlockDev.lvm_set_global_config("") ++ BlockDev.lvm_set_global_config(None) + + def test_devices_enabled(self): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + +- self.addCleanup(BlockDev.lvm_set_global_config, "") ++ self.addCleanup(BlockDev.lvm_set_global_config, None) + + # checking if the feature is enabled or disabled is hard so lets just disable + # the devices file using the global config and check lvm_devices_add fails +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 907b4f59..095e4bac 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1780,7 +1780,7 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + +- self.addCleanup(BlockDev.lvm_set_global_config, "") ++ self.addCleanup(BlockDev.lvm_set_global_config, None) + + # force-enable the feature, it might be disabled by default + succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") +@@ -1807,13 +1807,13 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) + +- BlockDev.lvm_set_global_config("") ++ BlockDev.lvm_set_global_config(None) + + def test_devices_enabled(self): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + +- self.addCleanup(BlockDev.lvm_set_global_config, "") ++ self.addCleanup(BlockDev.lvm_set_global_config, None) + + # checking if the feature is enabled or disabled is hard so lets just disable + # the devices file using the global config and check lvm_devices_add fails +-- +2.37.3 + + +From 1c2f1d20a3cfa522b78ab007e8e4f9a5a4bb579d Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 12 Nov 2021 15:10:45 +0100 +Subject: [PATCH 6/7] lvm: Do not set global config to and empty string + +If we set it to an empty string we end up running "--config" +without a parameter and lvm will use whatever is next parameter +like the device path for pvremove. +--- + tests/lvm_dbus_tests.py | 12 ++++++++++++ + tests/lvm_test.py | 12 ++++++++++++ + 2 files changed, 24 insertions(+) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 8ae670d5..61c898c1 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1843,3 +1843,15 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + + with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): + BlockDev.lvm_devices_add("", self.devicefile) ++ ++ ++class LvmConfigTestPvremove(LvmPVonlyTestCase): ++ ++ @tag_test(TestTags.REGRESSION) ++ def test_set_empty_config(self): ++ succ = BlockDev.lvm_pvcreate(self.loop_dev) ++ self.assertTrue(succ) ++ ++ BlockDev.lvm_set_global_config("") ++ succ = BlockDev.lvm_pvremove(self.loop_dev) ++ self.assertTrue(succ) +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 095e4bac..36ff10ec 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1823,3 +1823,15 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + + with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): + BlockDev.lvm_devices_add("", self.devicefile) ++ ++ ++class LvmConfigTestPvremove(LvmPVonlyTestCase): ++ ++ @tag_test(TestTags.REGRESSION) ++ def test_set_empty_config(self): ++ succ = BlockDev.lvm_pvcreate(self.loop_dev) ++ self.assertTrue(succ) ++ ++ BlockDev.lvm_set_global_config("") ++ succ = BlockDev.lvm_pvremove(self.loop_dev) ++ self.assertTrue(succ) +-- +2.37.3 + + +From 05cfb84777c5472550673a1f2150ca357718b3f2 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 26 Nov 2021 15:19:55 +0100 +Subject: [PATCH 7/7] lvm: Use "lvmconfig full" to get valid config instead of + "current" + +"lvmconfig current" doesn't work together with --config even if we +don't override the "use_devicefile" key. "lvmconfig full" seems to +be working in all cases. +--- + src/plugins/lvm-dbus.c | 4 ++-- + src/plugins/lvm.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index 7f48e422..d4b542e2 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -3964,9 +3964,9 @@ static gboolean _lvm_devices_enabled () { + gint scanned = 0; + g_autofree gchar *config_arg = NULL; + +- /* try current config first -- if we get something from this it means the feature is ++ /* try full config first -- if we get something from this it means the feature is + explicitly enabled or disabled by system lvm.conf or using the --config option */ +- args[2] = "current"; ++ args[2] = "full"; + + /* make sure to include the global config from us when getting the current config value */ + g_mutex_lock (&global_config_lock); +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 73d5005f..03211f8a 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -3263,9 +3263,9 @@ static gboolean _lvm_devices_enabled () { + gboolean enabled = FALSE; + gint scanned = 0; + +- /* try current config first -- if we get something from this it means the feature is ++ /* try full config first -- if we get something from this it means the feature is + explicitly enabled or disabled by system lvm.conf or using the --config option */ +- args[2] = "current"; ++ args[2] = "full"; + ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); + if (ret) { + scanned = sscanf (output, "use_devicesfile=%u", &enabled); +-- +2.37.3 + diff --git a/0002-Add-support-for-creating-and-activating-integrity-de.patch b/0002-Add-support-for-creating-and-activating-integrity-de.patch new file mode 100644 index 0000000..163c812 --- /dev/null +++ b/0002-Add-support-for-creating-and-activating-integrity-de.patch @@ -0,0 +1,963 @@ +From 77e6a109043e87f88d2bd2b47d1cefce0eb9f5a9 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Mon, 20 Sep 2021 16:38:16 +0200 +Subject: [PATCH 1/3] Add support for creating and activating integrity devices + +This adds support for create, open and close actions for standalone +integrity devices using cryptsetup. +--- + configure.ac | 2 +- + src/lib/plugin_apis/crypto.api | 157 +++++++++++++++++ + src/plugins/crypto.c | 261 +++++++++++++++++++++++++++- + src/plugins/crypto.h | 41 +++++ + src/python/gi/overrides/BlockDev.py | 24 +++ + tests/crypto_test.py | 96 +++++++++- + 6 files changed, 573 insertions(+), 8 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 79bd97d8..79bf8045 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -210,7 +210,7 @@ AS_IF([test "x$with_crypto" != "xno"], + AS_IF([$PKG_CONFIG --atleast-version=2.0.3 libcryptsetup], + [AC_DEFINE([LIBCRYPTSETUP_2])], []) + AS_IF([$PKG_CONFIG --atleast-version=2.3.0 libcryptsetup], +- [AC_DEFINE([LIBCRYPTSETUP_BITLK])], []) ++ [AC_DEFINE([LIBCRYPTSETUP_23])], []) + AS_IF([$PKG_CONFIG --atleast-version=2.4.0 libcryptsetup], + [AC_DEFINE([LIBCRYPTSETUP_24])], []) + AS_IF([test "x$with_escrow" != "xno"], +diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api +index ef0217fe..40e32c89 100644 +--- a/src/lib/plugin_apis/crypto.api ++++ b/src/lib/plugin_apis/crypto.api +@@ -1,5 +1,6 @@ + #include + #include ++#include + + #define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB + +@@ -245,6 +246,115 @@ GType bd_crypto_luks_extra_get_type () { + return type; + } + ++#define BD_CRYPTO_TYPE_INTEGRITY_EXTRA (bd_crypto_integrity_extra_get_type ()) ++GType bd_crypto_integrity_extra_get_type(); ++ ++/** ++ * BDCryptoIntegrityExtra: ++ * @sector_size: integrity sector size ++ * @journal_size: size of journal in bytes ++ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit ++ * @journal_commit_time: journal commit time (or bitmap flush time) in ms ++ * @interleave_sectors: number of interleave sectors (power of two) ++ * @tag_size: tag size per-sector in bytes ++ * @buffer_sectors: number of sectors in one buffer ++ */ ++typedef struct BDCryptoIntegrityExtra { ++ guint32 sector_size; ++ guint64 journal_size; ++ guint journal_watermark; ++ guint journal_commit_time; ++ guint32 interleave_sectors; ++ guint32 tag_size; ++ guint32 buffer_sectors; ++} BDCryptoIntegrityExtra; ++ ++/** ++ * bd_crypto_integrity_extra_copy: (skip) ++ * @extra: (allow-none): %BDCryptoIntegrityExtra to copy ++ * ++ * Creates a new copy of @extra. ++ */ ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) { ++ if (extra == NULL) ++ return NULL; ++ ++ BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1); ++ ++ new_extra->sector_size = extra->sector_size; ++ new_extra->journal_size = extra->journal_size; ++ new_extra->journal_watermark = extra->journal_watermark; ++ new_extra->journal_commit_time = extra->journal_commit_time; ++ new_extra->interleave_sectors = extra->interleave_sectors; ++ new_extra->tag_size = extra->tag_size; ++ new_extra->buffer_sectors = extra->buffer_sectors; ++ ++ return new_extra; ++} ++ ++/** ++ * bd_crypto_integrity_extra_free: (skip) ++ * @extra: (allow-none): %BDCryptoIntegrityExtra to free ++ * ++ * Frees @extra. ++ */ ++void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) { ++ if (extra == NULL) ++ return; ++ ++ g_free (extra); ++} ++ ++/** ++ * bd_crypto_integrity_extra_new: (constructor) ++ * @sector_size: integrity sector size, 0 for default (512) ++ * @journal_size: size of journal in bytes ++ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit ++ * @journal_commit_time: journal commit time (or bitmap flush time) in ms ++ * @interleave_sectors: number of interleave sectors (power of two) ++ * @tag_size: tag size per-sector in bytes ++ * @buffer_sectors: number of sectors in one buffer ++ * ++ * Returns: (transfer full): a new Integrity extra argument ++ */ ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) { ++ BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1); ++ ret->sector_size = sector_size; ++ ret->journal_size = journal_size; ++ ret->journal_watermark = journal_watermark; ++ ret->journal_commit_time = journal_commit_time; ++ ret->interleave_sectors = interleave_sectors; ++ ret->tag_size = tag_size; ++ ret->buffer_sectors = buffer_sectors; ++ ++ return ret; ++} ++ ++GType bd_crypto_integrity_extra_get_type () { ++ static GType type = 0; ++ ++ if (G_UNLIKELY(type == 0)) { ++ type = g_boxed_type_register_static("BDCryptoIntegrityExtra", ++ (GBoxedCopyFunc) bd_crypto_integrity_extra_copy, ++ (GBoxedFreeFunc) bd_crypto_integrity_extra_free); ++ } ++ ++ return type; ++} ++ ++typedef enum { ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, ++ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, ++#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, ++#endif ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, ++#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, ++#endif ++ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, ++} BDCryptoIntegrityOpenFlags; ++ + #define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ()) + GType bd_crypto_luks_info_get_type(); + +@@ -857,6 +967,53 @@ BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error) + */ + BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error); + ++/** ++ * bd_crypto_integrity_format: ++ * @device: a device to format as integrity ++ * @algorithm: integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default ++ * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums ++ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed ++ * @key_size: size the integrity key and @key_data ++ * @extra: (allow-none): extra arguments for integrity format creation ++ * @error: (out): place to store error (if any) ++ * ++ * Formats the given @device as integrity according to the other parameters given. ++ * ++ * Returns: whether the given @device was successfully formatted as integrity or not ++ * (the @error) contains the error in such cases) ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE ++ */ ++gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error); ++ ++/** ++ * bd_crypto_integrity_open: ++ * @device: integrity device to open ++ * @name: name for the opened @device ++ * @algorithm: (allow-none): integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default ++ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed ++ * @key_size: size the integrity key and @key_data ++ * @flags: flags for the integrity device activation ++ * @extra: (allow-none): extra arguments for integrity open ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully opened or not ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE ++ */ ++gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error); ++ ++/** ++ * bd_crypto_integrity_close: ++ * @integrity_device: integrity device to close ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the given @integrity_device was successfully closed or not ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE ++ */ ++gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error); ++ + /** + * bd_crypto_device_seems_encrypted: + * @device: the queried device +diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c +index 51908140..8549cf23 100644 +--- a/src/plugins/crypto.c ++++ b/src/plugins/crypto.c +@@ -50,6 +50,18 @@ + + #define SECTOR_SIZE 512 + ++#define DEFAULT_LUKS_KEYSIZE_BITS 256 ++#define DEFAULT_LUKS_CIPHER "aes-xts-plain64" ++ ++#ifdef LIBCRYPTSETUP_23 ++/* 0 for autodetect since 2.3.0 */ ++#define DEFAULT_INTEGRITY_TAG_SIZE 0 ++#else ++/* we need some sane default for older versions, users should specify tag size when using ++ other algorithms than the default crc32c */ ++#define DEFAULT_INTEGRITY_TAG_SIZE 4 ++#endif ++ + #define UNUSED __attribute__((unused)) + + /** +@@ -146,6 +158,43 @@ BDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar + return ret; + } + ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) { ++ BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1); ++ ret->sector_size = sector_size; ++ ret->journal_size = journal_size; ++ ret->journal_watermark = journal_watermark; ++ ret->journal_commit_time = journal_commit_time; ++ ret->interleave_sectors = interleave_sectors; ++ ret->tag_size = tag_size; ++ ret->buffer_sectors = buffer_sectors; ++ ++ return ret; ++} ++ ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) { ++ if (extra == NULL) ++ return NULL; ++ ++ BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1); ++ ++ new_extra->sector_size = extra->sector_size; ++ new_extra->journal_size = extra->journal_size; ++ new_extra->journal_watermark = extra->journal_watermark; ++ new_extra->journal_commit_time = extra->journal_commit_time; ++ new_extra->interleave_sectors = extra->interleave_sectors; ++ new_extra->tag_size = extra->tag_size; ++ new_extra->buffer_sectors = extra->buffer_sectors; ++ ++ return new_extra; ++} ++ ++void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) { ++ if (extra == NULL) ++ return; ++ ++ g_free (extra); ++} ++ + void bd_crypto_luks_info_free (BDCryptoLUKSInfo *info) { + if (info == NULL) + return; +@@ -346,15 +395,15 @@ gboolean bd_crypto_is_tech_avail (BDCryptoTech tech, guint64 mode, GError **erro + "Integrity technology requires libcryptsetup >= 2.0"); + return FALSE; + #endif +- ret = mode & (BD_CRYPTO_TECH_MODE_QUERY); ++ ret = mode & (BD_CRYPTO_TECH_MODE_CREATE|BD_CRYPTO_TECH_MODE_OPEN_CLOSE|BD_CRYPTO_TECH_MODE_QUERY); + if (ret != mode) { + g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, +- "Only 'query' supported for Integrity"); ++ "Only 'create', 'open' and 'query' supported for Integrity"); + return FALSE; + } else + return TRUE; + case BD_CRYPTO_TECH_BITLK: +-#ifndef LIBCRYPTSETUP_BITLK ++#ifndef LIBCRYPTSETUP_23 + g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, + "BITLK technology requires libcryptsetup >= 2.3.0"); + return FALSE; +@@ -2035,6 +2084,208 @@ BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **e + } + #endif + ++static int _wipe_progress (guint64 size, guint64 offset, void *usrptr) { ++ /* "convert" the progress from 0-100 to 50-100 because wipe starts at 50 in bd_crypto_integrity_format */ ++ gdouble progress = 50 + (((gdouble) offset / size) * 100) / 2; ++ bd_utils_report_progress (*(guint64 *) usrptr, progress, "Integrity device wipe in progress"); ++ ++ return 0; ++} ++ ++/** ++ * bd_crypto_integrity_format: ++ * @device: a device to format as integrity ++ * @algorithm: integrity algorithm specification (e.g. "crc32c" or "sha256") ++ * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums ++ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed ++ * @key_size: size the integrity key and @key_data ++ * @extra: (allow-none): extra arguments for integrity format creation ++ * @error: (out): place to store error (if any) ++ * ++ * Formats the given @device as integrity according to the other parameters given. ++ * ++ * Returns: whether the given @device was successfully formatted as integrity or not ++ * (the @error) contains the error in such cases) ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE ++ */ ++gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error) { ++ struct crypt_device *cd = NULL; ++ gint ret; ++ guint64 progress_id = 0; ++ gchar *msg = NULL; ++ struct crypt_params_integrity params = ZERO_INIT; ++ g_autofree gchar *tmp_name = NULL; ++ g_autofree gchar *tmp_path = NULL; ++ g_autofree gchar *dev_name = NULL; ++ ++ msg = g_strdup_printf ("Started formatting '%s' as integrity device", device); ++ progress_id = bd_utils_report_started (msg); ++ g_free (msg); ++ ++ ret = crypt_init (&cd, device); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to initialize device: %s", strerror_l (-ret, c_locale)); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ if (extra) { ++ params.sector_size = extra->sector_size; ++ params.journal_size = extra->journal_size; ++ params.journal_watermark = extra->journal_watermark; ++ params.journal_commit_time = extra->journal_commit_time; ++ params.interleave_sectors = extra->interleave_sectors; ++ params.tag_size = extra->tag_size; ++ params.buffer_sectors = extra->buffer_sectors; ++ } ++ ++ params.integrity_key_size = key_size; ++ params.integrity = algorithm; ++ params.tag_size = params.tag_size ? params.tag_size : DEFAULT_INTEGRITY_TAG_SIZE; ++ ++ ret = crypt_format (cd, CRYPT_INTEGRITY, NULL, NULL, NULL, NULL, 0, ¶ms); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED, ++ "Failed to format device: %s", strerror_l (-ret, c_locale)); ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ if (wipe) { ++ bd_utils_report_progress (progress_id, 50, "Format created"); ++ ++ dev_name = g_path_get_basename (device); ++ tmp_name = g_strdup_printf ("bd-temp-integrity-%s-%d", dev_name, g_random_int ()); ++ tmp_path = g_strdup_printf ("%s/%s", crypt_get_dir (), tmp_name); ++ ++ ret = crypt_activate_by_volume_key (cd, tmp_name, (const char *) key_data, key_size, ++ CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to activate the newly created integrity device for wiping: %s", ++ strerror_l (-ret, c_locale)); ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ bd_utils_report_progress (progress_id, 50, "Starting to wipe the newly created integrity device"); ++ ret = crypt_wipe (cd, tmp_path, CRYPT_WIPE_ZERO, 0, 0, 1048576, ++ 0, &_wipe_progress, &progress_id); ++ bd_utils_report_progress (progress_id, 100, "Wipe finished"); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to wipe the newly created integrity device: %s", ++ strerror_l (-ret, c_locale)); ++ ++ ret = crypt_deactivate (cd, tmp_name); ++ if (ret != 0) ++ g_warning ("Failed to deactivate temporary device %s", tmp_name); ++ ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ ret = crypt_deactivate (cd, tmp_name); ++ if (ret != 0) ++ g_warning ("Failed to deactivate temporary device %s", tmp_name); ++ ++ } else ++ bd_utils_report_finished (progress_id, "Completed"); ++ ++ crypt_free (cd); ++ ++ return TRUE; ++} ++ ++/** ++ * bd_crypto_integrity_open: ++ * @device: integrity device to open ++ * @name: name for the opened @device ++ * @algorithm: (allow-none): integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default ++ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed ++ * @key_size: size the integrity key and @key_data ++ * @flags: flags for the integrity device activation ++ * @extra: (allow-none): extra arguments for integrity open ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully opened or not ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE ++ */ ++gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error) { ++ struct crypt_device *cd = NULL; ++ gint ret = 0; ++ guint64 progress_id = 0; ++ gchar *msg = NULL; ++ struct crypt_params_integrity params = ZERO_INIT; ++ ++ params.integrity = algorithm; ++ params.integrity_key_size = key_size; ++ ++ if (extra) { ++ params.sector_size = extra->sector_size; ++ params.journal_size = extra->journal_size; ++ params.journal_watermark = extra->journal_watermark; ++ params.journal_commit_time = extra->journal_commit_time; ++ params.interleave_sectors = extra->interleave_sectors; ++ params.tag_size = extra->tag_size; ++ params.buffer_sectors = extra->buffer_sectors; ++ } ++ ++ msg = g_strdup_printf ("Started opening '%s' integrity device", device); ++ progress_id = bd_utils_report_started (msg); ++ g_free (msg); ++ ++ ret = crypt_init (&cd, device); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to initialize device: %s", strerror_l (-ret, c_locale)); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ ret = crypt_load (cd, CRYPT_INTEGRITY, ¶ms); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to load device's parameters: %s", strerror_l (-ret, c_locale)); ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, flags); ++ if (ret < 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to activate device: %s", strerror_l (-ret, c_locale)); ++ ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, "Completed"); ++ return TRUE; ++} ++ ++/** ++ * bd_crypto_integrity_close: ++ * @integrity_device: integrity device to close ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the given @integrity_device was successfully closed or not ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE ++ */ ++gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error) { ++ return _crypto_close (integrity_device, "integrity", error); ++} ++ + /** + * bd_crypto_device_seems_encrypted: + * @device: the queried device +@@ -2471,7 +2722,7 @@ gboolean bd_crypto_escrow_device (const gchar *device, const gchar *passphrase, + * + * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE + */ +-#ifndef LIBCRYPTSETUP_BITLK ++#ifndef LIBCRYPTSETUP_23 + gboolean bd_crypto_bitlk_open (const gchar *device UNUSED, const gchar *name UNUSED, const guint8* pass_data UNUSED, gsize data_len UNUSED, gboolean read_only UNUSED, GError **error) { + /* this will return FALSE and set error, because BITLK technology is not available */ + return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_BITLK, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error); +@@ -2541,7 +2792,7 @@ gboolean bd_crypto_bitlk_open (const gchar *device, const gchar *name, const gui + * + * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE + */ +-#ifndef LIBCRYPTSETUP_BITLK ++#ifndef LIBCRYPTSETUP_23 + gboolean bd_crypto_bitlk_close (const gchar *bitlk_device UNUSED, GError **error) { + /* this will return FALSE and set error, because BITLK technology is not available */ + return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_BITLK, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error); +diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h +index 1c8f47ea..6c1d40dd 100644 +--- a/src/plugins/crypto.h ++++ b/src/plugins/crypto.h +@@ -122,6 +122,43 @@ void bd_crypto_luks_extra_free (BDCryptoLUKSExtra *extra); + BDCryptoLUKSExtra* bd_crypto_luks_extra_copy (BDCryptoLUKSExtra *extra); + BDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar *data_device, const gchar *integrity, guint64 sector_size, const gchar *label, const gchar *subsystem, BDCryptoLUKSPBKDF *pbkdf); + ++/** ++ * BDCryptoIntegrityExtra: ++ * @sector_size: integrity sector size ++ * @journal_size: size of journal in bytes ++ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit ++ * @journal_commit_time: journal commit time (or bitmap flush time) in ms ++ * @interleave_sectors: number of interleave sectors (power of two) ++ * @tag_size: tag size per-sector in bytes ++ * @buffer_sectors: number of sectors in one buffer ++ */ ++typedef struct BDCryptoIntegrityExtra { ++ guint32 sector_size; ++ guint64 journal_size; ++ guint journal_watermark; ++ guint journal_commit_time; ++ guint32 interleave_sectors; ++ guint32 tag_size; ++ guint32 buffer_sectors; ++} BDCryptoIntegrityExtra; ++ ++void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra); ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra); ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors); ++ ++typedef enum { ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, ++ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, ++#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, ++#endif ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, ++#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, ++#endif ++ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, ++} BDCryptoIntegrityOpenFlags; ++ + /** + * BDCryptoLUKSInfo: + * @version: LUKS version +@@ -215,6 +252,10 @@ gboolean bd_crypto_luks_header_restore (const gchar *device, const gchar *backup + BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error); + BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error); + ++gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error); ++gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error); ++gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error); ++ + gboolean bd_crypto_device_seems_encrypted (const gchar *device, GError **error); + gboolean bd_crypto_tc_open (const gchar *device, const gchar *name, const guint8* pass_data, gsize data_len, gboolean read_only, GError **error); + gboolean bd_crypto_tc_open_full (const gchar *device, const gchar *name, const guint8* pass_data, gsize data_len, const gchar **keyfiles, gboolean hidden, gboolean system, gboolean veracrypt, guint32 veracrypt_pim, gboolean read_only, GError **error); +diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py +index 8574ab04..8bd03cf8 100644 +--- a/src/python/gi/overrides/BlockDev.py ++++ b/src/python/gi/overrides/BlockDev.py +@@ -276,6 +276,30 @@ def crypto_bitlk_open(device, name, passphrase, read_only=False): + __all__.append("crypto_bitlk_open") + + ++class CryptoIntegrityExtra(BlockDev.CryptoIntegrityExtra): ++ def __new__(cls, sector_size=0, journal_size=0, journal_watermark=0, journal_commit_time=0, interleave_sectors=0, tag_size=0, buffer_sectors=0): ++ ret = BlockDev.CryptoIntegrityExtra.new(sector_size, journal_size, journal_watermark, journal_commit_time, interleave_sectors, tag_size, buffer_sectors) ++ ret.__class__ = cls ++ return ret ++ def __init__(self, *args, **kwargs): # pylint: disable=unused-argument ++ super(CryptoIntegrityExtra, self).__init__() #pylint: disable=bad-super-call ++CryptoIntegrityExtra = override(CryptoIntegrityExtra) ++__all__.append("CryptoIntegrityExtra") ++ ++ ++_crypto_integrity_format = BlockDev.crypto_integrity_format ++@override(BlockDev.crypto_integrity_format) ++def crypto_integrity_format(device, algorithm=None, wipe=True, key_data=None, extra=None): ++ return _crypto_integrity_format(device, algorithm, wipe, key_data, extra) ++__all__.append("crypto_integrity_format") ++ ++_crypto_integrity_open = BlockDev.crypto_integrity_open ++@override(BlockDev.crypto_integrity_open) ++def crypto_integrity_open(device, name, algorithm, key_data=None, flags=0, extra=None): ++ return _crypto_integrity_open(device, name, algorithm, key_data, flags, extra) ++__all__.append("crypto_integrity_open") ++ ++ + _dm_create_linear = BlockDev.dm_create_linear + @override(BlockDev.dm_create_linear) + def dm_create_linear(map_name, device, length, uuid=None): +diff --git a/tests/crypto_test.py b/tests/crypto_test.py +index 5e02c00d..a8fc8579 100644 +--- a/tests/crypto_test.py ++++ b/tests/crypto_test.py +@@ -2,6 +2,7 @@ import unittest + import os + import tempfile + import overrides_hack ++import secrets + import shutil + import subprocess + import six +@@ -34,6 +35,8 @@ class CryptoTestCase(unittest.TestCase): + + requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "loop")) + ++ _dm_name = "libblockdevTestLUKS" ++ + @classmethod + def setUpClass(cls): + unittest.TestCase.setUpClass() +@@ -64,7 +67,7 @@ class CryptoTestCase(unittest.TestCase): + + def _clean_up(self): + try: +- BlockDev.crypto_luks_close("libblockdevTestLUKS") ++ BlockDev.crypto_luks_close(self._dm_name) + except: + pass + +@@ -1029,7 +1032,7 @@ class CryptoTestLuksSectorSize(CryptoTestCase): + self.assertTrue(succ) + + +-class CryptoTestIntegrity(CryptoTestCase): ++class CryptoTestLUKS2Integrity(CryptoTestCase): + @tag_test(TestTags.SLOW) + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_integrity(self): +@@ -1216,3 +1219,92 @@ class CryptoTestBitlk(CryptoTestCase): + succ = BlockDev.crypto_bitlk_close("libblockdevTestBitlk") + self.assertTrue(succ) + self.assertFalse(os.path.exists("/dev/mapper/libblockdevTestBitlk")) ++ ++ ++class CryptoTestIntegrity(CryptoTestCase): ++ ++ _dm_name = "libblockdevTestIntegrity" ++ ++ @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") ++ def test_integrity(self): ++ # basic format+open+close test ++ succ = BlockDev.crypto_integrity_format(self.loop_dev, "sha256", False) ++ self.assertTrue(succ) ++ ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "sha256") ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ info = BlockDev.crypto_integrity_info(self._dm_name) ++ self.assertEqual(info.algorithm, "sha256") ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ # same now with a keyed algorithm ++ key = list(secrets.token_bytes(64)) ++ ++ succ = BlockDev.crypto_integrity_format(self.loop_dev, "hmac(sha256)", False, key) ++ self.assertTrue(succ) ++ ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "hmac(sha256)", key) ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ info = BlockDev.crypto_integrity_info(self._dm_name) ++ self.assertEqual(info.algorithm, "hmac(sha256)") ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ # same with some custom parameters ++ extra = BlockDev.CryptoIntegrityExtra(sector_size=4096, interleave_sectors=65536) ++ succ = BlockDev.crypto_integrity_format(self.loop_dev, "crc32c", wipe=False, extra=extra) ++ self.assertTrue(succ) ++ ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "crc32c") ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ info = BlockDev.crypto_integrity_info(self._dm_name) ++ self.assertEqual(info.algorithm, "crc32c") ++ self.assertEqual(info.sector_size, 4096) ++ self.assertEqual(info.interleave_sectors, 65536) ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ @tag_test(TestTags.SLOW) ++ @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") ++ def test_integrity_wipe(self): ++ # also check that wipe progress reporting works ++ progress_log = [] ++ ++ def _my_progress_func(_task, _status, completion, msg): ++ progress_log.append((completion, msg)) ++ ++ succ = BlockDev.utils_init_prog_reporting(_my_progress_func) ++ self.assertTrue(succ) ++ self.addCleanup(BlockDev.utils_init_prog_reporting, None) ++ ++ succ = BlockDev.crypto_integrity_format(self.loop_dev, "sha256", True) ++ self.assertTrue(succ) ++ ++ # at least one message "Integrity device wipe in progress" should be logged ++ self.assertTrue(any(prog[1] == "Integrity device wipe in progress" for prog in progress_log)) ++ ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "sha256") ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ # check the devices was wiped and the checksums recalculated ++ # (mkfs reads some blocks first so without checksums it would fail) ++ ret, _out, err = run_command("mkfs.ext2 /dev/mapper/%s " % self._dm_name) ++ self.assertEqual(ret, 0, msg="Failed to create ext2 filesystem on integrity: %s" % err) ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) +-- +2.37.3 + + +From ad4ac36520ec96af2a7b043189bbdf18cc3cffb9 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Thu, 30 Sep 2021 16:01:40 +0200 +Subject: [PATCH 2/3] Create smaller test images for integrity tests + +We are going to overwrite the entire device in test_integrity_wipe +so we need to make sure the sparse actually fits to /tmp which +can be smaller than 1 GiB. +--- + tests/crypto_test.py | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/tests/crypto_test.py b/tests/crypto_test.py +index a8fc8579..9758bf81 100644 +--- a/tests/crypto_test.py ++++ b/tests/crypto_test.py +@@ -36,6 +36,7 @@ class CryptoTestCase(unittest.TestCase): + requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "loop")) + + _dm_name = "libblockdevTestLUKS" ++ _sparse_size = 1024**3 + + @classmethod + def setUpClass(cls): +@@ -49,8 +50,8 @@ class CryptoTestCase(unittest.TestCase): + + def setUp(self): + self.addCleanup(self._clean_up) +- self.dev_file = create_sparse_tempfile("crypto_test", 1024**3) +- self.dev_file2 = create_sparse_tempfile("crypto_test2", 1024**3) ++ self.dev_file = create_sparse_tempfile("crypto_test", self._sparse_size) ++ self.dev_file2 = create_sparse_tempfile("crypto_test2", self._sparse_size) + try: + self.loop_dev = create_lio_device(self.dev_file) + except RuntimeError as e: +@@ -1224,6 +1225,7 @@ class CryptoTestBitlk(CryptoTestCase): + class CryptoTestIntegrity(CryptoTestCase): + + _dm_name = "libblockdevTestIntegrity" ++ _sparse_size = 100 * 1024**2 + + @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") + def test_integrity(self): +-- +2.37.3 + + +From 048a803be5186b30c0f0a7e67020486990ba6b81 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 20 Oct 2021 10:27:41 +0200 +Subject: [PATCH 3/3] crypto: Do not use libcryptsetup flags directly in + crypto.h + +We can "translate" our flags in the implementation instead to +avoid including libcryptsetup.h in our header and API files. +--- + src/lib/plugin_apis/crypto.api | 17 ++++++----------- + src/plugins/crypto.c | 34 +++++++++++++++++++++++++++++++++- + src/plugins/crypto.h | 16 ++++++---------- + tests/crypto_test.py | 14 ++++++++++++++ + 4 files changed, 59 insertions(+), 22 deletions(-) + +diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api +index 40e32c89..cf87979d 100644 +--- a/src/lib/plugin_apis/crypto.api ++++ b/src/lib/plugin_apis/crypto.api +@@ -1,6 +1,5 @@ + #include + #include +-#include + + #define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB + +@@ -343,16 +342,12 @@ GType bd_crypto_integrity_extra_get_type () { + } + + typedef enum { +- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, +- BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, +-#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP +- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, +-#endif +- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, +-#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET +- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, +-#endif +- BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = 1 << 0, ++ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = 1 << 1, ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = 1 << 2, ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = 1 << 3, ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = 1 << 4, ++ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5, + } BDCryptoIntegrityOpenFlags; + + #define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ()) +diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c +index 8549cf23..35c38410 100644 +--- a/src/plugins/crypto.c ++++ b/src/plugins/crypto.c +@@ -2223,6 +2223,7 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const + guint64 progress_id = 0; + gchar *msg = NULL; + struct crypt_params_integrity params = ZERO_INIT; ++ guint32 activate_flags = 0; + + params.integrity = algorithm; + params.integrity_key_size = key_size; +@@ -2237,6 +2238,37 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const + params.buffer_sectors = extra->buffer_sectors; + } + ++ ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL) ++ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL; ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECOVERY) ++ activate_flags |= CRYPT_ACTIVATE_RECOVERY; ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE) ++ activate_flags |= CRYPT_ACTIVATE_RECALCULATE; ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS) ++ activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP) { ++#ifndef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, ++ "Cannot activate %s with bitmap, installed version of cryptsetup doesn't support this option.", device); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++#else ++ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP; ++#endif ++ } ++ ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET) { ++#ifndef CRYPT_ACTIVATE_RECALCULATE_RESET ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, ++ "Cannot reset integrity recalculation while activating %s, installed version of cryptsetup doesn't support this option.", device); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++#else ++ activate_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET; ++#endif ++ } ++ + msg = g_strdup_printf ("Started opening '%s' integrity device", device); + progress_id = bd_utils_report_started (msg); + g_free (msg); +@@ -2258,7 +2290,7 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const + return FALSE; + } + +- ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, flags); ++ ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, activate_flags); + if (ret < 0) { + g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, + "Failed to activate device: %s", strerror_l (-ret, c_locale)); +diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h +index 6c1d40dd..536accf9 100644 +--- a/src/plugins/crypto.h ++++ b/src/plugins/crypto.h +@@ -147,16 +147,12 @@ BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra * + BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors); + + typedef enum { +- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, +- BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, +-#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP +- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, +-#endif +- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, +-#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET +- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, +-#endif +- BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = 1 << 0, ++ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = 1 << 1, ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = 1 << 2, ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = 1 << 3, ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = 1 << 4, ++ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5, + } BDCryptoIntegrityOpenFlags; + + /** +diff --git a/tests/crypto_test.py b/tests/crypto_test.py +index 9758bf81..94b89131 100644 +--- a/tests/crypto_test.py ++++ b/tests/crypto_test.py +@@ -1279,6 +1279,20 @@ class CryptoTestIntegrity(CryptoTestCase): + self.assertTrue(succ) + self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) + ++ # open with flags ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "crc32c", ++ flags=BlockDev.CryptoIntegrityOpenFlags.ALLOW_DISCARDS) ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ # check that discard is enabled for the mapped device ++ _ret, out, _err = run_command("dmsetup table %s" % self._dm_name) ++ self.assertIn("allow_discards", out) ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ + @tag_test(TestTags.SLOW) + @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") + def test_integrity_wipe(self): +-- +2.37.3 + diff --git a/0002-Fix-default-key-size-for-non-XTS-ciphers.patch b/0002-Fix-default-key-size-for-non-XTS-ciphers.patch deleted file mode 100644 index 6292ac7..0000000 --- a/0002-Fix-default-key-size-for-non-XTS-ciphers.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 5d29bc014a33d9bdc1c5fb4b8add2f38850f46a8 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 24 Feb 2021 14:44:03 +0100 -Subject: [PATCH] crypto: Fix default key size for non XTS ciphers - -512 bits should be default only for AES-XTS which needs two keys, -default for other modes must be 256 bits. - -resolves: rhbz#1931847 ---- - src/plugins/crypto.c | 11 +++++++++-- - src/plugins/crypto.h | 2 +- - tests/crypto_test.py | 36 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 46 insertions(+), 3 deletions(-) - -diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c -index f4a2e8f0..1e7043fa 100644 ---- a/src/plugins/crypto.c -+++ b/src/plugins/crypto.c -@@ -774,8 +774,15 @@ static gboolean luks_format (const gchar *device, const gchar *cipher, guint64 k - return FALSE; - } - -- /* resolve requested/default key_size (should be in bytes) */ -- key_size = (key_size != 0) ? (key_size / 8) : (DEFAULT_LUKS_KEYSIZE_BITS / 8); -+ if (key_size == 0) { -+ if (g_str_has_prefix (cipher_specs[1], "xts-")) -+ key_size = DEFAULT_LUKS_KEYSIZE_BITS * 2; -+ else -+ key_size = DEFAULT_LUKS_KEYSIZE_BITS; -+ } -+ -+ /* key_size should be in bytes */ -+ key_size = key_size / 8; - - /* wait for enough random data entropy (if requested) */ - if (min_entropy > 0) { -diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h -index 71a1438d..a38724d9 100644 ---- a/src/plugins/crypto.h -+++ b/src/plugins/crypto.h -@@ -36,7 +36,7 @@ typedef enum { - /* 20 chars * 6 bits per char (64-item charset) = 120 "bits of security" */ - #define BD_CRYPTO_BACKUP_PASSPHRASE_LENGTH 20 - --#define DEFAULT_LUKS_KEYSIZE_BITS 512 -+#define DEFAULT_LUKS_KEYSIZE_BITS 256 - #define DEFAULT_LUKS_CIPHER "aes-xts-plain64" - #define DEFAULT_LUKS2_SECTOR_SIZE 512 - -diff --git a/tests/crypto_test.py b/tests/crypto_test.py -index 0609a070..0aecc032 100644 ---- a/tests/crypto_test.py -+++ b/tests/crypto_test.py -@@ -236,6 +236,42 @@ def test_luks2_format(self): - self.fail("Failed to get pbkdf information from:\n%s %s" % (out, err)) - self.assertEqual(int(m.group(1)), 5) - -+ def _get_luks1_key_size(self, device): -+ _ret, out, err = run_command("cryptsetup luksDump %s" % device) -+ m = re.search(r"MK bits:\s*(\S+)\s*", out) -+ if not m or len(m.groups()) != 1: -+ self.fail("Failed to get key size information from:\n%s %s" % (out, err)) -+ key_size = m.group(1) -+ if not key_size.isnumeric(): -+ self.fail("Failed to get key size information from: %s" % key_size) -+ return int(key_size) -+ -+ @tag_test(TestTags.SLOW, TestTags.CORE) -+ def test_luks_format_key_size(self): -+ """Verify that formating device as LUKS works""" -+ -+ # aes-xts: key size should default to 512 -+ succ = BlockDev.crypto_luks_format(self.loop_dev, "aes-xts-plain64", 0, PASSWD, None, 0) -+ self.assertTrue(succ) -+ -+ key_size = self._get_luks1_key_size(self.loop_dev) -+ self.assertEqual(key_size, 512) -+ -+ # aes-cbc: key size should default to 256 -+ succ = BlockDev.crypto_luks_format(self.loop_dev, "aes-cbc-essiv:sha256", 0, PASSWD, None, 0) -+ self.assertTrue(succ) -+ -+ key_size = self._get_luks1_key_size(self.loop_dev) -+ self.assertEqual(key_size, 256) -+ -+ # try specifying key size for aes-xts -+ succ = BlockDev.crypto_luks_format(self.loop_dev, "aes-xts-plain64", 256, PASSWD, None, 0) -+ self.assertTrue(succ) -+ -+ key_size = self._get_luks1_key_size(self.loop_dev) -+ self.assertEqual(key_size, 256) -+ -+ - class CryptoTestResize(CryptoTestCase): - - def _get_key_location(self, device): diff --git a/0002-Fix-setting-locale-for-util-calls.patch b/0002-Fix-setting-locale-for-util-calls.patch deleted file mode 100644 index 52d9a66..0000000 --- a/0002-Fix-setting-locale-for-util-calls.patch +++ /dev/null @@ -1,119 +0,0 @@ -From a29d25fdfdcd7b133052eab1a3d1defe12c1733f Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 10 Jun 2020 17:03:28 +0200 -Subject: [PATCH] exec: Fix setting locale for util calls - -This actually fixes two issue. The _utils_exec_and_report_progress -function didn't set the LC_ALL=C environment variable to make sure -we get output in English. And also we shouldn't use setenv in the -GSpawnChildSetupFunc, it's actually example of what not to do in -g_spawn_async documentation. This fix uses g_environ_setenv and -passes the new environment to the g_spawn call. ---- - src/utils/exec.c | 26 +++++++++++++++++--------- - tests/utils_test.py | 7 +++++++ - 2 files changed, 24 insertions(+), 9 deletions(-) - -diff --git a/src/utils/exec.c b/src/utils/exec.c -index 9293930..37bd960 100644 ---- a/src/utils/exec.c -+++ b/src/utils/exec.c -@@ -140,11 +140,6 @@ static void log_done (guint64 task_id, gint exit_code) { - return; - } - --static void set_c_locale(gpointer user_data __attribute__((unused))) { -- if (setenv ("LC_ALL", "C", 1) != 0) -- g_warning ("Failed to set LC_ALL=C for a child process!"); --} -- - /** - * bd_utils_exec_and_report_error: - * @argv: (array zero-terminated=1): the argv array for the call -@@ -194,6 +189,8 @@ gboolean bd_utils_exec_and_report_status_error (const gchar **argv, const BDExtr - const BDExtraArg **extra_p = NULL; - gint exit_status = 0; - guint i = 0; -+ gchar **old_env = NULL; -+ gchar **new_env = NULL; - - if (extra) { - args_len = g_strv_length ((gchar **) argv); -@@ -219,16 +216,20 @@ gboolean bd_utils_exec_and_report_status_error (const gchar **argv, const BDExtr - args[i] = NULL; - } - -+ old_env = g_get_environ (); -+ new_env = g_environ_setenv (old_env, "LC_ALL", "C", TRUE); -+ - task_id = log_running (args ? args : argv); -- success = g_spawn_sync (NULL, args ? (gchar **) args : (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, -- (GSpawnChildSetupFunc) set_c_locale, NULL, -- &stdout_data, &stderr_data, &exit_status, error); -+ success = g_spawn_sync (NULL, args ? (gchar **) args : (gchar **) argv, new_env, G_SPAWN_SEARCH_PATH, -+ NULL, NULL, &stdout_data, &stderr_data, &exit_status, error); - if (!success) { - /* error is already populated from the call */ -+ g_strfreev (new_env); - g_free (stdout_data); - g_free (stderr_data); - return FALSE; - } -+ g_strfreev (new_env); - - /* g_spawn_sync set the status in the same way waitpid() does, we need - to get the process exit code manually (this is similar to calling -@@ -297,6 +298,8 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt - gboolean err_done = FALSE; - GString *stdout_data = g_string_new (NULL); - GString *stderr_data = g_string_new (NULL); -+ gchar **old_env = NULL; -+ gchar **new_env = NULL; - - /* TODO: share this code between functions */ - if (extra) { -@@ -325,7 +328,10 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt - - task_id = log_running (args ? args : argv); - -- ret = g_spawn_async_with_pipes (NULL, args ? (gchar**) args : (gchar**) argv, NULL, -+ old_env = g_get_environ (); -+ new_env = g_environ_setenv (old_env, "LC_ALL", "C", TRUE); -+ -+ ret = g_spawn_async_with_pipes (NULL, args ? (gchar**) args : (gchar**) argv, new_env, - G_SPAWN_DEFAULT|G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, - NULL, NULL, &pid, NULL, &out_fd, &err_fd, error); - -@@ -333,9 +339,11 @@ static gboolean _utils_exec_and_report_progress (const gchar **argv, const BDExt - /* error is already populated */ - g_string_free (stdout_data, TRUE); - g_string_free (stderr_data, TRUE); -+ g_strfreev (new_env); - g_free (args); - return FALSE; - } -+ g_strfreev (new_env); - - args_str = g_strjoinv (" ", args ? (gchar **) args : (gchar **) argv); - msg = g_strdup_printf ("Started '%s'", args_str); -diff --git a/tests/utils_test.py b/tests/utils_test.py -index 4bec3db..2bec5ed 100644 ---- a/tests/utils_test.py -+++ b/tests/utils_test.py -@@ -170,6 +170,13 @@ class UtilsExecLoggingTest(UtilsTestCase): - # exit code != 0 - self.assertTrue(BlockDev.utils_check_util_version("libblockdev-fake-util-fail", "1.1", "version", "Version:\\s(.*)")) - -+ @tag_test(TestTags.NOSTORAGE, TestTags.CORE) -+ def test_exec_locale(self): -+ """Verify that setting locale for exec functions works as expected""" -+ -+ succ, out = BlockDev.utils_exec_and_capture_output(["locale"]) -+ self.assertTrue(succ) -+ self.assertIn("LC_ALL=C", out) - - class UtilsDevUtilsTestCase(UtilsTestCase): - @tag_test(TestTags.NOSTORAGE, TestTags.CORE) --- -2.26.2 - diff --git a/0002-LVM-thin-metadata-calculation-fix.patch b/0002-LVM-thin-metadata-calculation-fix.patch deleted file mode 100644 index 3eca9ae..0000000 --- a/0002-LVM-thin-metadata-calculation-fix.patch +++ /dev/null @@ -1,914 +0,0 @@ -From 2bb371937c7ef73f26717e57a5eb78cafe90a9f7 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 20 Sep 2019 09:58:01 +0200 -Subject: [PATCH 1/5] Mark all GIR file constants as guint64 - -See 9676585e65f69ec1c309f45ba139035408d59b8e for more information. ---- - src/lib/plugin_apis/btrfs.api | 2 +- - src/lib/plugin_apis/crypto.api | 2 +- - src/lib/plugin_apis/lvm.api | 20 ++++++++++---------- - src/lib/plugin_apis/mdraid.api | 4 ++-- - 4 files changed, 14 insertions(+), 14 deletions(-) - -diff --git a/src/lib/plugin_apis/btrfs.api b/src/lib/plugin_apis/btrfs.api -index b52fb4ce..ef0f6c28 100644 ---- a/src/lib/plugin_apis/btrfs.api -+++ b/src/lib/plugin_apis/btrfs.api -@@ -3,7 +3,7 @@ - #include - - #define BD_BTRFS_MAIN_VOLUME_ID 5 --#define BD_BTRFS_MIN_MEMBER_SIZE (128 MiB) -+#define BD_BTRFS_MIN_MEMBER_SIZE G_GUINT64_CONSTANT (134217728ULL) // 128 MiB - - GQuark bd_btrfs_error_quark (void) { - return g_quark_from_static_string ("g-bd-btrfs-error-quark"); -diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api -index e3d69986..ef0217fe 100644 ---- a/src/lib/plugin_apis/crypto.api -+++ b/src/lib/plugin_apis/crypto.api -@@ -1,7 +1,7 @@ - #include - #include - --#define BD_CRYPTO_LUKS_METADATA_SIZE (2 MiB) -+#define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB - - GQuark bd_crypto_error_quark (void) { - return g_quark_from_static_string ("g-bd-crypto-error-quark"); -diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api -index 21c8f74d..ea52263b 100644 ---- a/src/lib/plugin_apis/lvm.api -+++ b/src/lib/plugin_apis/lvm.api -@@ -15,18 +15,18 @@ - #define BD_LVM_MAX_LV_SIZE G_GUINT64_CONSTANT (9223372036854775808ULL) - - --#define BD_LVM_DEFAULT_PE_START (1 MiB) --#define BD_LVM_DEFAULT_PE_SIZE (4 MiB) --#define BD_LVM_MIN_PE_SIZE (1 KiB) --#define BD_LVM_MAX_PE_SIZE (16 GiB) --#define BD_LVM_MIN_THPOOL_MD_SIZE (2 MiB) --#define BD_LVM_MAX_THPOOL_MD_SIZE (16 GiB) --#define BD_LVM_MIN_THPOOL_CHUNK_SIZE (64 KiB) --#define BD_LVM_MAX_THPOOL_CHUNK_SIZE (1 GiB) --#define BD_LVM_DEFAULT_CHUNK_SIZE (64 KiB) -+#define BD_LVM_DEFAULT_PE_START G_GUINT64_CONSTANT (1048576ULL) // 1 MiB -+#define BD_LVM_DEFAULT_PE_SIZE G_GUINT64_CONSTANT (4194304ULL) // 4 MiB -+#define BD_LVM_MIN_PE_SIZE G_GUINT64_CONSTANT (1024ULL) // 1 KiB -+#define BD_LVM_MAX_PE_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB -+#define BD_LVM_MIN_THPOOL_MD_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB -+#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB -+#define BD_LVM_MIN_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB -+#define BD_LVM_MAX_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (1073741824ULL) // 1 GiB -+#define BD_LVM_DEFAULT_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB - - /* according to lvmcache (7) */ --#define BD_LVM_MIN_CACHE_MD_SIZE (8 MiB) -+#define BD_LVM_MIN_CACHE_MD_SIZE (8388608ULL) // 8 MiB - - GQuark bd_lvm_error_quark (void) { - return g_quark_from_static_string ("g-bd-lvm-error-quark"); -diff --git a/src/lib/plugin_apis/mdraid.api b/src/lib/plugin_apis/mdraid.api -index 3bd9eaf2..02ca9530 100644 ---- a/src/lib/plugin_apis/mdraid.api -+++ b/src/lib/plugin_apis/mdraid.api -@@ -7,8 +7,8 @@ - - /* taken from blivet */ - // these defaults were determined empirically --#define BD_MD_SUPERBLOCK_SIZE (2 MiB) --#define BD_MD_CHUNK_SIZE (512 KiB) -+#define BD_MD_SUPERBLOCK_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB -+#define BD_MD_CHUNK_SIZE G_GUINT64_CONSTANT (524288ULL) // 512 KiB - - GQuark bd_md_error_quark (void) { - return g_quark_from_static_string ("g-bd-md-error-quark"); - -From aeedce3bcaa8182c9878cc51d3f85a6c6eb6a01f Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 3 Dec 2020 14:41:25 +0100 -Subject: [PATCH 2/5] lvm: Set thin metadata limits to match limits LVM uses in - lvcreate - ---- - src/lib/plugin_apis/lvm.api | 4 ++-- - src/plugins/lvm.h | 9 +++++++-- - tests/lvm_dbus_tests.py | 7 ++++--- - tests/lvm_test.py | 7 ++++--- - 4 files changed, 17 insertions(+), 10 deletions(-) - -diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api -index ea52263b..e843c916 100644 ---- a/src/lib/plugin_apis/lvm.api -+++ b/src/lib/plugin_apis/lvm.api -@@ -19,8 +19,8 @@ - #define BD_LVM_DEFAULT_PE_SIZE G_GUINT64_CONSTANT (4194304ULL) // 4 MiB - #define BD_LVM_MIN_PE_SIZE G_GUINT64_CONSTANT (1024ULL) // 1 KiB - #define BD_LVM_MAX_PE_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB --#define BD_LVM_MIN_THPOOL_MD_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB --#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB -+#define BD_LVM_MIN_THPOOL_MD_SIZE G_GUINT64_CONSTANT (4194304ULL) // 4 MiB -+#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (33957085184ULL) // 31.62 GiB - #define BD_LVM_MIN_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB - #define BD_LVM_MAX_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (1073741824ULL) // 1 GiB - #define BD_LVM_DEFAULT_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB -diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h -index 4b970f2e..01c06ca4 100644 ---- a/src/plugins/lvm.h -+++ b/src/plugins/lvm.h -@@ -1,5 +1,6 @@ - #include - #include -+#include - - #ifndef BD_LVM - #define BD_LVM -@@ -21,8 +22,12 @@ - #define USE_DEFAULT_PE_SIZE 0 - #define RESOLVE_PE_SIZE(size) ((size) == USE_DEFAULT_PE_SIZE ? BD_LVM_DEFAULT_PE_SIZE : (size)) - --#define BD_LVM_MIN_THPOOL_MD_SIZE (2 MiB) --#define BD_LVM_MAX_THPOOL_MD_SIZE (16 GiB) -+/* lvm constants for thin pool metadata size are actually half of these -+ but when they calculate the actual metadata size they double the limits -+ so lets just double the limits here too */ -+#define BD_LVM_MIN_THPOOL_MD_SIZE (4 MiB) -+#define BD_LVM_MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE KiB) -+ - #define BD_LVM_MIN_THPOOL_CHUNK_SIZE (64 KiB) - #define BD_LVM_MAX_THPOOL_CHUNK_SIZE (1 GiB) - #define BD_LVM_DEFAULT_CHUNK_SIZE (64 KiB) -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index 47402fc3..b517aae9 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -160,12 +160,13 @@ def test_get_thpool_meta_size(self): - def test_is_valid_thpool_md_size(self): - """Verify that is_valid_thpool_md_size works as expected""" - -- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(2 * 1024**2)) -- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2)) -+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(4 * 1024**2)) -+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(5 * 1024**2)) - self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3)) - - self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2)) -- self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(17 * 1024**3)) -+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2)) -+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(32 * 1024**3)) - - @tag_test(TestTags.NOSTORAGE) - def test_is_valid_thpool_chunk_size(self): -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index 149cf54a..d0085651 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -153,12 +153,13 @@ def test_get_thpool_meta_size(self): - def test_is_valid_thpool_md_size(self): - """Verify that is_valid_thpool_md_size works as expected""" - -- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(2 * 1024**2)) -- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2)) -+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(4 * 1024**2)) -+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(5 * 1024**2)) - self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3)) - - self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2)) -- self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(17 * 1024**3)) -+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2)) -+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(32 * 1024**3)) - - @tag_test(TestTags.NOSTORAGE) - def test_is_valid_thpool_chunk_size(self): - -From 15fcf1bb62865083a3483fc51f45e11cdc2d7386 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 3 Dec 2020 14:46:00 +0100 -Subject: [PATCH 3/5] lvm: Do not use thin_metadata_size to recommend thin - metadata size - -thin_metadata_size calculates the metadata size differently and -recommends smaller metadata than lvcreate so we should use the -lvcreate formula instead. - -Resolves: rhbz#1898668 ---- - dist/libblockdev.spec.in | 4 -- - src/lib/plugin_apis/lvm.api | 8 +-- - src/plugins/lvm-dbus.c | 78 ++++++----------------------- - src/plugins/lvm.c | 66 +++++++----------------- - src/python/gi/overrides/BlockDev.py | 6 +++ - tests/library_test.py | 6 +-- - tests/lvm_dbus_tests.py | 20 ++++---- - tests/lvm_test.py | 15 ++---- - tests/utils.py | 2 +- - 9 files changed, 61 insertions(+), 144 deletions(-) - -diff --git a/dist/libblockdev.spec.in b/dist/libblockdev.spec.in -index 7c775174..3e0a53c6 100644 ---- a/dist/libblockdev.spec.in -+++ b/dist/libblockdev.spec.in -@@ -387,8 +387,6 @@ BuildRequires: device-mapper-devel - Summary: The LVM plugin for the libblockdev library - Requires: %{name}-utils%{?_isa} >= 0.11 - Requires: lvm2 --# for thin_metadata_size --Requires: device-mapper-persistent-data - - %description lvm - The libblockdev library plugin (and in the same time a standalone library) -@@ -411,8 +409,6 @@ BuildRequires: device-mapper-devel - Summary: The LVM plugin for the libblockdev library - Requires: %{name}-utils%{?_isa} >= 1.4 - Requires: lvm2-dbusd >= 2.02.156 --# for thin_metadata_size --Requires: device-mapper-persistent-data - - %description lvm-dbus - The libblockdev library plugin (and in the same time a standalone library) -diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api -index e843c916..9f25c1ed 100644 ---- a/src/lib/plugin_apis/lvm.api -+++ b/src/lib/plugin_apis/lvm.api -@@ -704,11 +704,13 @@ guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean inclu - * bd_lvm_get_thpool_meta_size: - * @size: size of the thin pool - * @chunk_size: chunk size of the thin pool or 0 to use the default (%BD_LVM_DEFAULT_CHUNK_SIZE) -- * @n_snapshots: number of snapshots that will be created in the pool -+ * @n_snapshots: ignored - * @error: (out): place to store error (if any) - * -- * Returns: recommended size of the metadata space for the specified pool or 0 -- * in case of error -+ * Note: This function will be changed in 3.0: the @n_snapshots parameter -+ * is currently not used and will be removed. -+ * -+ * Returns: recommended size of the metadata space for the specified pool - * - * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored) - */ -diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c -index 9f821a99..24d54426 100644 ---- a/src/plugins/lvm-dbus.c -+++ b/src/plugins/lvm-dbus.c -@@ -20,7 +20,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -248,14 +247,6 @@ static volatile guint avail_features = 0; - static volatile guint avail_module_deps = 0; - static GMutex deps_check_lock; - --#define DEPS_THMS 0 --#define DEPS_THMS_MASK (1 << DEPS_THMS) --#define DEPS_LAST 1 -- --static const UtilDep deps[DEPS_LAST] = { -- {"thin_metadata_size", NULL, NULL, NULL}, --}; -- - #define DBUS_DEPS_LVMDBUSD 0 - #define DBUS_DEPS_LVMDBUSD_MASK (1 << DBUS_DEPS_LVMDBUSD) - #define DBUS_DEPS_LAST 1 -@@ -301,17 +292,6 @@ gboolean bd_lvm_check_deps (void) { - check_ret = check_ret && success; - } - -- for (i=0; i < DEPS_LAST; i++) { -- success = bd_utils_check_util_version (deps[i].name, deps[i].version, -- deps[i].ver_arg, deps[i].ver_regexp, &error); -- if (!success) -- g_warning ("%s", error->message); -- else -- g_atomic_int_or (&avail_deps, 1 << i); -- g_clear_error (&error); -- check_ret = check_ret && success; -- } -- - if (!check_ret) - g_warning("Cannot load the LVM plugin"); - -@@ -386,10 +366,7 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) { - g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_TECH_UNAVAIL, - "Only 'query' supported for thin calculations"); - return FALSE; -- } else if ((mode & BD_LVM_TECH_MODE_QUERY) && -- !check_deps (&avail_deps, DEPS_THMS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) -- return FALSE; -- else -+ } else - return TRUE; - case BD_LVM_TECH_CALCS: - if (mode & ~BD_LVM_TECH_MODE_QUERY) { -@@ -1303,53 +1280,28 @@ guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean inclu - * bd_lvm_get_thpool_meta_size: - * @size: size of the thin pool - * @chunk_size: chunk size of the thin pool or 0 to use the default (%BD_LVM_DEFAULT_CHUNK_SIZE) -- * @n_snapshots: number of snapshots that will be created in the pool -+ * @n_snapshots: ignored - * @error: (out): place to store error (if any) - * -- * Returns: recommended size of the metadata space for the specified pool or 0 -- * in case of error -+ * Note: This function will be changed in 3.0: the @n_snapshots parameter -+ * is currently not used and will be removed. -+ * -+ * Returns: recommended size of the metadata space for the specified pool - * - * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored) - */ --guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots, GError **error) { -- /* ub - output in bytes, n - output just the number */ -- const gchar* args[7] = {"thin_metadata_size", "-ub", "-n", NULL, NULL, NULL, NULL}; -- gchar *output = NULL; -- gboolean success = FALSE; -- guint64 ret = 0; -- -- if (!check_deps (&avail_deps, DEPS_THMS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) -- return 0; -+guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots UNUSED, GError **error UNUSED) { -+ guint64 md_size = 0; - -- /* s - total size, b - chunk size, m - number of snapshots */ -- args[3] = g_strdup_printf ("-s%"G_GUINT64_FORMAT, size); -- args[4] = g_strdup_printf ("-b%"G_GUINT64_FORMAT, -- chunk_size != 0 ? chunk_size : (guint64) BD_LVM_DEFAULT_CHUNK_SIZE); -- args[5] = g_strdup_printf ("-m%"G_GUINT64_FORMAT, n_snapshots); -- -- success = bd_utils_exec_and_capture_output (args, NULL, &output, error); -- g_free ((gchar*) args[3]); -- g_free ((gchar*) args[4]); -- g_free ((gchar*) args[5]); -- -- if (!success) { -- /* error is already set */ -- g_free (output); -- return 0; -- } -- -- ret = g_ascii_strtoull (output, NULL, 0); -- if (ret == 0) { -- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_PARSE, -- "Failed to parse number from thin_metadata_size's output: '%s'", -- output); -- g_free (output); -- return 0; -- } -+ /* based on lvcreate metadata size calculation */ -+ md_size = UINT64_C(64) * size / (chunk_size ? chunk_size : BD_LVM_DEFAULT_CHUNK_SIZE); - -- g_free (output); -+ if (md_size > BD_LVM_MAX_THPOOL_MD_SIZE) -+ md_size = BD_LVM_MAX_THPOOL_MD_SIZE; -+ else if (md_size < BD_LVM_MIN_THPOOL_MD_SIZE) -+ md_size = BD_LVM_MIN_THPOOL_MD_SIZE; - -- return MAX (ret, BD_LVM_MIN_THPOOL_MD_SIZE); -+ return md_size; - } - - /** -diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c -index 6bfaa338..74493feb 100644 ---- a/src/plugins/lvm.c -+++ b/src/plugins/lvm.c -@@ -20,7 +20,6 @@ - #include - #include - #include --#include - #include - #include - -@@ -213,13 +212,10 @@ static GMutex deps_check_lock; - - #define DEPS_LVM 0 - #define DEPS_LVM_MASK (1 << DEPS_LVM) --#define DEPS_THMS 1 --#define DEPS_THMS_MASK (1 << DEPS_THMS) --#define DEPS_LAST 2 -+#define DEPS_LAST 1 - - static const UtilDep deps[DEPS_LAST] = { - {"lvm", LVM_MIN_VERSION, "version", "LVM version:\\s+([\\d\\.]+)"}, -- {"thin_metadata_size", NULL, NULL, NULL}, - }; - - #define FEATURES_VDO 0 -@@ -236,6 +232,8 @@ static const UtilFeatureDep features[FEATURES_LAST] = { - - static const gchar*const module_deps[MODULE_DEPS_LAST] = { "kvdo" }; - -+#define UNUSED __attribute__((unused)) -+ - /** - * bd_lvm_check_deps: - * -@@ -317,10 +315,7 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) { - g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_TECH_UNAVAIL, - "Only 'query' supported for thin calculations"); - return FALSE; -- } else if ((mode & BD_LVM_TECH_MODE_QUERY) && -- !check_deps (&avail_deps, DEPS_THMS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) -- return FALSE; -- else -+ } else - return TRUE; - case BD_LVM_TECH_CALCS: - if (mode & ~BD_LVM_TECH_MODE_QUERY) { -@@ -820,53 +815,28 @@ guint64 bd_lvm_get_thpool_padding (guint64 size, guint64 pe_size, gboolean inclu - * bd_lvm_get_thpool_meta_size: - * @size: size of the thin pool - * @chunk_size: chunk size of the thin pool or 0 to use the default (%BD_LVM_DEFAULT_CHUNK_SIZE) -- * @n_snapshots: number of snapshots that will be created in the pool -+ * @n_snapshots: ignored - * @error: (out): place to store error (if any) - * -- * Returns: recommended size of the metadata space for the specified pool or 0 -- * in case of error -+ * Note: This function will be changed in 3.0: the @n_snapshots parameter -+ * is currently not used and will be removed. -+ * -+ * Returns: recommended size of the metadata space for the specified pool - * - * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored) - */ --guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots, GError **error) { -- /* ub - output in bytes, n - output just the number */ -- const gchar* args[7] = {"thin_metadata_size", "-ub", "-n", NULL, NULL, NULL, NULL}; -- gchar *output = NULL; -- gboolean success = FALSE; -- guint64 ret = 0; -- -- if (!check_deps (&avail_deps, DEPS_THMS_MASK, deps, DEPS_LAST, &deps_check_lock, error)) -- return 0; -+guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n_snapshots UNUSED, GError **error UNUSED) { -+ guint64 md_size = 0; - -- /* s - total size, b - chunk size, m - number of snapshots */ -- args[3] = g_strdup_printf ("-s%"G_GUINT64_FORMAT, size); -- args[4] = g_strdup_printf ("-b%"G_GUINT64_FORMAT, -- chunk_size != 0 ? chunk_size : (guint64) BD_LVM_DEFAULT_CHUNK_SIZE); -- args[5] = g_strdup_printf ("-m%"G_GUINT64_FORMAT, n_snapshots); -+ /* based on lvcreate metadata size calculation */ -+ md_size = UINT64_C(64) * size / (chunk_size ? chunk_size : BD_LVM_DEFAULT_CHUNK_SIZE); - -- success = bd_utils_exec_and_capture_output (args, NULL, &output, error); -- g_free ((gchar*) args[3]); -- g_free ((gchar*) args[4]); -- g_free ((gchar*) args[5]); -- -- if (!success) { -- /* error is already set */ -- g_free (output); -- return 0; -- } -- -- ret = g_ascii_strtoull (output, NULL, 0); -- if (ret == 0) { -- g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_PARSE, -- "Failed to parse number from thin_metadata_size's output: '%s'", -- output); -- g_free (output); -- return 0; -- } -- -- g_free (output); -+ if (md_size > BD_LVM_MAX_THPOOL_MD_SIZE) -+ md_size = BD_LVM_MAX_THPOOL_MD_SIZE; -+ else if (md_size < BD_LVM_MIN_THPOOL_MD_SIZE) -+ md_size = BD_LVM_MIN_THPOOL_MD_SIZE; - -- return MAX (ret, BD_LVM_MIN_THPOOL_MD_SIZE); -+ return md_size; - } - - /** -diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py -index d78bfaab..f768c8bd 100644 ---- a/src/python/gi/overrides/BlockDev.py -+++ b/src/python/gi/overrides/BlockDev.py -@@ -462,6 +462,12 @@ def lvm_get_thpool_padding(size, pe_size=0, included=False): - return _lvm_get_thpool_padding(size, pe_size, included) - __all__.append("lvm_get_thpool_padding") - -+_lvm_get_thpool_meta_size = BlockDev.lvm_get_thpool_meta_size -+@override(BlockDev.lvm_get_thpool_meta_size) -+def lvm_get_thpool_meta_size(size, chunk_size=0, n_snapshots=0): -+ return _lvm_get_thpool_meta_size(size, chunk_size, n_snapshots) -+__all__.append("lvm_get_thpool_meta_size") -+ - _lvm_pvcreate = BlockDev.lvm_pvcreate - @override(BlockDev.lvm_pvcreate) - def lvm_pvcreate(device, data_alignment=0, metadata_size=0, extra=None, **kwargs): -diff --git a/tests/library_test.py b/tests/library_test.py -index e8bb175a..08e44fdc 100644 ---- a/tests/library_test.py -+++ b/tests/library_test.py -@@ -349,8 +349,7 @@ def test_try_reinit(self): - - # try reinitializing with only some utilities being available and thus - # only some plugins able to load -- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", -- "thin_metadata_size", "swaplabel"]): -+ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", "swaplabel"]): - succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None) - self.assertFalse(succ) - for plug_name in ("swap", "lvm", "crypto"): -@@ -361,8 +360,7 @@ def test_try_reinit(self): - - # now the same with a subset of plugins requested - plugins = BlockDev.plugin_specs_from_names(["lvm", "swap", "crypto"]) -- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", -- "thin_metadata_size", "swaplabel"]): -+ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm","swaplabel"]): - succ, loaded = BlockDev.try_reinit(plugins, True, None) - self.assertTrue(succ) - self.assertEqual(set(loaded), set(["swap", "lvm", "crypto"])) -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index b517aae9..c06a480c 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -141,21 +141,19 @@ def test_get_thpool_padding(self): - def test_get_thpool_meta_size(self): - """Verify that getting recommended thin pool metadata size works as expected""" - -- # no idea how thin_metadata_size works, but let's at least check that -- # the function works and returns what thin_metadata_size says -- out1 = subprocess.check_output(["thin_metadata_size", "-ub", "-n", "-b64k", "-s1t", "-m100"]) -- self.assertEqual(int(out1), BlockDev.lvm_get_thpool_meta_size (1 * 1024**4, 64 * 1024, 100)) -+ # metadata size is calculated as 64 * pool_size / chunk_size -+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(1 * 1024**4, 64 * 1024), 1 * 1024**3) - -- out2 = subprocess.check_output(["thin_metadata_size", "-ub", "-n", "-b128k", "-s1t", "-m100"]) -- self.assertEqual(int(out2), BlockDev.lvm_get_thpool_meta_size (1 * 1024**4, 128 * 1024, 100)) -+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(1 * 1024**4, 128 * 1024), 512 * 1024**2) - -- # twice the chunk_size -> roughly half the metadata needed -- self.assertAlmostEqual(float(out1) / float(out2), 2, places=2) -- -- # unless thin_metadata_size gives a value that is not valid (too small) -- self.assertEqual(BlockDev.lvm_get_thpool_meta_size (100 * 1024**2, 128 * 1024, 100), -+ # lower limit is 4 MiB -+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(100 * 1024**2, 128 * 1024), - BlockDev.LVM_MIN_THPOOL_MD_SIZE) - -+ # upper limit is 31.62 GiB -+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(100 * 1024**4, 64 * 1024), -+ BlockDev.LVM_MAX_THPOOL_MD_SIZE) -+ - @tag_test(TestTags.NOSTORAGE) - def test_is_valid_thpool_md_size(self): - """Verify that is_valid_thpool_md_size works as expected""" -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index d0085651..b84adece 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -134,19 +134,14 @@ def test_get_thpool_padding(self): - def test_get_thpool_meta_size(self): - """Verify that getting recommended thin pool metadata size works as expected""" - -- # no idea how thin_metadata_size works, but let's at least check that -- # the function works and returns what thin_metadata_size says -- out1 = subprocess.check_output(["thin_metadata_size", "-ub", "-n", "-b64k", "-s1t", "-m100"]) -- self.assertEqual(int(out1), BlockDev.lvm_get_thpool_meta_size (1 * 1024**4, 64 * 1024, 100)) - -- out2 = subprocess.check_output(["thin_metadata_size", "-ub", "-n", "-b128k", "-s1t", "-m100"]) -- self.assertEqual(int(out2), BlockDev.lvm_get_thpool_meta_size (1 * 1024**4, 128 * 1024, 100)) -+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(1 * 1024**4, 64 * 1024), -+ 1 * 1024**3) - -- # twice the chunk_size -> roughly half the metadata needed -- self.assertAlmostEqual(float(out1) / float(out2), 2, places=2) -+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(1 * 1024**4, 128 * 1024), -+ 512 * 1024**2) - -- # unless thin_metadata_size gives a value that is not valid (too small) -- self.assertEqual(BlockDev.lvm_get_thpool_meta_size (100 * 1024**2, 128 * 1024, 100), -+ self.assertEqual(BlockDev.lvm_get_thpool_meta_size(100 * 1024**2, 128 * 1024), - BlockDev.LVM_MIN_THPOOL_MD_SIZE) - - @tag_test(TestTags.NOSTORAGE) -diff --git a/tests/utils.py b/tests/utils.py -index 182eda6a..584fde5c 100644 ---- a/tests/utils.py -+++ b/tests/utils.py -@@ -70,7 +70,7 @@ def fake_utils(path="."): - finally: - os.environ["PATH"] = old_path - --ALL_UTILS = {"lvm", "thin_metadata_size", "btrfs", "mkswap", "swaplabel", "multipath", "mpathconf", "dmsetup", "mdadm", "make-bcache", "sgdisk", "sfdisk"} -+ALL_UTILS = {"lvm", "btrfs", "mkswap", "swaplabel", "multipath", "mpathconf", "dmsetup", "mdadm", "make-bcache", "sgdisk", "sfdisk"} - - @contextmanager - def fake_path(path=None, keep_utils=None, all_but=None): - -From 27961a3fcb205ea51f40668d68765dd8d388777b Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 3 Dec 2020 14:48:08 +0100 -Subject: [PATCH 4/5] lvm: Use the UNUSED macro instead of - __attribute__((unused)) - -for unused attributes. It makes the function definition a little -bit more readable. ---- - src/plugins/lvm-dbus.c | 24 ++++++++++++------------ - src/plugins/lvm.c | 20 ++++++++++---------- - 2 files changed, 22 insertions(+), 22 deletions(-) - -diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c -index 24d54426..b7b4480e 100644 ---- a/src/plugins/lvm-dbus.c -+++ b/src/plugins/lvm-dbus.c -@@ -959,7 +959,7 @@ static BDLVMPVdata* get_pv_data_from_props (GVariant *props, GError **error) { - return data; - } - --static BDLVMVGdata* get_vg_data_from_props (GVariant *props, GError **error __attribute__((unused))) { -+static BDLVMVGdata* get_vg_data_from_props (GVariant *props, GError **error UNUSED) { - BDLVMVGdata *data = g_new0 (BDLVMVGdata, 1); - GVariantDict dict; - -@@ -1061,7 +1061,7 @@ static BDLVMLVdata* get_lv_data_from_props (GVariant *props, GError **error) { - return data; - } - --static BDLVMVDOPooldata* get_vdo_data_from_props (GVariant *props, GError **error __attribute__((unused))) { -+static BDLVMVDOPooldata* get_vdo_data_from_props (GVariant *props, GError **error UNUSED) { - BDLVMVDOPooldata *data = g_new0 (BDLVMVDOPooldata, 1); - GVariantDict dict; - gchar *value = NULL; -@@ -1165,7 +1165,7 @@ static GVariant* create_size_str_param (guint64 size, const gchar *unit) { - * - * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored) - */ --gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error __attribute__((unused))) { -+gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error UNUSED) { - return (((size % 2) == 0) && (size >= (BD_LVM_MIN_PE_SIZE)) && (size <= (BD_LVM_MAX_PE_SIZE))); - } - -@@ -1177,7 +1177,7 @@ gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error __attribute__ - * - * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored) - */ --guint64 *bd_lvm_get_supported_pe_sizes (GError **error __attribute__((unused))) { -+guint64 *bd_lvm_get_supported_pe_sizes (GError **error UNUSED) { - guint8 i; - guint64 val = BD_LVM_MIN_PE_SIZE; - guint8 num_items = ((guint8) round (log2 ((double) BD_LVM_MAX_PE_SIZE))) - ((guint8) round (log2 ((double) BD_LVM_MIN_PE_SIZE))) + 2; -@@ -1199,7 +1199,7 @@ guint64 *bd_lvm_get_supported_pe_sizes (GError **error __attribute__((unused))) - * - * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored) - */ --guint64 bd_lvm_get_max_lv_size (GError **error __attribute__((unused))) { -+guint64 bd_lvm_get_max_lv_size (GError **error UNUSED) { - return BD_LVM_MAX_LV_SIZE; - } - -@@ -1219,7 +1219,7 @@ guint64 bd_lvm_get_max_lv_size (GError **error __attribute__((unused))) { - * - * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored) - */ --guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error __attribute__((unused))) { -+guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error UNUSED) { - pe_size = RESOLVE_PE_SIZE(pe_size); - guint64 delta = size % pe_size; - if (delta == 0) -@@ -1313,7 +1313,7 @@ guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n - * - * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored) - */ --gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error __attribute__((unused))) { -+gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error UNUSED) { - return ((BD_LVM_MIN_THPOOL_MD_SIZE <= size) && (size <= BD_LVM_MAX_THPOOL_MD_SIZE)); - } - -@@ -1327,7 +1327,7 @@ gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error __attribut - * - * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored) - */ --gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error __attribute__((unused))) { -+gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error UNUSED) { - gdouble size_log2 = 0.0; - - if ((size < BD_LVM_MIN_THPOOL_CHUNK_SIZE) || (size > BD_LVM_MAX_THPOOL_CHUNK_SIZE)) -@@ -2616,7 +2616,7 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name - * - * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored) - */ --gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error __attribute__((unused))) { -+gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error UNUSED) { - /* XXX: the error attribute will likely be used in the future when - some validation comes into the game */ - -@@ -2641,7 +2641,7 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error __att - * - * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored) - */ --gchar* bd_lvm_get_global_config (GError **error __attribute__((unused))) { -+gchar* bd_lvm_get_global_config (GError **error UNUSED) { - gchar *ret = NULL; - - g_mutex_lock (&global_config_lock); -@@ -2660,7 +2660,7 @@ gchar* bd_lvm_get_global_config (GError **error __attribute__((unused))) { - * - * Tech category: %BD_LVM_TECH_CACHE_CALCS no mode (it is ignored) - */ --guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error __attribute__((unused))) { -+guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error UNUSED) { - return MAX ((guint64) cache_size / 1000, BD_LVM_MIN_CACHE_MD_SIZE); - } - -@@ -2670,7 +2670,7 @@ guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error __a - * - * Get LV type string from flags. - */ --static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error __attribute__((unused))) { -+static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error UNUSED) { - if (!meta) { - if (flags & BD_LVM_CACHE_POOL_STRIPED) - return "striped"; -diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c -index 74493feb..2be1dbdb 100644 ---- a/src/plugins/lvm.c -+++ b/src/plugins/lvm.c -@@ -700,7 +700,7 @@ static BDLVMVDOPooldata* get_vdo_data_from_table (GHashTable *table, gboolean fr - * - * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored) - */ --gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error __attribute__((unused))) { -+gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error UNUSED) { - return (((size % 2) == 0) && (size >= (BD_LVM_MIN_PE_SIZE)) && (size <= (BD_LVM_MAX_PE_SIZE))); - } - -@@ -712,7 +712,7 @@ gboolean bd_lvm_is_supported_pe_size (guint64 size, GError **error __attribute__ - * - * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored) - */ --guint64 *bd_lvm_get_supported_pe_sizes (GError **error __attribute__((unused))) { -+guint64 *bd_lvm_get_supported_pe_sizes (GError **error UNUSED) { - guint8 i; - guint64 val = BD_LVM_MIN_PE_SIZE; - guint8 num_items = ((guint8) round (log2 ((double) BD_LVM_MAX_PE_SIZE))) - ((guint8) round (log2 ((double) BD_LVM_MIN_PE_SIZE))) + 2; -@@ -734,7 +734,7 @@ guint64 *bd_lvm_get_supported_pe_sizes (GError **error __attribute__((unused))) - * - * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored) - */ --guint64 bd_lvm_get_max_lv_size (GError **error __attribute__((unused))) { -+guint64 bd_lvm_get_max_lv_size (GError **error UNUSED) { - return BD_LVM_MAX_LV_SIZE; - } - -@@ -754,7 +754,7 @@ guint64 bd_lvm_get_max_lv_size (GError **error __attribute__((unused))) { - * - * Tech category: %BD_LVM_TECH_CALCS no mode (it is ignored) - */ --guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error __attribute__((unused))) { -+guint64 bd_lvm_round_size_to_pe (guint64 size, guint64 pe_size, gboolean roundup, GError **error UNUSED) { - pe_size = RESOLVE_PE_SIZE(pe_size); - guint64 delta = size % pe_size; - if (delta == 0) -@@ -848,7 +848,7 @@ guint64 bd_lvm_get_thpool_meta_size (guint64 size, guint64 chunk_size, guint64 n - * - * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored) - */ --gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error __attribute__((unused))) { -+gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error UNUSED) { - return ((BD_LVM_MIN_THPOOL_MD_SIZE <= size) && (size <= BD_LVM_MAX_THPOOL_MD_SIZE)); - } - -@@ -862,7 +862,7 @@ gboolean bd_lvm_is_valid_thpool_md_size (guint64 size, GError **error __attribut - * - * Tech category: %BD_LVM_TECH_THIN_CALCS no mode (it is ignored) - */ --gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error __attribute__((unused))) { -+gboolean bd_lvm_is_valid_thpool_chunk_size (guint64 size, gboolean discard, GError **error UNUSED) { - gdouble size_log2 = 0.0; - - if ((size < BD_LVM_MIN_THPOOL_CHUNK_SIZE) || (size > BD_LVM_MAX_THPOOL_CHUNK_SIZE)) -@@ -1983,7 +1983,7 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name - * - * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored) - */ --gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error __attribute__((unused))) { -+gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error UNUSED) { - /* XXX: the error attribute will likely be used in the future when - some validation comes into the game */ - -@@ -2008,7 +2008,7 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error __att - * - * Tech category: %BD_LVM_TECH_GLOB_CONF no mode (it is ignored) - */ --gchar* bd_lvm_get_global_config (GError **error __attribute__((unused))) { -+gchar* bd_lvm_get_global_config (GError **error UNUSED) { - gchar *ret = NULL; - - g_mutex_lock (&global_config_lock); -@@ -2027,7 +2027,7 @@ gchar* bd_lvm_get_global_config (GError **error __attribute__((unused))) { - * - * Tech category: %BD_LVM_TECH_CACHE_CALCS no mode (it is ignored) - */ --guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error __attribute__((unused))) { -+guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error UNUSED) { - return MAX ((guint64) cache_size / 1000, BD_LVM_MIN_CACHE_MD_SIZE); - } - -@@ -2037,7 +2037,7 @@ guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error __a - * - * Get LV type string from flags. - */ --static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error __attribute__((unused))) { -+static const gchar* get_lv_type_from_flags (BDLVMCachePoolFlags flags, gboolean meta, GError **error UNUSED) { - if (!meta) { - if (flags & BD_LVM_CACHE_POOL_STRIPED) - return "striped"; - -From f106e775d3c73e5f97512dd109627e00539b703a Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 15 Dec 2020 14:53:13 +0100 -Subject: [PATCH 5/5] Fix max size limit for LVM thinpool metadata - -DM_THIN_MAX_METADATA_SIZE is in 512 sectors, not in KiB so the -upper limit is 15.81 GiB not 31.62 GiB ---- - src/lib/plugin_apis/lvm.api | 2 +- - src/plugins/lvm.h | 10 ++++++---- - tests/lvm_dbus_tests.py | 3 ++- - tests/lvm_test.py | 3 ++- - 4 files changed, 11 insertions(+), 7 deletions(-) - -diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api -index 9f25c1ed..563c1041 100644 ---- a/src/lib/plugin_apis/lvm.api -+++ b/src/lib/plugin_apis/lvm.api -@@ -20,7 +20,7 @@ - #define BD_LVM_MIN_PE_SIZE G_GUINT64_CONSTANT (1024ULL) // 1 KiB - #define BD_LVM_MAX_PE_SIZE G_GUINT64_CONSTANT (17179869184ULL) // 16 GiB - #define BD_LVM_MIN_THPOOL_MD_SIZE G_GUINT64_CONSTANT (4194304ULL) // 4 MiB --#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (33957085184ULL) // 31.62 GiB -+#define BD_LVM_MAX_THPOOL_MD_SIZE G_GUINT64_CONSTANT (16978542592ULL) // 15.81 GiB - #define BD_LVM_MIN_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB - #define BD_LVM_MAX_THPOOL_CHUNK_SIZE G_GUINT64_CONSTANT (1073741824ULL) // 1 GiB - #define BD_LVM_DEFAULT_CHUNK_SIZE G_GUINT64_CONSTANT (65536ULL) // 64 KiB -diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h -index 01c06ca4..2162d769 100644 ---- a/src/plugins/lvm.h -+++ b/src/plugins/lvm.h -@@ -22,11 +22,13 @@ - #define USE_DEFAULT_PE_SIZE 0 - #define RESOLVE_PE_SIZE(size) ((size) == USE_DEFAULT_PE_SIZE ? BD_LVM_DEFAULT_PE_SIZE : (size)) - --/* lvm constants for thin pool metadata size are actually half of these -- but when they calculate the actual metadata size they double the limits -- so lets just double the limits here too */ -+/* lvm constant for thin pool metadata size is actually half of this -+ but when they calculate the actual metadata size they double the limit -+ so lets just double the limit here too */ - #define BD_LVM_MIN_THPOOL_MD_SIZE (4 MiB) --#define BD_LVM_MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE KiB) -+ -+/* DM_THIN_MAX_METADATA_SIZE is in 512 sectors */ -+#define BD_LVM_MAX_THPOOL_MD_SIZE (DM_THIN_MAX_METADATA_SIZE * 512) - - #define BD_LVM_MIN_THPOOL_CHUNK_SIZE (64 KiB) - #define BD_LVM_MAX_THPOOL_CHUNK_SIZE (1 GiB) -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index c06a480c..8f2bb95d 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -160,10 +160,11 @@ def test_is_valid_thpool_md_size(self): - - self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(4 * 1024**2)) - self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(5 * 1024**2)) -- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3)) -+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(15 * 1024**3)) - - self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2)) - self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2)) -+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3)) - self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(32 * 1024**3)) - - @tag_test(TestTags.NOSTORAGE) -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index b84adece..6f80a3ba 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -150,10 +150,11 @@ def test_is_valid_thpool_md_size(self): - - self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(4 * 1024**2)) - self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(5 * 1024**2)) -- self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3)) -+ self.assertTrue(BlockDev.lvm_is_valid_thpool_md_size(15 * 1024**3)) - - self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(1 * 1024**2)) - self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(3 * 1024**2)) -+ self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(16 * 1024**3)) - self.assertFalse(BlockDev.lvm_is_valid_thpool_md_size(32 * 1024**3)) - - @tag_test(TestTags.NOSTORAGE) diff --git a/0003-Memory-leaks-fixes-backport.patch b/0003-Memory-leaks-fixes-backport.patch deleted file mode 100644 index 5c19421..0000000 --- a/0003-Memory-leaks-fixes-backport.patch +++ /dev/null @@ -1,178 +0,0 @@ -From 98cb3b9cf2046ba6e33db6ff400449c6a4827932 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 29 Apr 2021 12:38:49 +0200 -Subject: [PATCH 1/8] kbd: Fix memory leak - ---- - src/plugins/kbd.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/plugins/kbd.c b/src/plugins/kbd.c -index a2908ecb..d5ae0ed7 100644 ---- a/src/plugins/kbd.c -+++ b/src/plugins/kbd.c -@@ -1035,6 +1035,7 @@ gboolean bd_kbd_bcache_destroy (const gchar *bcache_device, GError **error) { - - if (c_set_uuid) { - path = g_strdup_printf ("/sys/fs/bcache/%s/stop", c_set_uuid); -+ g_free (c_set_uuid); - success = bd_utils_echo_str_to_file ("1", path, error); - g_free (path); - if (!success) { - -From c6d226c70996f6006a3f6eff13f8264f03e95c4f Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:22:58 +0200 -Subject: [PATCH 2/8] crypto: Fix memory leak - ---- - src/plugins/crypto.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c -index 1e7043fa..4fad9a85 100644 ---- a/src/plugins/crypto.c -+++ b/src/plugins/crypto.c -@@ -1275,6 +1275,7 @@ gboolean bd_crypto_luks_add_key (const gchar *device, const gchar *pass, const g - success = g_file_get_contents (nkey_file, &nkey_buf, &nbuf_len, error); - if (!success) { - g_prefix_error (error, "Failed to load key from file '%s': ", nkey_file); -+ g_free (key_buf); - return FALSE; - } - } else - -From 41b460fb81cf066e7ddc0bdda7f34db5e90b9f79 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:23:24 +0200 -Subject: [PATCH 3/8] dm: Fix memory leak in the DM plugin and DM logging - redirect function - ---- - src/plugins/dm.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/plugins/dm.c b/src/plugins/dm.c -index fb4e50b5..c9a735ed 100644 ---- a/src/plugins/dm.c -+++ b/src/plugins/dm.c -@@ -245,7 +245,8 @@ gchar* bd_dm_name_from_node (const gchar *dm_node, GError **error) { - g_free (sys_path); - - if (!success) { -- /* errror is already populated */ -+ /* error is already populated */ -+ g_free (ret); - return NULL; - } - - -From 8d085fbb15c18ca91a5eff89192391c5a0b3bb7a Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:24:14 +0200 -Subject: [PATCH 4/8] fs: Fix memory leak - ---- - src/plugins/fs/mount.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/plugins/fs/mount.c b/src/plugins/fs/mount.c -index 43d64e8c..46e03ca4 100644 ---- a/src/plugins/fs/mount.c -+++ b/src/plugins/fs/mount.c -@@ -541,6 +541,7 @@ static gboolean run_as_user (MountFunc func, MountArgs *args, uid_t run_as_uid, - "Unknoen error while reading error."); - g_io_channel_unref (channel); - close (pipefd[0]); -+ g_free (error_msg); - return FALSE; - } - - -From 6c45f4ef1fc898d71cc2f13670adb508a6037c66 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:26:24 +0200 -Subject: [PATCH 5/8] kbd: Fix memory leak - ---- - src/plugins/kbd.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/plugins/kbd.c b/src/plugins/kbd.c -index d5ae0ed7..ff8bde17 100644 ---- a/src/plugins/kbd.c -+++ b/src/plugins/kbd.c -@@ -1255,6 +1255,7 @@ static gboolean get_cache_size_used (const gchar *cache_dev_sys, guint64 *size, - g_io_channel_unref (file); - - if (!found) { -+ g_free (line); - g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_BCACHE_INVAL, - "Failed to get cache usage data"); - return FALSE; - -From 4f4e93dfca36421eb0e0cb2dec5d48df5bc2f363 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:26:37 +0200 -Subject: [PATCH 6/8] lvm-dbus: Fix memory leak - ---- - src/plugins/lvm-dbus.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c -index b7b4480e..144551f5 100644 ---- a/src/plugins/lvm-dbus.c -+++ b/src/plugins/lvm-dbus.c -@@ -2927,6 +2927,7 @@ gboolean bd_lvm_cache_detach (const gchar *vg_name, const gchar *cached_lv, gboo - lv_id = g_strdup_printf ("%s/%s", vg_name, cached_lv); - call_lvm_obj_method_sync (lv_id, CACHED_LV_INTF, "DetachCachePool", params, NULL, extra, TRUE, error); - g_free (lv_id); -+ g_free (cache_pool_name); - return ((*error) == NULL); - } - - -From 410a10bc2cfceeb550d72456573d4722b4207ddc Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:27:22 +0200 -Subject: [PATCH 7/8] mdraid: Fix memory leak - ---- - src/plugins/mdraid.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c -index 74af744c..b97bc641 100644 ---- a/src/plugins/mdraid.c -+++ b/src/plugins/mdraid.c -@@ -1332,6 +1332,7 @@ gchar* bd_md_name_from_node (const gchar *node, GError **error) { - continue; - } - node_name = g_path_get_basename (dev_path); -+ g_free (dev_path); - if (g_strcmp0 (node_name, node) == 0) { - found = TRUE; - name = g_path_get_basename (*path_p); - -From 0d49e5d190e24fa89ae2795714d0276f24285b19 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:27:54 +0200 -Subject: [PATCH 8/8] swap: Fix memory leak - ---- - src/plugins/swap.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/plugins/swap.c b/src/plugins/swap.c -index 102780a7..115f8fca 100644 ---- a/src/plugins/swap.c -+++ b/src/plugins/swap.c -@@ -417,6 +417,7 @@ gboolean bd_swap_swapstatus (const gchar *device, GError **error) { - if (!real_device) { - /* the device doesn't exist and thus is not an active swap */ - g_clear_error (error); -+ g_free (file_content); - return FALSE; - } - } diff --git a/0004-Adapt-to-dosfstools-4.2-changes.patch b/0004-Adapt-to-dosfstools-4.2-changes.patch deleted file mode 100644 index a32e4ae..0000000 --- a/0004-Adapt-to-dosfstools-4.2-changes.patch +++ /dev/null @@ -1,296 +0,0 @@ -From cc522ec3717d909370af6181c7859c62fa0167df Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Mon, 22 Feb 2021 15:40:56 +0100 -Subject: [PATCH 1/2] fs: Allow using empty label for vfat with newest - dosfstools - ---- - src/plugins/fs/vfat.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/src/plugins/fs/vfat.c b/src/plugins/fs/vfat.c -index ff0c35a3..ce13f147 100644 ---- a/src/plugins/fs/vfat.c -+++ b/src/plugins/fs/vfat.c -@@ -232,10 +232,21 @@ gboolean bd_fs_vfat_repair (const gchar *device, const BDExtraArg **extra, GErro - */ - gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError **error) { - const gchar *args[4] = {"fatlabel", device, label, NULL}; -+ UtilDep dep = {"fatlabel", "4.2", "--version", "fatlabel\\s+([\\d\\.]+).+"}; -+ gboolean new_vfat = FALSE; - - if (!check_deps (&avail_deps, DEPS_FATLABEL_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; - -+ if (!label || g_strcmp0 (label, "") == 0) { -+ /* fatlabel >= 4.2 refuses to set empty label */ -+ new_vfat = bd_utils_check_util_version (dep.name, dep.version, -+ dep.ver_arg, dep.ver_regexp, -+ NULL); -+ if (new_vfat) -+ args[2] = "--reset"; -+ } -+ - return bd_utils_exec_and_report_error (args, NULL, error); - } - - -From c3c3583409c8ed8f99a840e0c70cc92ca1dd3c93 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 27 Apr 2021 14:06:59 +0200 -Subject: [PATCH 2/2] tests: Call fs_vfat_mkfs with "--mbr=n" extra option in - tests - -Without the option the newest dosfstools 4.2 will create a valid -MBR partition table with a simgle partition on the disk, see -dosfstools/dosfstools#95 for details. ---- - src/plugins/fs/vfat.c | 5 ++- - tests/fs_test.py | 76 +++++++++++++++++++++++++++++++++---------- - 2 files changed, 62 insertions(+), 19 deletions(-) - -diff --git a/src/plugins/fs/vfat.c b/src/plugins/fs/vfat.c -index ce13f147..6cb82537 100644 ---- a/src/plugins/fs/vfat.c -+++ b/src/plugins/fs/vfat.c -@@ -234,6 +234,7 @@ gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError * - const gchar *args[4] = {"fatlabel", device, label, NULL}; - UtilDep dep = {"fatlabel", "4.2", "--version", "fatlabel\\s+([\\d\\.]+).+"}; - gboolean new_vfat = FALSE; -+ GError *loc_error = NULL; - - if (!check_deps (&avail_deps, DEPS_FATLABEL_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; -@@ -242,9 +243,11 @@ gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError * - /* fatlabel >= 4.2 refuses to set empty label */ - new_vfat = bd_utils_check_util_version (dep.name, dep.version, - dep.ver_arg, dep.ver_regexp, -- NULL); -+ &loc_error); - if (new_vfat) - args[2] = "--reset"; -+ else -+ g_clear_error (&loc_error); - } - - return bd_utils_exec_and_report_error (args, NULL, error); -diff --git a/tests/fs_test.py b/tests/fs_test.py -index 239cb47c..2233db4f 100644 ---- a/tests/fs_test.py -+++ b/tests/fs_test.py -@@ -5,10 +5,13 @@ - import tempfile - from contextlib import contextmanager - import utils --from utils import run, create_sparse_tempfile, mount, umount, TestTags, tag_test -+from utils import run, create_sparse_tempfile, mount, umount, TestTags, tag_test, run_command -+import re - import six - import overrides_hack - -+from distutils.version import LooseVersion -+ - from gi.repository import BlockDev, GLib - - -@@ -29,9 +32,20 @@ def mounted(device, where, ro=False): - yield - umount(where) - -+ -+def _get_dosfstools_version(): -+ _ret, out, _err = run_command("mkfs.vfat --help") -+ # mkfs.fat 4.1 (2017-01-24) -+ m = re.search(r"mkfs\.fat ([\d\.]+)", out) -+ if not m or len(m.groups()) != 1: -+ raise RuntimeError("Failed to determine dosfstools version from: %s" % out) -+ return LooseVersion(m.groups()[0]) -+ -+ - class FSTestCase(unittest.TestCase): - - requested_plugins = BlockDev.plugin_specs_from_names(("fs", "loop")) -+ _vfat_version = _get_dosfstools_version() - - @classmethod - def setUpClass(cls): -@@ -66,6 +80,11 @@ def setUp(self): - - self.mount_dir = tempfile.mkdtemp(prefix="libblockdev.", suffix="ext4_test") - -+ if self._vfat_version <= LooseVersion("4.1"): -+ self._mkfs_options = None -+ else: -+ self._mkfs_options = [BlockDev.ExtraArg.new("--mbr=n", "")] -+ - def _clean_up(self): - try: - utils.delete_lio_device(self.loop_dev) -@@ -120,7 +139,10 @@ def test_generic_wipe(self): - - # vfat has multiple signatures on the device so it allows us to test the - # 'all' argument of fs_wipe() -- ret = run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) -+ if self._vfat_version >= LooseVersion("4.2"): -+ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1 --mbr=n" % self.loop_dev) -+ else: -+ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) - self.assertEqual(ret, 0) - - time.sleep(0.5) -@@ -142,7 +164,10 @@ def test_generic_wipe(self): - self.assertEqual(fs_type, b"") - - # now do the wipe all in a one step -- ret = run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) -+ if self._vfat_version >= LooseVersion("4.2"): -+ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1 --mbr=n" % self.loop_dev) -+ else: -+ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) - self.assertEqual(ret, 0) - - succ = BlockDev.fs_wipe(self.loop_dev, True) -@@ -197,7 +222,10 @@ def test_clean(self): - - # vfat has multiple signatures on the device so it allows us to test - # that clean removes all signatures -- ret = run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) -+ if self._vfat_version >= LooseVersion("4.2"): -+ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1 --mbr=n" % self.loop_dev) -+ else: -+ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) - self.assertEqual(ret, 0) - - time.sleep(0.5) -@@ -744,9 +772,9 @@ def test_vfat_mkfs(self): - """Verify that it is possible to create a new vfat file system""" - - with self.assertRaises(GLib.GError): -- BlockDev.fs_vfat_mkfs("/non/existing/device", None) -+ BlockDev.fs_vfat_mkfs("/non/existing/device", self._mkfs_options) - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - # just try if we can mount the file system -@@ -764,7 +792,10 @@ def test_vfat_mkfs_with_label(self): - """Verify that it is possible to create an vfat file system with label""" - - ea = BlockDev.ExtraArg.new("-n", "TEST_LABEL") -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, [ea]) -+ if self._mkfs_options: -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, [ea] + self._mkfs_options) -+ else: -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, [ea]) - self.assertTrue(succ) - - fi = BlockDev.fs_vfat_get_info(self.loop_dev) -@@ -775,7 +806,7 @@ class VfatTestWipe(FSTestCase): - def test_vfat_wipe(self): - """Verify that it is possible to wipe an vfat file system""" - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - succ = BlockDev.fs_vfat_wipe(self.loop_dev) -@@ -805,7 +836,7 @@ class VfatTestCheck(FSTestCase): - def test_vfat_check(self): - """Verify that it is possible to check an vfat file system""" - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - succ = BlockDev.fs_vfat_check(self.loop_dev, None) -@@ -818,7 +849,7 @@ class VfatTestRepair(FSTestCase): - def test_vfat_repair(self): - """Verify that it is possible to repair an vfat file system""" - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - succ = BlockDev.fs_vfat_repair(self.loop_dev, None) -@@ -828,7 +859,7 @@ class VfatGetInfo(FSTestCase): - def test_vfat_get_info(self): - """Verify that it is possible to get info about an vfat file system""" - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - fi = BlockDev.fs_vfat_get_info(self.loop_dev) -@@ -841,7 +872,7 @@ class VfatSetLabel(FSTestCase): - def test_vfat_set_label(self): - """Verify that it is possible to set label of an vfat file system""" - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - fi = BlockDev.fs_vfat_get_info(self.loop_dev) -@@ -870,7 +901,7 @@ class VfatResize(FSTestCase): - def test_vfat_resize(self): - """Verify that it is possible to resize an vfat file system""" - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - # shrink -@@ -999,7 +1030,7 @@ def _remove_user(self): - def test_mount(self): - """ Test basic mounting and unmounting """ - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - tmp = tempfile.mkdtemp(prefix="libblockdev.", suffix="mount_test") -@@ -1104,7 +1135,7 @@ def test_mount_fstab(self): - fstab = utils.read_file("/etc/fstab") - self.addCleanup(utils.write_file, "/etc/fstab", fstab) - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - tmp = tempfile.mkdtemp(prefix="libblockdev.", suffix="mount_fstab_test") -@@ -1139,7 +1170,7 @@ def test_mount_fstab_user(self): - fstab = utils.read_file("/etc/fstab") - self.addCleanup(utils.write_file, "/etc/fstab", fstab) - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - tmp = tempfile.mkdtemp(prefix="libblockdev.", suffix="mount_fstab_user_test") -@@ -1423,7 +1454,16 @@ def expected_size(fi): - @tag_test(TestTags.UNSTABLE) - def test_vfat_generic_resize(self): - """Test generic resize function with a vfat file system""" -- self._test_generic_resize(mkfs_function=BlockDev.fs_vfat_mkfs) -+ def mkfs_vfat(device, options=None): -+ if self._vfat_version >= LooseVersion("4.2"): -+ if options: -+ return BlockDev.fs_vfat_mkfs(device, options + [BlockDev.ExtraArg.new("--mbr=n", "")]) -+ else: -+ return BlockDev.fs_vfat_mkfs(device, [BlockDev.ExtraArg.new("--mbr=n", "")]) -+ else: -+ return BlockDev.fs_vfat_mkfs(device, options) -+ -+ self._test_generic_resize(mkfs_function=mkfs_vfat) - - def _destroy_lvm(self): - run("vgremove --yes libbd_fs_tests >/dev/null 2>&1") -@@ -1539,7 +1579,7 @@ def test_freeze_xfs(self): - def test_freeze_vfat(self): - """ Test basic freezing and un-freezing with FAT """ - -- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) -+ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) - self.assertTrue(succ) - - tmp = tempfile.mkdtemp(prefix="libblockdev.", suffix="freeze_test") diff --git a/0005-Add-workarounds-for-some-LVM-test-issues.patch b/0005-Add-workarounds-for-some-LVM-test-issues.patch deleted file mode 100644 index c41d687..0000000 --- a/0005-Add-workarounds-for-some-LVM-test-issues.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 7c31cc534f96766dd2e3427b09d0affca66b0745 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 23 Mar 2021 13:54:02 +0100 -Subject: [PATCH 1/3] tests: Do not try to remove VG before removing the VDO - pool - ---- - tests/lvm_dbus_tests.py | 6 +++--- - tests/lvm_test.py | 6 +++--- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index 8f2bb95d..b599fdd0 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -1517,14 +1517,14 @@ def setUp(self): - self.assertTrue(succ) - - def _clean_up(self): -- BlockDev.lvm_vgremove("testVDOVG") -- BlockDev.lvm_pvremove(self.loop_dev) -- - try: - BlockDev.lvm_lvremove("testVDOVG", "vdoPool", True, None) - except: - pass - -+ BlockDev.lvm_vgremove("testVDOVG") -+ BlockDev.lvm_pvremove(self.loop_dev) -+ - try: - delete_lio_device(self.loop_dev) - except RuntimeError: -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index 6f80a3ba..6c04faf9 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -1437,14 +1437,14 @@ def setUp(self): - self.assertTrue(succ) - - def _clean_up(self): -- BlockDev.lvm_vgremove("testVDOVG") -- BlockDev.lvm_pvremove(self.loop_dev) -- - try: - BlockDev.lvm_lvremove("testVDOVG", "vdoPool", True, None) - except: - pass - -+ BlockDev.lvm_vgremove("testVDOVG") -+ BlockDev.lvm_pvremove(self.loop_dev) -+ - try: - delete_lio_device(self.loop_dev) - except RuntimeError: - -From 41b9d745b8c1a33221e15683f390bae180d1e960 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 23 Mar 2021 13:59:24 +0100 -Subject: [PATCH 2/3] tests: Force remove LVM VG /dev/ entry not removed by - vgremove - -The directory is sometimes not removed. This is a known bug that -causes subsequent test cases to fail. ---- - tests/lvm_dbus_tests.py | 6 ++++++ - tests/lvm_test.py | 6 ++++++ - 2 files changed, 12 insertions(+) - -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index b599fdd0..3278716e 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -399,6 +399,9 @@ def _clean_up(self): - except: - pass - -+ # XXX remove lingering /dev entries -+ shutil.rmtree("/dev/testVG", ignore_errors=True) -+ - LvmPVonlyTestCase._clean_up(self) - - @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") -@@ -1525,6 +1528,9 @@ def _clean_up(self): - BlockDev.lvm_vgremove("testVDOVG") - BlockDev.lvm_pvremove(self.loop_dev) - -+ # XXX remove lingering /dev entries -+ shutil.rmtree("/dev/testVDOVG", ignore_errors=True) -+ - try: - delete_lio_device(self.loop_dev) - except RuntimeError: -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index 6c04faf9..d7e1f84c 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -378,6 +378,9 @@ def _clean_up(self): - except: - pass - -+ # XXX remove lingering /dev entries -+ shutil.rmtree("/dev/testVG", ignore_errors=True) -+ - LvmPVonlyTestCase._clean_up(self) - - class LvmTestVGcreateRemove(LvmPVVGTestCase): -@@ -1445,6 +1448,9 @@ def _clean_up(self): - BlockDev.lvm_vgremove("testVDOVG") - BlockDev.lvm_pvremove(self.loop_dev) - -+ # XXX remove lingering /dev entries -+ shutil.rmtree("/dev/testVDOVG", ignore_errors=True) -+ - try: - delete_lio_device(self.loop_dev) - except RuntimeError: - -From 4ecf0075cedf3a1d275d34b94ce5bb512c4e970e Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 23 Mar 2021 14:03:44 +0100 -Subject: [PATCH 3/3] tests: Tag LvmPVVGLVcachePoolCreateRemoveTestCase as - unstable - -LVM randomly fails to activate the newly created metadata LV. -Issue is reported to LVM and not yet fixed. ---- - tests/lvm_dbus_tests.py | 2 +- - tests/lvm_test.py | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index 3278716e..4882da88 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -1213,7 +1213,7 @@ def _clean_up(self): - - @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") - class LvmPVVGLVcachePoolCreateRemoveTestCase(LvmPVVGLVcachePoolTestCase): -- @tag_test(TestTags.SLOW) -+ @tag_test(TestTags.SLOW, TestTags.UNSTABLE) - def test_cache_pool_create_remove(self): - """Verify that is it possible to create and remove a cache pool""" - -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index d7e1f84c..eb94c917 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -1129,7 +1129,7 @@ def _clean_up(self): - LvmPVVGLVTestCase._clean_up(self) - - class LvmPVVGLVcachePoolCreateRemoveTestCase(LvmPVVGLVcachePoolTestCase): -- @tag_test(TestTags.SLOW) -+ @tag_test(TestTags.SLOW, TestTags.UNSTABLE) - def test_cache_pool_create_remove(self): - """Verify that is it possible to create and remove a cache pool""" - diff --git a/0006-Misc-test-fixes-backport.patch b/0006-Misc-test-fixes-backport.patch deleted file mode 100644 index 12746c5..0000000 --- a/0006-Misc-test-fixes-backport.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 77b8d17b0baf96a7a552fb8963afdbe8c3b18da7 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 2 Jun 2021 12:53:24 +0200 -Subject: [PATCH 1/4] tests: Make sure the test temp mount is always unmounted - -With try-finally the unmount function will always run even if the -test case fails. ---- - tests/fs_test.py | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/tests/fs_test.py b/tests/fs_test.py -index 2233db4f..de685b5f 100644 ---- a/tests/fs_test.py -+++ b/tests/fs_test.py -@@ -29,8 +29,10 @@ def check_output(args, ignore_retcode=True): - @contextmanager - def mounted(device, where, ro=False): - mount(device, where, ro) -- yield -- umount(where) -+ try: -+ yield -+ finally: -+ utils.umount(where) - - - def _get_dosfstools_version(): - -From aa802b6a2c9038069cfea7f821333367840a43ca Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 2 Jun 2021 13:05:17 +0200 -Subject: [PATCH 2/4] tests: Do not check that XFS shrink fails with xfsprogs - >= 5.12 - -xfsprogs 5.12 now has experimental support for shrinking, we need -more changes to support it properly so just skip this check for -now. ---- - tests/fs_test.py | 24 ++++++++++++++++++------ - 1 file changed, 18 insertions(+), 6 deletions(-) - -diff --git a/tests/fs_test.py b/tests/fs_test.py -index de685b5f..551b6a7b 100644 ---- a/tests/fs_test.py -+++ b/tests/fs_test.py -@@ -44,6 +44,14 @@ def _get_dosfstools_version(): - return LooseVersion(m.groups()[0]) - - -+def _get_xfs_version(): -+ _ret, out, _err = utils.run_command("mkfs.xfs -V") -+ m = re.search(r"mkfs\.xfs version ([\d\.]+)", out) -+ if not m or len(m.groups()) != 1: -+ raise RuntimeError("Failed to determine xfsprogs version from: %s" % out) -+ return LooseVersion(m.groups()[0]) -+ -+ - class FSTestCase(unittest.TestCase): - - requested_plugins = BlockDev.plugin_specs_from_names(("fs", "loop")) -@@ -736,9 +744,11 @@ def test_xfs_resize(self): - self.assertEqual(fi.block_size * fi.block_count, 50 * 1024**2) - - # (still) impossible to shrink an XFS file system -- with mounted(lv, self.mount_dir): -- with self.assertRaises(GLib.GError): -- succ = BlockDev.fs_xfs_resize(self.mount_dir, 40 * 1024**2 / fi.block_size, None) -+ xfs_version = _get_xfs_version() -+ if xfs_version < LooseVersion("5.1.12"): -+ with mounted(lv, self.mount_dir): -+ with self.assertRaises(GLib.GError): -+ succ = BlockDev.fs_resize(lv, 40 * 1024**2) - - run("lvresize -L70M libbd_fs_tests/xfs_test >/dev/null 2>&1") - # should grow -@@ -1503,9 +1513,11 @@ def test_xfs_generic_resize(self): - self.assertEqual(fi.block_size * fi.block_count, 50 * 1024**2) - - # (still) impossible to shrink an XFS file system -- with mounted(lv, self.mount_dir): -- with self.assertRaises(GLib.GError): -- succ = BlockDev.fs_resize(lv, 40 * 1024**2) -+ xfs_version = _get_xfs_version() -+ if xfs_version < LooseVersion("5.1.12"): -+ with mounted(lv, self.mount_dir): -+ with self.assertRaises(GLib.GError): -+ succ = BlockDev.fs_resize(lv, 40 * 1024**2) - - run("lvresize -L70M libbd_fs_tests/xfs_test >/dev/null 2>&1") - # should grow - -From ca01b6021cce3ea6a2318e74de408757f933d947 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 2 Jun 2021 13:06:41 +0200 -Subject: [PATCH 3/4] tests: Temporarily skip - test_snapshotcreate_lvorigin_snapshotmerge - -With LVM DBus API the lvconvert job is never finished which means -the test run never finishes in our CI. ---- - tests/skip.yml | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/tests/skip.yml b/tests/skip.yml -index 145d321d..e22e712d 100644 ---- a/tests/skip.yml -+++ b/tests/skip.yml -@@ -137,3 +137,9 @@ - - distro: "fedora" - version: ["31", "32"] - reason: "working with old-style LVM snapshots leads to deadlock in LVM tools" -+ -+- test: lvm_dbus_tests.LvmTestLVsnapshots.test_snapshotcreate_lvorigin_snapshotmerge -+ skip_on: -+ - distro: "centos" -+ version: "9" -+ reason: "snapshot merge doesn't work on CentOS 9 Stream with LVM DBus API" - -From d0c44cd3d182599433f352901796af7c403239eb Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 2 Jun 2021 13:08:09 +0200 -Subject: [PATCH 4/4] Fix skipping tests on Debian testing - -Testing now identifies itself as "Debian GNU/Linux 11 (bullseye)" -so the tests that should be skipped on testing needs to be skipped -on "11" too. ---- - tests/skip.yml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tests/skip.yml b/tests/skip.yml -index e22e712d..4134ee87 100644 ---- a/tests/skip.yml -+++ b/tests/skip.yml -@@ -37,7 +37,7 @@ - - test: fs_test.MountTest.test_mount_ntfs_ro - skip_on: - - distro: "debian" -- version: ["9", "10", "testing"] -+ version: ["9", "10", "11", "testing"] - reason: "NTFS mounting of read-only devices doesn't work as expected on Debian" - - - test: kbd_test.KbdZRAM* diff --git a/0007-lvm-devices-file-support.patch b/0007-lvm-devices-file-support.patch deleted file mode 100644 index bc7c55c..0000000 --- a/0007-lvm-devices-file-support.patch +++ /dev/null @@ -1,1908 +0,0 @@ -From e364883416785d51ff8eb132b63bd802ab0ccfe9 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 13 Jul 2021 13:22:05 +0200 -Subject: [PATCH 1/8] lvm: Allow configuring global "device filter" for LVM - commands - -Starting with 2.03.12 LVM introduces a new system for telling LVM -which devices it should use. The old device filters in config are -no longer working and we need to use either the system.devices -config file in /etc/lvm/devices (default behaviour) or specify -all allowed devices using the new --devices option. Because this -option must be specified for every call which might be incovenient -for our users, this commit introduces a new function to configure -this globally, which we already do for the --config option. ---- - src/lib/plugin_apis/lvm.api | 23 +++ - src/plugins/lvm-dbus.c | 74 ++++++++- - src/plugins/lvm.c | 97 ++++++++++-- - src/plugins/lvm.h | 4 + - tests/library_test.py | 304 ++++++++++++++++++++---------------- - tests/lvm_dbus_tests.py | 47 +++++- - tests/lvm_test.py | 50 ++++++ - tests/overrides_test.py | 23 ++- - 8 files changed, 469 insertions(+), 153 deletions(-) - -diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api -index 563c104..62f602f 100644 ---- a/src/lib/plugin_apis/lvm.api -+++ b/src/lib/plugin_apis/lvm.api -@@ -601,6 +601,7 @@ typedef enum { - BD_LVM_TECH_CACHE_CALCS, - BD_LVM_TECH_GLOB_CONF, - BD_LVM_TECH_VDO, -+ BD_LVM_TECH_DEVICES, - } BDLVMTech; - - typedef enum { -@@ -1214,6 +1215,28 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error); - */ - gchar* bd_lvm_get_global_config (GError **error); - -+/** -+ * bd_lvm_set_devices_filter: -+ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the devices filter was successfully set or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error); -+ -+/** -+ * bd_lvm_get_devices_filter: -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of -+ * the currently set LVM devices filter -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gchar** bd_lvm_get_devices_filter (GError **error); -+ - /** - * bd_lvm_cache_get_default_md_size: - * @cache_size: size of the cache to determine MD size for -diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c -index 144551f..d1726ed 100644 ---- a/src/plugins/lvm-dbus.c -+++ b/src/plugins/lvm-dbus.c -@@ -35,6 +35,8 @@ - static GMutex global_config_lock; - static gchar *global_config_str = NULL; - -+static gchar *global_devices_str = NULL; -+ - #define LVM_BUS_NAME "com.redhat.lvmdbus1" - #define LVM_OBJ_PREFIX "/com/redhat/lvmdbus1" - #define MANAGER_OBJ "/com/redhat/lvmdbus1/Manager" -@@ -247,6 +249,14 @@ static volatile guint avail_features = 0; - static volatile guint avail_module_deps = 0; - static GMutex deps_check_lock; - -+#define DEPS_LVMDEVICES 0 -+#define DEPS_LVMDEVICES_MASK (1 << DEPS_LVMDEVICES) -+#define DEPS_LAST 1 -+ -+static const UtilDep deps[DEPS_LAST] = { -+ {"lvmdevices", NULL, NULL, NULL}, -+}; -+ - #define DBUS_DEPS_LVMDBUSD 0 - #define DBUS_DEPS_LVMDBUSD_MASK (1 << DBUS_DEPS_LVMDBUSD) - #define DBUS_DEPS_LAST 1 -@@ -385,6 +395,8 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) { - return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error) && - check_features (&avail_features, FEATURES_VDO_MASK, features, FEATURES_LAST, &deps_check_lock, error) && - check_module_deps (&avail_module_deps, MODULE_DEPS_VDO_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error); -+ case BD_LVM_TECH_DEVICES: -+ return check_deps (&avail_deps, DEPS_LVMDEVICES_MASK, deps, DEPS_LAST, &deps_check_lock, error); - default: - /* everything is supported by this implementation of the plugin */ - return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error); -@@ -522,6 +534,7 @@ static gboolean unbox_params_and_add (GVariant *params, GVariantBuilder *builder - - static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, guint64 *task_id, guint64 *progress_id, gboolean lock_config, GError **error) { - GVariant *config = NULL; -+ GVariant *devices = NULL; - GVariant *param = NULL; - GVariantIter iter; - GVariantBuilder builder; -@@ -543,8 +556,8 @@ static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gch - if (lock_config) - g_mutex_lock (&global_config_lock); - -- if (global_config_str || extra_params || extra_args) { -- if (global_config_str || extra_args) { -+ if (global_config_str || global_devices_str || extra_params || extra_args) { -+ if (global_config_str || global_devices_str || extra_args) { - /* add the global config to the extra_params */ - g_variant_builder_init (&extra_builder, G_VARIANT_TYPE_DICTIONARY); - -@@ -565,6 +578,11 @@ static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gch - g_variant_builder_add (&extra_builder, "{sv}", "--config", config); - added_extra = TRUE; - } -+ if (global_devices_str) { -+ devices = g_variant_new ("s", global_devices_str); -+ g_variant_builder_add (&extra_builder, "{sv}", "--devices", devices); -+ added_extra = TRUE; -+ } - - if (added_extra) - config_extra_params = g_variant_builder_end (&extra_builder); -@@ -2651,6 +2669,58 @@ gchar* bd_lvm_get_global_config (GError **error UNUSED) { - return ret; - } - -+/** -+ * bd_lvm_set_devices_filter: -+ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the devices filter was successfully set or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) { -+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) -+ return FALSE; -+ -+ g_mutex_lock (&global_config_lock); -+ -+ /* first free the old value */ -+ g_free (global_devices_str); -+ -+ /* now store the new one */ -+ if (!devices || !(*devices)) -+ global_devices_str = NULL; -+ else -+ global_devices_str = g_strjoinv (",", (gchar **) devices); -+ -+ g_mutex_unlock (&global_config_lock); -+ return TRUE; -+} -+ -+/** -+ * bd_lvm_get_devices_filter: -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of -+ * the currently set LVM devices filter -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gchar** bd_lvm_get_devices_filter (GError **error UNUSED) { -+ gchar **ret = NULL; -+ -+ g_mutex_lock (&global_config_lock); -+ -+ if (global_devices_str) -+ ret = g_strsplit (global_devices_str, ",", -1); -+ else -+ ret = NULL; -+ -+ g_mutex_unlock (&global_config_lock); -+ -+ return ret; -+} -+ - /** - * bd_lvm_cache_get_default_md_size: - * @cache_size: size of the cache to determine MD size for -diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c -index 2be1dbd..c0d8198 100644 ---- a/src/plugins/lvm.c -+++ b/src/plugins/lvm.c -@@ -34,6 +34,8 @@ - static GMutex global_config_lock; - static gchar *global_config_str = NULL; - -+static gchar *global_devices_str = NULL; -+ - /** - * SECTION: lvm - * @short_description: plugin for operations with LVM -@@ -212,10 +214,13 @@ static GMutex deps_check_lock; - - #define DEPS_LVM 0 - #define DEPS_LVM_MASK (1 << DEPS_LVM) --#define DEPS_LAST 1 -+#define DEPS_LVMDEVICES 1 -+#define DEPS_LVMDEVICES_MASK (1 << DEPS_LVMDEVICES) -+#define DEPS_LAST 2 - - static const UtilDep deps[DEPS_LAST] = { - {"lvm", LVM_MIN_VERSION, "version", "LVM version:\\s+([\\d\\.]+)"}, -+ {"lvmdevices", NULL, NULL, NULL}, - }; - - #define FEATURES_VDO 0 -@@ -327,6 +332,8 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) { - case BD_LVM_TECH_VDO: - return check_features (&avail_features, FEATURES_VDO_MASK, features, FEATURES_LAST, &deps_check_lock, error) && - check_module_deps (&avail_module_deps, MODULE_DEPS_VDO_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error); -+ case BD_LVM_TECH_DEVICES: -+ return check_deps (&avail_deps, DEPS_LVMDEVICES_MASK, deps, DEPS_LAST, &deps_check_lock, error); - default: - /* everything is supported by this implementation of the plugin */ - return check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error); -@@ -337,6 +344,8 @@ static gboolean call_lvm_and_report_error (const gchar **args, const BDExtraArg - gboolean success = FALSE; - guint i = 0; - guint args_length = g_strv_length ((gchar **) args); -+ g_autofree gchar *config_arg = NULL; -+ g_autofree gchar *devices_arg = NULL; - - if (!check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; -@@ -345,20 +354,26 @@ static gboolean call_lvm_and_report_error (const gchar **args, const BDExtraArg - if (lock_config) - g_mutex_lock (&global_config_lock); - -- /* allocate enough space for the args plus "lvm", "--config" and NULL */ -- const gchar **argv = g_new0 (const gchar*, args_length + 3); -+ /* allocate enough space for the args plus "lvm", "--config", "--devices" and NULL */ -+ const gchar **argv = g_new0 (const gchar*, args_length + 4); - - /* construct argv from args with "lvm" prepended */ - argv[0] = "lvm"; - for (i=0; i < args_length; i++) - argv[i+1] = args[i]; -- argv[args_length + 1] = global_config_str ? g_strdup_printf("--config=%s", global_config_str) : NULL; -- argv[args_length + 2] = NULL; -+ if (global_config_str) { -+ config_arg = g_strdup_printf("--config=%s", global_config_str); -+ argv[++args_length] = config_arg; -+ } -+ if (global_devices_str) { -+ devices_arg = g_strdup_printf("--devices=%s", global_devices_str); -+ argv[++args_length] = devices_arg; -+ } -+ argv[++args_length] = NULL; - - success = bd_utils_exec_and_report_error (argv, extra, error); - if (lock_config) - g_mutex_unlock (&global_config_lock); -- g_free ((gchar *) argv[args_length + 1]); - g_free (argv); - - return success; -@@ -368,6 +383,8 @@ static gboolean call_lvm_and_capture_output (const gchar **args, const BDExtraAr - gboolean success = FALSE; - guint i = 0; - guint args_length = g_strv_length ((gchar **) args); -+ g_autofree gchar *config_arg = NULL; -+ g_autofree gchar *devices_arg = NULL; - - if (!check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error)) - return FALSE; -@@ -375,19 +392,25 @@ static gboolean call_lvm_and_capture_output (const gchar **args, const BDExtraAr - /* don't allow global config string changes during the run */ - g_mutex_lock (&global_config_lock); - -- /* allocate enough space for the args plus "lvm", "--config" and NULL */ -- const gchar **argv = g_new0 (const gchar*, args_length + 3); -+ /* allocate enough space for the args plus "lvm", "--config", "--devices" and NULL */ -+ const gchar **argv = g_new0 (const gchar*, args_length + 4); - - /* construct argv from args with "lvm" prepended */ - argv[0] = "lvm"; - for (i=0; i < args_length; i++) - argv[i+1] = args[i]; -- argv[args_length + 1] = global_config_str ? g_strdup_printf("--config=%s", global_config_str) : NULL; -- argv[args_length + 2] = NULL; -+ if (global_config_str) { -+ config_arg = g_strdup_printf("--config=%s", global_config_str); -+ argv[++args_length] = config_arg; -+ } -+ if (global_devices_str) { -+ devices_arg = g_strdup_printf("--devices=%s", global_devices_str); -+ argv[++args_length] = devices_arg; -+ } -+ argv[++args_length] = NULL; - - success = bd_utils_exec_and_capture_output (argv, extra, output, error); - g_mutex_unlock (&global_config_lock); -- g_free ((gchar *) argv[args_length + 1]); - g_free (argv); - - return success; -@@ -2018,6 +2041,58 @@ gchar* bd_lvm_get_global_config (GError **error UNUSED) { - return ret; - } - -+/** -+ * bd_lvm_set_devices_filter: -+ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the devices filter was successfully set or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) { -+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) -+ return FALSE; -+ -+ g_mutex_lock (&global_config_lock); -+ -+ /* first free the old value */ -+ g_free (global_devices_str); -+ -+ /* now store the new one */ -+ if (!devices || !(*devices)) -+ global_devices_str = NULL; -+ else -+ global_devices_str = g_strjoinv (",", (gchar **) devices); -+ -+ g_mutex_unlock (&global_config_lock); -+ return TRUE; -+} -+ -+/** -+ * bd_lvm_get_devices_filter: -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of -+ * the currently set LVM devices filter -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gchar** bd_lvm_get_devices_filter (GError **error UNUSED) { -+ gchar **ret = NULL; -+ -+ g_mutex_lock (&global_config_lock); -+ -+ if (global_devices_str) -+ ret = g_strsplit (global_devices_str, ",", -1); -+ else -+ ret = NULL; -+ -+ g_mutex_unlock (&global_config_lock); -+ -+ return ret; -+} -+ - /** - * bd_lvm_cache_get_default_md_size: - * @cache_size: size of the cache to determine MD size for -diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h -index 2162d76..8063693 100644 ---- a/src/plugins/lvm.h -+++ b/src/plugins/lvm.h -@@ -216,6 +216,7 @@ typedef enum { - BD_LVM_TECH_CACHE_CALCS, - BD_LVM_TECH_GLOB_CONF, - BD_LVM_TECH_VDO, -+ BD_LVM_TECH_DEVICES, - } BDLVMTech; - - typedef enum { -@@ -289,6 +290,9 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name - gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error); - gchar* bd_lvm_get_global_config (GError **error); - -+gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error); -+gchar** bd_lvm_get_devices_filter (GError **error); -+ - guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error); - const gchar* bd_lvm_cache_get_mode_str (BDLVMCacheMode mode, GError **error); - BDLVMCacheMode bd_lvm_cache_get_mode_from_str (const gchar *mode_str, GError **error); -diff --git a/tests/library_test.py b/tests/library_test.py -index 08e44fd..efd17bd 100644 ---- a/tests/library_test.py -+++ b/tests/library_test.py -@@ -13,18 +13,178 @@ class LibraryOpsTestCase(unittest.TestCase): - # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all - # the dependencies on CentOS/Debian and we don't need them for this test - requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "dm", -- "kbd", "loop", "lvm", -+ "kbd", "loop", - "mdraid", "part", "swap")) - -+ @classmethod -+ def setUpClass(cls): -+ if not BlockDev.is_initialized(): -+ BlockDev.init(cls.requested_plugins, None) -+ else: -+ BlockDev.reinit(cls.requested_plugins, True, None) -+ -+ @classmethod -+ def tearDownClass(cls): -+ BlockDev.switch_init_checks(True) -+ -+ def my_log_func(self, level, msg): -+ # not much to verify here -+ self.assertTrue(isinstance(level, int)) -+ self.assertTrue(isinstance(msg, str)) -+ -+ self.log += msg + "\n" -+ -+ @tag_test(TestTags.CORE) -+ def test_logging_setup(self): -+ """Verify that setting up logging works as expected""" -+ -+ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self.my_log_func)) -+ -+ succ = BlockDev.utils_exec_and_report_error(["true"]) -+ self.assertTrue(succ) -+ -+ # reinit with no logging function should change nothing about logging -+ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, None)) -+ -+ succ, out = BlockDev.utils_exec_and_capture_output(["echo", "hi"]) -+ self.assertTrue(succ) -+ self.assertEqual(out, "hi\n") -+ -+ match = re.search(r'Running \[(\d+)\] true', self.log) -+ self.assertIsNot(match, None) -+ task_id1 = match.group(1) -+ match = re.search(r'Running \[(\d+)\] echo hi', self.log) -+ self.assertIsNot(match, None) -+ task_id2 = match.group(1) -+ -+ self.assertIn("...done [%s] (exit code: 0)" % task_id1, self.log) -+ self.assertIn("stdout[%s]:" % task_id1, self.log) -+ self.assertIn("stderr[%s]:" % task_id1, self.log) -+ -+ self.assertIn("stdout[%s]: hi" % task_id2, self.log) -+ self.assertIn("stderr[%s]:" % task_id2, self.log) -+ self.assertIn("...done [%s] (exit code: 0)" % task_id2, self.log) -+ -+ @tag_test(TestTags.CORE) -+ def test_require_plugins(self): -+ """Verify that loading only required plugins works as expected""" -+ -+ ps = BlockDev.PluginSpec() -+ ps.name = BlockDev.Plugin.SWAP -+ ps.so_name = "" -+ self.assertTrue(BlockDev.reinit([ps], True, None)) -+ self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) -+ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -+ -+ @tag_test(TestTags.CORE) -+ def test_not_implemented(self): -+ """Verify that unloaded/unimplemented functions report errors""" -+ -+ # should be loaded and working -+ self.assertTrue(BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236")) -+ -+ ps = BlockDev.PluginSpec() -+ ps.name = BlockDev.Plugin.SWAP -+ ps.so_name = "" -+ self.assertTrue(BlockDev.reinit([ps], True, None)) -+ self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) -+ -+ # no longer loaded -+ with self.assertRaises(GLib.GError): -+ BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") -+ -+ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -+ -+ # loaded again -+ self.assertTrue(BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236")) -+ -+ def test_ensure_init(self): -+ """Verify that ensure_init just returns when already initialized""" -+ -+ # the library is already initialized, ensure_init() shonuld do nothing -+ avail_plugs = BlockDev.get_available_plugin_names() -+ self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) -+ self.assertEqual(avail_plugs, BlockDev.get_available_plugin_names()) -+ -+ # reinit with a subset of plugins -+ plugins = BlockDev.plugin_specs_from_names(["swap", "part"]) -+ self.assertTrue(BlockDev.reinit(plugins, True, None)) -+ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part"])) -+ -+ # ensure_init with the same subset -> nothing should change -+ self.assertTrue(BlockDev.ensure_init(plugins, None)) -+ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part"])) -+ -+ # ensure_init with more plugins -> extra plugins should be loaded -+ plugins = BlockDev.plugin_specs_from_names(["swap", "part", "crypto"]) -+ self.assertTrue(BlockDev.ensure_init(plugins, None)) -+ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part", "crypto"])) -+ -+ # reinit to unload all plugins -+ self.assertTrue(BlockDev.reinit([], True, None)) -+ self.assertEqual(BlockDev.get_available_plugin_names(), []) -+ -+ # ensure_init to load all plugins back -+ self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) -+ self.assertGreaterEqual(len(BlockDev.get_available_plugin_names()), 7) -+ -+ def test_try_reinit(self): -+ """Verify that try_reinit() works as expected""" -+ -+ # try reinitializing with only some utilities being available and thus -+ # only some plugins able to load -+ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "swaplabel"]): -+ succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None) -+ self.assertFalse(succ) -+ for plug_name in ("swap", "crypto"): -+ self.assertIn(plug_name, loaded) -+ -+ # reset back to all plugins -+ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -+ -+ # now the same with a subset of plugins requested -+ plugins = BlockDev.plugin_specs_from_names(["swap", "crypto"]) -+ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "swaplabel"]): -+ succ, loaded = BlockDev.try_reinit(plugins, True, None) -+ self.assertTrue(succ) -+ self.assertEqual(set(loaded), set(["swap", "crypto"])) -+ -+ def test_non_en_init(self): -+ """Verify that the library initializes with lang different from en_US""" -+ -+ orig_lang = os.environ.get("LANG") -+ os.environ["LANG"] = "cs.CZ_UTF-8" -+ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -+ if orig_lang: -+ os.environ["LANG"] = orig_lang -+ else: -+ del os.environ["LANG"] -+ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -+ -+ -+class PluginsTestCase(unittest.TestCase): -+ # only LVM plugin for this test -+ requested_plugins = BlockDev.plugin_specs_from_names(("lvm",)) -+ - orig_config_dir = "" - - @classmethod - def setUpClass(cls): -+ BlockDev.switch_init_checks(False) - if not BlockDev.is_initialized(): - BlockDev.init(cls.requested_plugins, None) - else: - BlockDev.reinit(cls.requested_plugins, True, None) - -+ try: -+ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) -+ except: -+ cls.devices_avail = False -+ -+ @classmethod -+ def tearDownClass(cls): -+ BlockDev.switch_init_checks(True) -+ - def setUp(self): - self.orig_config_dir = os.environ.get("LIBBLOCKDEV_CONFIG_DIR", "") - self.addCleanup(self._clean_up) -@@ -185,6 +345,12 @@ class LibraryOpsTestCase(unittest.TestCase): - def test_plugin_fallback(self): - """Verify that fallback when loading plugins works as expected""" - -+ if not self.devices_avail: -+ self.skipTest("skipping plugin fallback test: missing some LVM dependencies") -+ -+ BlockDev.switch_init_checks(True) -+ self.addCleanup(BlockDev.switch_init_checks, False) -+ - # library should be successfully initialized - self.assertTrue(BlockDev.is_initialized()) - -@@ -206,7 +372,7 @@ class LibraryOpsTestCase(unittest.TestCase): - - # now reinit the library with the config preferring the new build - orig_conf_dir = os.environ.get("LIBBLOCKDEV_CONFIG_DIR") -- os.environ["LIBBLOCKDEV_CONFIG_DIR"] = "tests/plugin_prio_conf.d" -+ os.environ["LIBBLOCKDEV_CONFIG_DIR"] = "tests/test_configs/plugin_prio_conf.d" - self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) - - # the original plugin should be loaded because the new one should fail -@@ -243,139 +409,9 @@ class LibraryOpsTestCase(unittest.TestCase): - - self.assertEqual(BlockDev.lvm_get_max_lv_size(), orig_max_size) - -- def my_log_func(self, level, msg): -- # not much to verify here -- self.assertTrue(isinstance(level, int)) -- self.assertTrue(isinstance(msg, str)) -- -- self.log += msg + "\n" -- -- @tag_test(TestTags.CORE) -- def test_logging_setup(self): -- """Verify that setting up logging works as expected""" -- -- self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self.my_log_func)) -- -- succ = BlockDev.utils_exec_and_report_error(["true"]) -- self.assertTrue(succ) -- -- # reinit with no logging function should change nothing about logging -- self.assertTrue(BlockDev.reinit(self.requested_plugins, False, None)) -- -- succ, out = BlockDev.utils_exec_and_capture_output(["echo", "hi"]) -- self.assertTrue(succ) -- self.assertEqual(out, "hi\n") -- -- match = re.search(r'Running \[(\d+)\] true', self.log) -- self.assertIsNot(match, None) -- task_id1 = match.group(1) -- match = re.search(r'Running \[(\d+)\] echo hi', self.log) -- self.assertIsNot(match, None) -- task_id2 = match.group(1) -- -- self.assertIn("...done [%s] (exit code: 0)" % task_id1, self.log) -- self.assertIn("stdout[%s]:" % task_id1, self.log) -- self.assertIn("stderr[%s]:" % task_id1, self.log) -- -- self.assertIn("stdout[%s]: hi" % task_id2, self.log) -- self.assertIn("stderr[%s]:" % task_id2, self.log) -- self.assertIn("...done [%s] (exit code: 0)" % task_id2, self.log) -- -- @tag_test(TestTags.CORE) -- def test_require_plugins(self): -- """Verify that loading only required plugins works as expected""" -- -- ps = BlockDev.PluginSpec() -- ps.name = BlockDev.Plugin.SWAP -- ps.so_name = "" -- self.assertTrue(BlockDev.reinit([ps], True, None)) -- self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) -- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -- -- @tag_test(TestTags.CORE) -- def test_not_implemented(self): -- """Verify that unloaded/unimplemented functions report errors""" -- -- # should be loaded and working -- self.assertTrue(BlockDev.lvm_get_max_lv_size() > 0) - -- ps = BlockDev.PluginSpec() -- ps.name = BlockDev.Plugin.SWAP -- ps.so_name = "" -- self.assertTrue(BlockDev.reinit([ps], True, None)) -- self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) -- -- # no longer loaded -- with self.assertRaises(GLib.GError): -- BlockDev.lvm_get_max_lv_size() -- -- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -- -- # loaded again -- self.assertTrue(BlockDev.lvm_get_max_lv_size() > 0) -- -- def test_ensure_init(self): -- """Verify that ensure_init just returns when already initialized""" -- -- # the library is already initialized, ensure_init() shonuld do nothing -- avail_plugs = BlockDev.get_available_plugin_names() -- self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) -- self.assertEqual(avail_plugs, BlockDev.get_available_plugin_names()) -- -- # reinit with a subset of plugins -- plugins = BlockDev.plugin_specs_from_names(["swap", "lvm"]) -- self.assertTrue(BlockDev.reinit(plugins, True, None)) -- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm"])) -- -- # ensure_init with the same subset -> nothing should change -- self.assertTrue(BlockDev.ensure_init(plugins, None)) -- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm"])) -- -- # ensure_init with more plugins -> extra plugins should be loaded -- plugins = BlockDev.plugin_specs_from_names(["swap", "lvm", "crypto"]) -- self.assertTrue(BlockDev.ensure_init(plugins, None)) -- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm", "crypto"])) -- -- # reinit to unload all plugins -- self.assertTrue(BlockDev.reinit([], True, None)) -- self.assertEqual(BlockDev.get_available_plugin_names(), []) -- -- # ensure_init to load all plugins back -- self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) -- self.assertGreaterEqual(len(BlockDev.get_available_plugin_names()), 8) -- -- def test_try_reinit(self): -- """Verify that try_reinit() works as expected""" -- -- # try reinitializing with only some utilities being available and thus -- # only some plugins able to load -- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", "swaplabel"]): -- succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None) -- self.assertFalse(succ) -- for plug_name in ("swap", "lvm", "crypto"): -- self.assertIn(plug_name, loaded) -- -- # reset back to all plugins -- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -- -- # now the same with a subset of plugins requested -- plugins = BlockDev.plugin_specs_from_names(["lvm", "swap", "crypto"]) -- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm","swaplabel"]): -- succ, loaded = BlockDev.try_reinit(plugins, True, None) -- self.assertTrue(succ) -- self.assertEqual(set(loaded), set(["swap", "lvm", "crypto"])) -- -- def test_non_en_init(self): -- """Verify that the library initializes with lang different from en_US""" -- -- orig_lang = os.environ.get("LANG") -- os.environ["LANG"] = "cs.CZ_UTF-8" -- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -- if orig_lang: -- os.environ["LANG"] = orig_lang -- else: -- del os.environ["LANG"] -- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -+class DepChecksTestCase(unittest.TestCase): -+ requested_plugins = BlockDev.plugin_specs_from_names(( "swap",)) - - def test_dep_checks_disabled(self): - """Verify that disabling runtime dep checks works""" -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index 4882da8..35ace37 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -33,6 +33,11 @@ class LVMTestCase(unittest.TestCase): - else: - BlockDev.reinit([cls.ps, cls.ps2], True, None) - -+ try: -+ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) -+ except: -+ cls.devices_avail = False -+ - @classmethod - def _get_lvm_version(cls): - _ret, out, _err = run_command("lvm version") -@@ -44,8 +49,7 @@ class LVMTestCase(unittest.TestCase): - @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") - class LvmNoDevTestCase(LVMTestCase): - -- def __init__(self, *args, **kwargs): -- super(LvmNoDevTestCase, self).__init__(*args, **kwargs) -+ def setUp(self): - self._log = "" - - @tag_test(TestTags.NOSTORAGE) -@@ -227,6 +231,45 @@ class LvmNoDevTestCase(LVMTestCase): - succ = BlockDev.lvm_set_global_config(None) - self.assertTrue(succ) - -+ @tag_test(TestTags.NOSTORAGE) -+ def test_get_set_global_devices_filter(self): -+ """Verify that getting and setting LVM devices filter works as expected""" -+ if not self.devices_avail: -+ self.skipTest("skipping LVM devices filter test: not supported") -+ -+ # setup logging -+ self.assertTrue(BlockDev.reinit([self.ps], False, self._store_log)) -+ -+ # no global config set initially -+ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) -+ -+ # set and try to get back -+ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) -+ self.assertTrue(succ) -+ self.assertListEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sda"]) -+ -+ # reset and try to get back -+ succ = BlockDev.lvm_set_devices_filter(None) -+ self.assertTrue(succ) -+ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) -+ -+ # set twice and try to get back twice -+ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) -+ self.assertTrue(succ) -+ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb"]) -+ self.assertTrue(succ) -+ self.assertEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sdb"]) -+ -+ # set something sane and check it's really used -+ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb", "/dev/sdc"]) -+ BlockDev.lvm_pvscan() -+ self.assertIn("'--devices'", self._log) -+ self.assertIn("'/dev/sdb,/dev/sdc'", self._log) -+ -+ # reset back to default -+ succ = BlockDev.lvm_set_devices_filter(None) -+ self.assertTrue(succ) -+ - @tag_test(TestTags.NOSTORAGE) - def test_cache_get_default_md_size(self): - """Verify that default cache metadata size is calculated properly""" -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index eb94c91..b37a879 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -22,10 +22,17 @@ class LVMTestCase(unittest.TestCase): - ps.so_name = "libbd_lvm.so.2" - cls.requested_plugins = [ps] - -+ BlockDev.switch_init_checks(False) - if not BlockDev.is_initialized(): - BlockDev.init(cls.requested_plugins, None) - else: - BlockDev.reinit(cls.requested_plugins, True, None) -+ BlockDev.switch_init_checks(True) -+ -+ try: -+ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) -+ except: -+ cls.devices_avail = False - - @classmethod - def _get_lvm_version(cls): -@@ -39,6 +46,8 @@ class LVMTestCase(unittest.TestCase): - class LvmNoDevTestCase(LVMTestCase): - def __init__(self, *args, **kwargs): - super(LvmNoDevTestCase, self).__init__(*args, **kwargs) -+ -+ def setUp(self): - self._log = "" - - @tag_test(TestTags.NOSTORAGE) -@@ -213,6 +222,44 @@ class LvmNoDevTestCase(LVMTestCase): - succ = BlockDev.lvm_set_global_config(None) - self.assertTrue(succ) - -+ @tag_test(TestTags.NOSTORAGE) -+ def test_get_set_global_devices_filter(self): -+ """Verify that getting and setting LVM devices filter works as expected""" -+ if not self.devices_avail: -+ self.skipTest("skipping LVM devices filter test: not supported") -+ -+ # setup logging -+ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self._store_log)) -+ -+ # no global config set initially -+ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) -+ -+ # set and try to get back -+ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) -+ self.assertTrue(succ) -+ self.assertListEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sda"]) -+ -+ # reset and try to get back -+ succ = BlockDev.lvm_set_devices_filter(None) -+ self.assertTrue(succ) -+ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) -+ -+ # set twice and try to get back twice -+ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) -+ self.assertTrue(succ) -+ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb"]) -+ self.assertTrue(succ) -+ self.assertEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sdb"]) -+ -+ # set something sane and check it's really used -+ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb", "/dev/sdc"]) -+ BlockDev.lvm_lvs(None) -+ self.assertIn("--devices=/dev/sdb,/dev/sdc", self._log) -+ -+ # reset back to default -+ succ = BlockDev.lvm_set_devices_filter(None) -+ self.assertTrue(succ) -+ - @tag_test(TestTags.NOSTORAGE) - def test_cache_get_default_md_size(self): - """Verify that default cache metadata size is calculated properly""" -@@ -1335,6 +1382,9 @@ class LvmPVVGcachedThpoolstatsTestCase(LvmPVVGLVTestCase): - - class LVMUnloadTest(LVMTestCase): - def setUp(self): -+ if not self.devices_avail: -+ self.skipTest("skipping LVM unload test: missing some LVM dependencies") -+ - # make sure the library is initialized with all plugins loaded for other - # tests - self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None) -diff --git a/tests/overrides_test.py b/tests/overrides_test.py -index 8e7f5a5..d3faf3c 100644 ---- a/tests/overrides_test.py -+++ b/tests/overrides_test.py -@@ -15,10 +15,12 @@ class OverridesTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): -+ BlockDev.switch_init_checks(False) - if not BlockDev.is_initialized(): - BlockDev.init(cls.requested_plugins, None) - else: - BlockDev.reinit(cls.requested_plugins, True, None) -+ BlockDev.switch_init_checks(True) - - class OverridesTestCase(OverridesTest): - @tag_test(TestTags.NOSTORAGE, TestTags.CORE) -@@ -65,7 +67,20 @@ class OverridesTestCase(OverridesTest): - self.assertEqual(BlockDev.lvm_get_thpool_padding(11 * 1024**2), - expected_padding) - --class OverridesUnloadTestCase(OverridesTest): -+class OverridesUnloadTestCase(unittest.TestCase): -+ # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all -+ # the dependencies on CentOS/Debian and we don't need them for this test -+ requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "dm", -+ "kbd", "loop", -+ "mdraid", "part", "swap")) -+ -+ @classmethod -+ def setUpClass(cls): -+ if not BlockDev.is_initialized(): -+ BlockDev.init(cls.requested_plugins, None) -+ else: -+ BlockDev.reinit(cls.requested_plugins, True, None) -+ - def tearDown(self): - # make sure the library is initialized with all plugins loaded for other - # tests -@@ -80,7 +95,7 @@ class OverridesUnloadTestCase(OverridesTest): - - # no longer loaded - with self.assertRaises(BlockDev.BlockDevNotImplementedError): -- BlockDev.lvm.get_max_lv_size() -+ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") - - # load the plugins back - self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) -@@ -92,9 +107,9 @@ class OverridesUnloadTestCase(OverridesTest): - - # the exception should be properly inherited from two classes - with self.assertRaises(NotImplementedError): -- BlockDev.lvm.get_max_lv_size() -+ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") - with self.assertRaises(BlockDev.BlockDevError): -- BlockDev.lvm.get_max_lv_size() -+ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") - - # load the plugins back - self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) --- -2.31.1 - - -From bebd74962db6fb7b5314be411a4d02b21554d80f Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 13 Jul 2021 13:27:32 +0200 -Subject: [PATCH 2/8] lvm: Add functions for managing LVM devices file - -Currently covers only --adddev and --deldev from the lvmdevices -command. ---- - src/lib/plugin_apis/lvm.api | 26 +++++++++++++++ - src/plugins/lvm-dbus.c | 52 +++++++++++++++++++++++++++++ - src/plugins/lvm.c | 52 +++++++++++++++++++++++++++++ - src/plugins/lvm.h | 3 ++ - src/python/gi/overrides/BlockDev.py | 15 +++++++++ - tests/lvm_dbus_tests.py | 37 +++++++++++++++++++- - tests/lvm_test.py | 37 +++++++++++++++++++- - 7 files changed, 220 insertions(+), 2 deletions(-) - -diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api -index 62f602f..bce2920 100644 ---- a/src/lib/plugin_apis/lvm.api -+++ b/src/lib/plugin_apis/lvm.api -@@ -1685,4 +1685,30 @@ GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_n - */ - BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error); - -+/** -+ * bd_lvm_devices_add: -+ * @device: device (PV) to add to the devices file -+ * @devices_file: (allow-none): LVM devices file or %NULL for default -+ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the @device was successfully added to @devices_file or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); -+ -+/** -+ * bd_lvm_devices_delete: -+ * @device: device (PV) to delete from the devices file -+ * @devices_file: (allow-none): LVM devices file or %NULL for default -+ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the @device was successfully removed from @devices_file or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); -+ - #endif /* BD_LVM_API */ -diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c -index d1726ed..44d2794 100644 ---- a/src/plugins/lvm-dbus.c -+++ b/src/plugins/lvm-dbus.c -@@ -3938,3 +3938,55 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam - - return stats; - } -+ -+/** -+ * bd_lvm_devices_add: -+ * @device: device (PV) to add to the devices file -+ * @devices_file: (allow-none): LVM devices file or %NULL for default -+ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the @device was successfully added to @devices_file or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { -+ const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL}; -+ g_autofree gchar *devfile = NULL; -+ -+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) -+ return FALSE; -+ -+ if (devices_file) { -+ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); -+ args[3] = devfile; -+ } -+ -+ return bd_utils_exec_and_report_error (args, extra, error); -+} -+ -+/** -+ * bd_lvm_devices_delete: -+ * @device: device (PV) to delete from the devices file -+ * @devices_file: (allow-none): LVM devices file or %NULL for default -+ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the @device was successfully removed from @devices_file or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { -+ const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL}; -+ g_autofree gchar *devfile = NULL; -+ -+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) -+ return FALSE; -+ -+ if (devices_file) { -+ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); -+ args[3] = devfile; -+ } -+ -+ return bd_utils_exec_and_report_error (args, extra, error); -+} -diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c -index c0d8198..94c6a22 100644 ---- a/src/plugins/lvm.c -+++ b/src/plugins/lvm.c -@@ -3235,3 +3235,55 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam - - return stats; - } -+ -+/** -+ * bd_lvm_devices_add: -+ * @device: device (PV) to add to the devices file -+ * @devices_file: (allow-none): LVM devices file or %NULL for default -+ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the @device was successfully added to @devices_file or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { -+ const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL}; -+ g_autofree gchar *devfile = NULL; -+ -+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) -+ return FALSE; -+ -+ if (devices_file) { -+ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); -+ args[3] = devfile; -+ } -+ -+ return bd_utils_exec_and_report_error (args, extra, error); -+} -+ -+/** -+ * bd_lvm_devices_delete: -+ * @device: device (PV) to delete from the devices file -+ * @devices_file: (allow-none): LVM devices file or %NULL for default -+ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the @device was successfully removed from @devices_file or not -+ * -+ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) -+ */ -+gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { -+ const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL}; -+ g_autofree gchar *devfile = NULL; -+ -+ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) -+ return FALSE; -+ -+ if (devices_file) { -+ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); -+ args[3] = devfile; -+ } -+ -+ return bd_utils_exec_and_report_error (args, extra, error); -+} -diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h -index 8063693..5ca2a9d 100644 ---- a/src/plugins/lvm.h -+++ b/src/plugins/lvm.h -@@ -333,4 +333,7 @@ BDLVMVDOWritePolicy bd_lvm_get_vdo_write_policy_from_str (const gchar *policy_st - BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error); - GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_name, GError **error); - -+gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); -+gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); -+ - #endif /* BD_LVM */ -diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py -index f768c8b..715a262 100644 ---- a/src/python/gi/overrides/BlockDev.py -+++ b/src/python/gi/overrides/BlockDev.py -@@ -724,6 +724,21 @@ def lvm_vdo_pool_convert(vg_name, lv_name, pool_name, virtual_size, index_memory - return _lvm_vdo_pool_convert(vg_name, lv_name, pool_name, virtual_size, index_memory, compression, deduplication, write_policy, extra) - __all__.append("lvm_vdo_pool_convert") - -+_lvm_devices_add = BlockDev.lvm_devices_add -+@override(BlockDev.lvm_devices_add) -+def lvm_devices_add(device, devices_file=None, extra=None, **kwargs): -+ extra = _get_extra(extra, kwargs) -+ return _lvm_devices_add(device, devices_file, extra) -+__all__.append("lvm_devices_add") -+ -+_lvm_devices_delete = BlockDev.lvm_devices_delete -+@override(BlockDev.lvm_devices_delete) -+def lvm_devices_delete(device, devices_file=None, extra=None, **kwargs): -+ extra = _get_extra(extra, kwargs) -+ return _lvm_devices_delete(device, devices_file, extra) -+__all__.append("lvm_devices_delete") -+ -+ - _md_get_superblock_size = BlockDev.md_get_superblock_size - @override(BlockDev.md_get_superblock_size) - def md_get_superblock_size(size, version=None): -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index 35ace37..fb1a9ed 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -10,7 +10,7 @@ import subprocess - from distutils.version import LooseVersion - from itertools import chain - --from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test -+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test, read_file - from gi.repository import BlockDev, GLib - - import dbus -@@ -1696,3 +1696,38 @@ class LVMVDOTest(LVMTestCase): - - full_stats = BlockDev.lvm_vdo_get_stats_full("testVDOVG", "vdoPool") - self.assertIn("writeAmplificationRatio", full_stats.keys()) -+ -+ -+class LvmTestDevicesFile(LvmPVonlyTestCase): -+ devicefile = "bd_lvm_dbus_tests.devices" -+ -+ @classmethod -+ def tearDownClass(cls): -+ shutil.rmtree("/etc/lvm/devices/" + cls.devicefile, ignore_errors=True) -+ -+ super(LvmTestDevicesFile, cls).tearDownClass() -+ -+ def test_devices_add_delete(self): -+ if not self.devices_avail: -+ self.skipTest("skipping LVM devices file test: not supported") -+ -+ succ = BlockDev.lvm_pvcreate(self.loop_dev) -+ self.assertTrue(succ) -+ -+ with self.assertRaises(GLib.GError): -+ BlockDev.lvm_devices_add("/non/existing/device", self.devicefile) -+ -+ with self.assertRaises(GLib.GError): -+ BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) -+ -+ succ = BlockDev.lvm_devices_add(self.loop_dev, self.devicefile) -+ self.assertTrue(succ) -+ -+ dfile = read_file("/etc/lvm/devices/" + self.devicefile) -+ self.assertIn(self.loop_dev, dfile) -+ -+ succ = BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) -+ self.assertTrue(succ) -+ -+ dfile = read_file("/etc/lvm/devices/" + self.devicefile) -+ self.assertNotIn(self.loop_dev, dfile) -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index b37a879..786434f 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -9,7 +9,7 @@ import shutil - import subprocess - from distutils.version import LooseVersion - --from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command -+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command, read_file - from gi.repository import BlockDev, GLib - - -@@ -1682,3 +1682,38 @@ class LVMVDOTest(LVMTestCase): - - full_stats = BlockDev.lvm_vdo_get_stats_full("testVDOVG", "vdoPool") - self.assertIn("writeAmplificationRatio", full_stats.keys()) -+ -+ -+class LvmTestDevicesFile(LvmPVonlyTestCase): -+ devicefile = "bd_lvm_test.devices" -+ -+ @classmethod -+ def tearDownClass(cls): -+ shutil.rmtree("/etc/lvm/devices/" + cls.devicefile, ignore_errors=True) -+ -+ super(LvmTestDevicesFile, cls).tearDownClass() -+ -+ def test_devices_add_delete(self): -+ if not self.devices_avail: -+ self.skipTest("skipping LVM devices file test: not supported") -+ -+ succ = BlockDev.lvm_pvcreate(self.loop_dev) -+ self.assertTrue(succ) -+ -+ with self.assertRaises(GLib.GError): -+ BlockDev.lvm_devices_add("/non/existing/device", self.devicefile) -+ -+ with self.assertRaises(GLib.GError): -+ BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) -+ -+ succ = BlockDev.lvm_devices_add(self.loop_dev, self.devicefile) -+ self.assertTrue(succ) -+ -+ dfile = read_file("/etc/lvm/devices/" + self.devicefile) -+ self.assertIn(self.loop_dev, dfile) -+ -+ succ = BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) -+ self.assertTrue(succ) -+ -+ dfile = read_file("/etc/lvm/devices/" + self.devicefile) -+ self.assertNotIn(self.loop_dev, dfile) --- -2.31.1 - - -From 8d8cbe7169cb94b01e7064a0d00b7d86baf5e652 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 15 Oct 2021 13:18:54 +0200 -Subject: [PATCH 3/8] lvm: Report special error when system.devices file is not - enabled - -This can be disabled either in LVM by a compile time option or -by a lvm.conf option so we should report a specific error for this -case so users can distinguish between the feature not being enabled -and not being supported at all. ---- - src/lib/plugin_apis/lvm.api | 1 + - src/plugins/lvm-dbus.c | 70 +++++++++++++++++++++++++++++++++++++ - src/plugins/lvm.c | 60 +++++++++++++++++++++++++++++++ - src/plugins/lvm.h | 1 + - tests/lvm_dbus_tests.py | 15 ++++++++ - tests/lvm_test.py | 15 ++++++++ - 6 files changed, 162 insertions(+) - -diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api -index bce2920..b96bcfd 100644 ---- a/src/lib/plugin_apis/lvm.api -+++ b/src/lib/plugin_apis/lvm.api -@@ -44,6 +44,7 @@ typedef enum { - BD_LVM_ERROR_FAIL, - BD_LVM_ERROR_NOT_SUPPORTED, - BD_LVM_ERROR_VDO_POLICY_INVAL, -+ BD_LVM_ERROR_DEVICES_DISABLED, - } BDLVMError; - - typedef enum { -diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c -index 44d2794..22204d5 100644 ---- a/src/plugins/lvm-dbus.c -+++ b/src/plugins/lvm-dbus.c -@@ -3939,6 +3939,64 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam - return stats; - } - -+/* check whether the LVM devices file is enabled by LVM -+ * we use the existence of the "lvmdevices" command to check whether the feature is available -+ * or not, but this can still be disabled either in LVM or in lvm.conf -+ */ -+static gboolean _lvm_devices_enabled () { -+ const gchar *args[6] = {"lvmconfig", "--typeconfig", NULL, "devices/use_devicesfile", NULL, NULL}; -+ gboolean ret = FALSE; -+ GError *loc_error = NULL; -+ gchar *output = NULL; -+ gboolean enabled = FALSE; -+ gint scanned = 0; -+ g_autofree gchar *config_arg = NULL; -+ -+ /* try current config first -- if we get something from this it means the feature is -+ explicitly enabled or disabled by system lvm.conf or using the --config option */ -+ args[2] = "current"; -+ -+ /* make sure to include the global config from us when getting the current config value */ -+ g_mutex_lock (&global_config_lock); -+ if (global_config_str) { -+ config_arg = g_strdup_printf ("--config=%s", global_config_str); -+ args[4] = config_arg; -+ } -+ -+ ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error); -+ g_mutex_unlock (&global_config_lock); -+ if (ret) { -+ scanned = sscanf (output, "use_devicesfile=%u", &enabled); -+ g_free (output); -+ if (scanned != 1) -+ return FALSE; -+ -+ return enabled; -+ } else { -+ g_clear_error (&loc_error); -+ g_free (output); -+ } -+ -+ output = NULL; -+ -+ /* now try default */ -+ args[2] = "default"; -+ ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error); -+ if (ret) { -+ scanned = sscanf (output, "# use_devicesfile=%u", &enabled); -+ g_free (output); -+ if (scanned != 1) -+ return FALSE; -+ -+ return enabled; -+ } else { -+ g_clear_error (&loc_error); -+ g_free (output); -+ } -+ -+ return FALSE; -+} -+ - /** - * bd_lvm_devices_add: - * @device: device (PV) to add to the devices file -@@ -3957,6 +4015,12 @@ gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, con - if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) - return FALSE; - -+ if (!_lvm_devices_enabled ()) { -+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, -+ "LVM devices file not enabled."); -+ return FALSE; -+ } -+ - if (devices_file) { - devfile = g_strdup_printf ("--devicesfile=%s", devices_file); - args[3] = devfile; -@@ -3983,6 +4047,12 @@ gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, - if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) - return FALSE; - -+ if (!_lvm_devices_enabled ()) { -+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, -+ "LVM devices file not enabled."); -+ return FALSE; -+ } -+ - if (devices_file) { - devfile = g_strdup_printf ("--devicesfile=%s", devices_file); - args[3] = devfile; -diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c -index 94c6a22..605fcb0 100644 ---- a/src/plugins/lvm.c -+++ b/src/plugins/lvm.c -@@ -3236,6 +3236,54 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam - return stats; - } - -+/* check whether the LVM devices file is enabled by LVM -+ * we use the existence of the "lvmdevices" command to check whether the feature is available -+ * or not, but this can still be disabled either in LVM or in lvm.conf -+ */ -+static gboolean _lvm_devices_enabled () { -+ const gchar *args[5] = {"config", "--typeconfig", NULL, "devices/use_devicesfile", NULL}; -+ gboolean ret = FALSE; -+ GError *loc_error = NULL; -+ gchar *output = NULL; -+ gboolean enabled = FALSE; -+ gint scanned = 0; -+ -+ /* try current config first -- if we get something from this it means the feature is -+ explicitly enabled or disabled by system lvm.conf or using the --config option */ -+ args[2] = "current"; -+ ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); -+ if (ret) { -+ scanned = sscanf (output, "use_devicesfile=%u", &enabled); -+ g_free (output); -+ if (scanned != 1) -+ return FALSE; -+ -+ return enabled; -+ } else { -+ g_clear_error (&loc_error); -+ g_free (output); -+ } -+ -+ output = NULL; -+ -+ /* now try default */ -+ args[2] = "default"; -+ ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); -+ if (ret) { -+ scanned = sscanf (output, "# use_devicesfile=%u", &enabled); -+ g_free (output); -+ if (scanned != 1) -+ return FALSE; -+ -+ return enabled; -+ } else { -+ g_clear_error (&loc_error); -+ g_free (output); -+ } -+ -+ return FALSE; -+} -+ - /** - * bd_lvm_devices_add: - * @device: device (PV) to add to the devices file -@@ -3254,6 +3302,12 @@ gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, con - if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) - return FALSE; - -+ if (!_lvm_devices_enabled ()) { -+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, -+ "LVM devices file not enabled."); -+ return FALSE; -+ } -+ - if (devices_file) { - devfile = g_strdup_printf ("--devicesfile=%s", devices_file); - args[3] = devfile; -@@ -3280,6 +3334,12 @@ gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, - if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) - return FALSE; - -+ if (!_lvm_devices_enabled ()) { -+ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, -+ "LVM devices file not enabled."); -+ return FALSE; -+ } -+ - if (devices_file) { - devfile = g_strdup_printf ("--devicesfile=%s", devices_file); - args[3] = devfile; -diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h -index 5ca2a9d..fabf091 100644 ---- a/src/plugins/lvm.h -+++ b/src/plugins/lvm.h -@@ -53,6 +53,7 @@ typedef enum { - BD_LVM_ERROR_FAIL, - BD_LVM_ERROR_NOT_SUPPORTED, - BD_LVM_ERROR_VDO_POLICY_INVAL, -+ BD_LVM_ERROR_DEVICES_DISABLED, - } BDLVMError; - - typedef enum { -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index fb1a9ed..c411c9e 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -1731,3 +1731,18 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - - dfile = read_file("/etc/lvm/devices/" + self.devicefile) - self.assertNotIn(self.loop_dev, dfile) -+ -+ def test_devices_enabled(self): -+ if not self.devices_avail: -+ self.skipTest("skipping LVM devices file test: not supported") -+ -+ self.addCleanup(BlockDev.lvm_set_global_config, "") -+ -+ # checking if the feature is enabled or disabled is hard so lets just disable -+ # the devices file using the global config and check lvm_devices_add fails -+ # with the correct exception message -+ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=0 }") -+ self.assertTrue(succ) -+ -+ with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): -+ BlockDev.lvm_devices_add("", self.devicefile) -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index 786434f..315dd07 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -1717,3 +1717,18 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - - dfile = read_file("/etc/lvm/devices/" + self.devicefile) - self.assertNotIn(self.loop_dev, dfile) -+ -+ def test_devices_enabled(self): -+ if not self.devices_avail: -+ self.skipTest("skipping LVM devices file test: not supported") -+ -+ self.addCleanup(BlockDev.lvm_set_global_config, "") -+ -+ # checking if the feature is enabled or disabled is hard so lets just disable -+ # the devices file using the global config and check lvm_devices_add fails -+ # with the correct exception message -+ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=0 }") -+ self.assertTrue(succ) -+ -+ with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): -+ BlockDev.lvm_devices_add("", self.devicefile) --- -2.31.1 - - -From 81df85e7ea6e129e78074b6967f80c505d1b08f0 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 15 Oct 2021 14:21:03 +0200 -Subject: [PATCH 4/8] lvm: Force enable LVM devices file for LvmTestDevicesFile - -This feauture might be disabled in lvm.conf so to be able to test -it we need to override this. The correct handling of the disabled -state is checked in a separate test case. ---- - tests/lvm_dbus_tests.py | 8 ++++++++ - tests/lvm_test.py | 8 ++++++++ - 2 files changed, 16 insertions(+) - -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index c411c9e..9cfc647 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -1711,6 +1711,12 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - if not self.devices_avail: - self.skipTest("skipping LVM devices file test: not supported") - -+ self.addCleanup(BlockDev.lvm_set_global_config, "") -+ -+ # force-enable the feature, it might be disabled by default -+ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") -+ self.assertTrue(succ) -+ - succ = BlockDev.lvm_pvcreate(self.loop_dev) - self.assertTrue(succ) - -@@ -1732,6 +1738,8 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - dfile = read_file("/etc/lvm/devices/" + self.devicefile) - self.assertNotIn(self.loop_dev, dfile) - -+ BlockDev.lvm_set_global_config("") -+ - def test_devices_enabled(self): - if not self.devices_avail: - self.skipTest("skipping LVM devices file test: not supported") -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index 315dd07..ea3b7f8 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -1697,6 +1697,12 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - if not self.devices_avail: - self.skipTest("skipping LVM devices file test: not supported") - -+ self.addCleanup(BlockDev.lvm_set_global_config, "") -+ -+ # force-enable the feature, it might be disabled by default -+ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") -+ self.assertTrue(succ) -+ - succ = BlockDev.lvm_pvcreate(self.loop_dev) - self.assertTrue(succ) - -@@ -1718,6 +1724,8 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - dfile = read_file("/etc/lvm/devices/" + self.devicefile) - self.assertNotIn(self.loop_dev, dfile) - -+ BlockDev.lvm_set_global_config("") -+ - def test_devices_enabled(self): - if not self.devices_avail: - self.skipTest("skipping LVM devices file test: not supported") --- -2.31.1 - - -From 01237b62bb8ad67def7c937185c42152503fbc6f Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 12 Nov 2021 14:51:39 +0100 -Subject: [PATCH 5/8] tests: Fix resetting global LVM config after LVM devices - file test - -We need to set the config to None/NULL not to an empty string. ---- - tests/lvm_dbus_tests.py | 6 +++--- - tests/lvm_test.py | 6 +++--- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index 9cfc647..d422869 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -1711,7 +1711,7 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - if not self.devices_avail: - self.skipTest("skipping LVM devices file test: not supported") - -- self.addCleanup(BlockDev.lvm_set_global_config, "") -+ self.addCleanup(BlockDev.lvm_set_global_config, None) - - # force-enable the feature, it might be disabled by default - succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") -@@ -1738,13 +1738,13 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - dfile = read_file("/etc/lvm/devices/" + self.devicefile) - self.assertNotIn(self.loop_dev, dfile) - -- BlockDev.lvm_set_global_config("") -+ BlockDev.lvm_set_global_config(None) - - def test_devices_enabled(self): - if not self.devices_avail: - self.skipTest("skipping LVM devices file test: not supported") - -- self.addCleanup(BlockDev.lvm_set_global_config, "") -+ self.addCleanup(BlockDev.lvm_set_global_config, None) - - # checking if the feature is enabled or disabled is hard so lets just disable - # the devices file using the global config and check lvm_devices_add fails -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index ea3b7f8..882cdf2 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -1697,7 +1697,7 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - if not self.devices_avail: - self.skipTest("skipping LVM devices file test: not supported") - -- self.addCleanup(BlockDev.lvm_set_global_config, "") -+ self.addCleanup(BlockDev.lvm_set_global_config, None) - - # force-enable the feature, it might be disabled by default - succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") -@@ -1724,13 +1724,13 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - dfile = read_file("/etc/lvm/devices/" + self.devicefile) - self.assertNotIn(self.loop_dev, dfile) - -- BlockDev.lvm_set_global_config("") -+ BlockDev.lvm_set_global_config(None) - - def test_devices_enabled(self): - if not self.devices_avail: - self.skipTest("skipping LVM devices file test: not supported") - -- self.addCleanup(BlockDev.lvm_set_global_config, "") -+ self.addCleanup(BlockDev.lvm_set_global_config, None) - - # checking if the feature is enabled or disabled is hard so lets just disable - # the devices file using the global config and check lvm_devices_add fails --- -2.31.1 - - -From 2f33f2af18efa0b337f8383cb6f137d6211fe7fb Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 12 Nov 2021 15:10:45 +0100 -Subject: [PATCH 6/8] lvm: Do not set global config to and empty string - -If we set it to an empty string we end up running "--config" -without a parameter and lvm will use whatever is next parameter -like the device path for pvremove. ---- - src/plugins/lvm-dbus.c | 5 ++++- - src/plugins/lvm.c | 5 ++++- - tests/lvm_dbus_tests.py | 12 ++++++++++++ - tests/lvm_test.py | 12 ++++++++++++ - 4 files changed, 32 insertions(+), 2 deletions(-) - -diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c -index 22204d5..b7bd019 100644 ---- a/src/plugins/lvm-dbus.c -+++ b/src/plugins/lvm-dbus.c -@@ -2644,7 +2644,10 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error UNUSE - g_free (global_config_str); - - /* now store the new one */ -- global_config_str = g_strdup (new_config); -+ if (!new_config || g_strcmp0 (new_config, "") == 0) -+ global_config_str = NULL; -+ else -+ global_config_str = g_strdup (new_config); - - g_mutex_unlock (&global_config_lock); - return TRUE; -diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c -index 605fcb0..124fce7 100644 ---- a/src/plugins/lvm.c -+++ b/src/plugins/lvm.c -@@ -2016,7 +2016,10 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error UNUSE - g_free (global_config_str); - - /* now store the new one */ -- global_config_str = g_strdup (new_config); -+ if (!new_config || g_strcmp0 (new_config, "") == 0) -+ global_config_str = NULL; -+ else -+ global_config_str = g_strdup (new_config); - - g_mutex_unlock (&global_config_lock); - return TRUE; -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index d422869..5516afe 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -1754,3 +1754,15 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - - with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): - BlockDev.lvm_devices_add("", self.devicefile) -+ -+ -+class LvmConfigTestPvremove(LvmPVonlyTestCase): -+ -+ @tag_test(TestTags.REGRESSION) -+ def test_set_empty_config(self): -+ succ = BlockDev.lvm_pvcreate(self.loop_dev) -+ self.assertTrue(succ) -+ -+ BlockDev.lvm_set_global_config("") -+ succ = BlockDev.lvm_pvremove(self.loop_dev) -+ self.assertTrue(succ) -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index 882cdf2..e349817 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -1740,3 +1740,15 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): - - with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): - BlockDev.lvm_devices_add("", self.devicefile) -+ -+ -+class LvmConfigTestPvremove(LvmPVonlyTestCase): -+ -+ @tag_test(TestTags.REGRESSION) -+ def test_set_empty_config(self): -+ succ = BlockDev.lvm_pvcreate(self.loop_dev) -+ self.assertTrue(succ) -+ -+ BlockDev.lvm_set_global_config("") -+ succ = BlockDev.lvm_pvremove(self.loop_dev) -+ self.assertTrue(succ) --- -2.31.1 - - -From 2a4e610027a2c2a315054b84a323ce973939ca2d Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 16 Mar 2021 12:05:37 +0100 -Subject: [PATCH 7/8] vdo: Do not use g_memdup in bd_vdo_stats_copy - -g_memdup is deprecated and the replacement g_memdup2 is not yet -available so lets just do the copy manually. ---- - src/lib/plugin_apis/vdo.api | 17 ++++++++++++++++- - src/plugins/vdo.c | 17 ++++++++++++++++- - 2 files changed, 32 insertions(+), 2 deletions(-) - -diff --git a/src/lib/plugin_apis/vdo.api b/src/lib/plugin_apis/vdo.api -index 936f8e0..312de4e 100644 ---- a/src/lib/plugin_apis/vdo.api -+++ b/src/lib/plugin_apis/vdo.api -@@ -170,7 +170,22 @@ void bd_vdo_stats_free (BDVDOStats *stats) { - * Deprecated: 2.24: Use LVM-VDO integration instead. - */ - BDVDOStats* bd_vdo_stats_copy (BDVDOStats *stats) { -- return g_memdup (stats, sizeof (BDVDOStats)); -+ if (stats == NULL) -+ return NULL; -+ -+ BDVDOStats *new_stats = g_new0 (BDVDOStats, 1); -+ -+ new_stats->block_size = stats->block_size; -+ new_stats->logical_block_size = stats->logical_block_size; -+ new_stats->physical_blocks = stats->physical_blocks; -+ new_stats->data_blocks_used = stats->data_blocks_used; -+ new_stats->overhead_blocks_used = stats->overhead_blocks_used; -+ new_stats->logical_blocks_used = stats->logical_blocks_used; -+ new_stats->used_percent = stats->used_percent; -+ new_stats->saving_percent = stats->saving_percent; -+ new_stats->write_amplification_ratio = stats->write_amplification_ratio; -+ -+ return new_stats; - } - - GType bd_vdo_stats_get_type () { -diff --git a/src/plugins/vdo.c b/src/plugins/vdo.c -index 2352394..d443099 100644 ---- a/src/plugins/vdo.c -+++ b/src/plugins/vdo.c -@@ -81,7 +81,22 @@ void bd_vdo_stats_free (BDVDOStats *stats) { - } - - BDVDOStats* bd_vdo_stats_copy (BDVDOStats *stats) { -- return g_memdup (stats, sizeof (BDVDOStats)); -+ if (stats == NULL) -+ return NULL; -+ -+ BDVDOStats *new_stats = g_new0 (BDVDOStats, 1); -+ -+ new_stats->block_size = stats->block_size; -+ new_stats->logical_block_size = stats->logical_block_size; -+ new_stats->physical_blocks = stats->physical_blocks; -+ new_stats->data_blocks_used = stats->data_blocks_used; -+ new_stats->overhead_blocks_used = stats->overhead_blocks_used; -+ new_stats->logical_blocks_used = stats->logical_blocks_used; -+ new_stats->used_percent = stats->used_percent; -+ new_stats->saving_percent = stats->saving_percent; -+ new_stats->write_amplification_ratio = stats->write_amplification_ratio; -+ -+ return new_stats; - } - - --- -2.31.1 - - -From 577ea466e3b7af464137e087907ba980ad3994ee Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 26 Nov 2021 15:19:55 +0100 -Subject: [PATCH 8/8] lvm: Use "lvmconfig full" to get valid config instead of - "current" - -"lvmconfig current" doesn't work together with --config even if we -don't override the "use_devicefile" key. "lvmconfig full" seems to -be working in all cases. ---- - src/plugins/lvm-dbus.c | 4 ++-- - src/plugins/lvm.c | 4 ++-- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c -index b7bd019..825c5e9 100644 ---- a/src/plugins/lvm-dbus.c -+++ b/src/plugins/lvm-dbus.c -@@ -3955,9 +3955,9 @@ static gboolean _lvm_devices_enabled () { - gint scanned = 0; - g_autofree gchar *config_arg = NULL; - -- /* try current config first -- if we get something from this it means the feature is -+ /* try full config first -- if we get something from this it means the feature is - explicitly enabled or disabled by system lvm.conf or using the --config option */ -- args[2] = "current"; -+ args[2] = "full"; - - /* make sure to include the global config from us when getting the current config value */ - g_mutex_lock (&global_config_lock); -diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c -index 124fce7..21320f3 100644 ---- a/src/plugins/lvm.c -+++ b/src/plugins/lvm.c -@@ -3251,9 +3251,9 @@ static gboolean _lvm_devices_enabled () { - gboolean enabled = FALSE; - gint scanned = 0; - -- /* try current config first -- if we get something from this it means the feature is -+ /* try full config first -- if we get something from this it means the feature is - explicitly enabled or disabled by system lvm.conf or using the --config option */ -- args[2] = "current"; -+ args[2] = "full"; - ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); - if (ret) { - scanned = sscanf (output, "use_devicesfile=%u", &enabled); --- -2.31.1 - diff --git a/0008-lvm-Fix-reading-statistics-for-VDO-pools-with-VDO-8.patch b/0008-lvm-Fix-reading-statistics-for-VDO-pools-with-VDO-8.patch deleted file mode 100644 index 4d3796b..0000000 --- a/0008-lvm-Fix-reading-statistics-for-VDO-pools-with-VDO-8.patch +++ /dev/null @@ -1,80 +0,0 @@ -From e0fcbae856454dba9df3f8df800d74fde66731e5 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 31 Aug 2021 14:07:23 +0200 -Subject: [PATCH] lvm: Fix reading statistics for VDO pools with VDO 8 - -The statistics are no longer available in /sys/kvdo, in the latest -version of kvdo we need to use /sys/block//vdo/statistics. - -Resolves: rhbz#1994220 ---- - src/plugins/vdo_stats.c | 42 +++++++++++++++++++++++++++++++++++++---- - 1 file changed, 38 insertions(+), 4 deletions(-) - -diff --git a/src/plugins/vdo_stats.c b/src/plugins/vdo_stats.c -index ed04b51..2e244aa 100644 ---- a/src/plugins/vdo_stats.c -+++ b/src/plugins/vdo_stats.c -@@ -133,6 +133,23 @@ static void add_computed_stats (GHashTable *stats) { - add_journal_stats (stats); - } - -+static gchar* _dm_node_from_name (const gchar *map_name, GError **error) { -+ gchar *dev_path = NULL; -+ gchar *ret = NULL; -+ gchar *dev_mapper_path = g_strdup_printf ("/dev/mapper/%s", map_name); -+ -+ dev_path = bd_utils_resolve_device (dev_mapper_path, error); -+ g_free (dev_mapper_path); -+ if (!dev_path) -+ /* error is already populated */ -+ return NULL; -+ -+ ret = g_path_get_basename (dev_path); -+ g_free (dev_path); -+ -+ return ret; -+} -+ - GHashTable __attribute__ ((visibility ("hidden"))) - *vdo_get_stats_full (const gchar *name, GError **error) { - GHashTable *stats; -@@ -141,14 +158,31 @@ GHashTable __attribute__ ((visibility ("hidden"))) - const gchar *direntry; - gchar *s; - gchar *val = NULL; -+ g_autofree gchar *dm_node = NULL; - -- /* TODO: does the `name` need to be escaped? */ -- stats_dir = g_build_path (G_DIR_SEPARATOR_S, VDO_SYS_PATH, name, "statistics", NULL); -+ /* try "new" (kvdo >= 8) path first -- /sys/block/dm-X/vdo/statistics */ -+ dm_node = _dm_node_from_name (name, error); -+ if (dm_node == NULL) { -+ g_prefix_error (error, "Failed to get DM node for %s: ", name); -+ return NULL; -+ } -+ -+ stats_dir = g_build_path (G_DIR_SEPARATOR_S, "/sys/block", dm_node, "vdo/statistics", NULL); - dir = g_dir_open (stats_dir, 0, error); - if (dir == NULL) { -- g_prefix_error (error, "Error reading statistics from %s: ", stats_dir); -+ g_debug ("Failed to read VDO stats using the new API, falling back to %s: %s", -+ VDO_SYS_PATH, (*error)->message); - g_free (stats_dir); -- return NULL; -+ g_clear_error (error); -+ -+ /* lets try /sys/kvdo */ -+ stats_dir = g_build_path (G_DIR_SEPARATOR_S, VDO_SYS_PATH, name, "statistics", NULL); -+ dir = g_dir_open (stats_dir, 0, error); -+ if (dir == NULL) { -+ g_prefix_error (error, "Error reading statistics from %s: ", stats_dir); -+ g_free (stats_dir); -+ return NULL; -+ } - } - - stats = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); --- -2.31.1 - diff --git a/0009-vdo_stats-Default-to-100-savings-for-invalid-savings.patch b/0009-vdo_stats-Default-to-100-savings-for-invalid-savings.patch deleted file mode 100644 index f1ada49..0000000 --- a/0009-vdo_stats-Default-to-100-savings-for-invalid-savings.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 940346f14ee5644f2593817b4196c18de8a713f0 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Mon, 22 Nov 2021 14:16:02 +0100 -Subject: [PATCH] vdo_stats: Default to 100 % savings for invalid savings - values - -We are currently using "-1" when VDO logical_blocks_used is 0 -which doesn't match the LVM logic which returns 100 so to make -both values in vdo_info and vdo_stats equal we should return 100 -in this case too. ---- - src/plugins/vdo_stats.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/plugins/vdo_stats.c b/src/plugins/vdo_stats.c -index 3ec2d60..f3f0390 100644 ---- a/src/plugins/vdo_stats.c -+++ b/src/plugins/vdo_stats.c -@@ -96,7 +96,7 @@ static void add_block_stats (GHashTable *stats) { - g_hash_table_replace (stats, g_strdup ("oneKBlocksUsed"), g_strdup_printf ("%"G_GINT64_FORMAT, (data_blocks_used + overhead_blocks_used) * block_size / 1024)); - g_hash_table_replace (stats, g_strdup ("oneKBlocksAvailable"), g_strdup_printf ("%"G_GINT64_FORMAT, (physical_blocks - data_blocks_used - overhead_blocks_used) * block_size / 1024)); - g_hash_table_replace (stats, g_strdup ("usedPercent"), g_strdup_printf ("%.0f", 100.0 * (gfloat) (data_blocks_used + overhead_blocks_used) / (gfloat) physical_blocks + 0.5)); -- savings = (logical_blocks_used > 0) ? (gint64) (100.0 * (gfloat) (logical_blocks_used - data_blocks_used) / (gfloat) logical_blocks_used) : -1; -+ savings = (logical_blocks_used > 0) ? (gint64) (100.0 * (gfloat) (logical_blocks_used - data_blocks_used) / (gfloat) logical_blocks_used) : 100; - g_hash_table_replace (stats, g_strdup ("savings"), g_strdup_printf ("%"G_GINT64_FORMAT, savings)); - if (savings >= 0) - g_hash_table_replace (stats, g_strdup ("savingPercent"), g_strdup_printf ("%"G_GINT64_FORMAT, savings)); --- -2.31.1 - diff --git a/0010-Add-support-for-creating-and-activating-integrity-de.patch b/0010-Add-support-for-creating-and-activating-integrity-de.patch deleted file mode 100644 index 77d6bc8..0000000 --- a/0010-Add-support-for-creating-and-activating-integrity-de.patch +++ /dev/null @@ -1,966 +0,0 @@ -From 37f1aff5f5f967d6a4440d176f3de877aab789ac Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Mon, 20 Sep 2021 16:38:16 +0200 -Subject: [PATCH 1/3] Add support for creating and activating integrity devices - -This adds support for create, open and close actions for standalone -integrity devices using cryptsetup. ---- - configure.ac | 4 +- - src/lib/plugin_apis/crypto.api | 157 +++++++++++++++++ - src/plugins/crypto.c | 261 +++++++++++++++++++++++++++- - src/plugins/crypto.h | 41 +++++ - src/python/gi/overrides/BlockDev.py | 24 +++ - tests/crypto_test.py | 97 ++++++++++- - 6 files changed, 576 insertions(+), 8 deletions(-) - -diff --git a/configure.ac b/configure.ac -index abe1412..13830ae 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -210,7 +210,9 @@ AS_IF([test "x$with_crypto" != "xno"], - AS_IF([$PKG_CONFIG --atleast-version=2.0.3 libcryptsetup], - [AC_DEFINE([LIBCRYPTSETUP_2])], []) - AS_IF([$PKG_CONFIG --atleast-version=2.3.0 libcryptsetup], -- [AC_DEFINE([LIBCRYPTSETUP_BITLK])], []) -+ [AC_DEFINE([LIBCRYPTSETUP_23])], []) -+ AS_IF([$PKG_CONFIG --atleast-version=2.4.0 libcryptsetup], -+ [AC_DEFINE([LIBCRYPTSETUP_24])], []) - AS_IF([test "x$with_escrow" != "xno"], - [LIBBLOCKDEV_PKG_CHECK_MODULES([NSS], [nss >= 3.18.0]) - LIBBLOCKDEV_CHECK_HEADER([volume_key/libvolume_key.h], [$GLIB_CFLAGS $NSS_CFLAGS], [libvolume_key.h not available])], -diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api -index ef0217f..40e32c8 100644 ---- a/src/lib/plugin_apis/crypto.api -+++ b/src/lib/plugin_apis/crypto.api -@@ -1,5 +1,6 @@ - #include - #include -+#include - - #define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB - -@@ -245,6 +246,115 @@ GType bd_crypto_luks_extra_get_type () { - return type; - } - -+#define BD_CRYPTO_TYPE_INTEGRITY_EXTRA (bd_crypto_integrity_extra_get_type ()) -+GType bd_crypto_integrity_extra_get_type(); -+ -+/** -+ * BDCryptoIntegrityExtra: -+ * @sector_size: integrity sector size -+ * @journal_size: size of journal in bytes -+ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit -+ * @journal_commit_time: journal commit time (or bitmap flush time) in ms -+ * @interleave_sectors: number of interleave sectors (power of two) -+ * @tag_size: tag size per-sector in bytes -+ * @buffer_sectors: number of sectors in one buffer -+ */ -+typedef struct BDCryptoIntegrityExtra { -+ guint32 sector_size; -+ guint64 journal_size; -+ guint journal_watermark; -+ guint journal_commit_time; -+ guint32 interleave_sectors; -+ guint32 tag_size; -+ guint32 buffer_sectors; -+} BDCryptoIntegrityExtra; -+ -+/** -+ * bd_crypto_integrity_extra_copy: (skip) -+ * @extra: (allow-none): %BDCryptoIntegrityExtra to copy -+ * -+ * Creates a new copy of @extra. -+ */ -+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) { -+ if (extra == NULL) -+ return NULL; -+ -+ BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1); -+ -+ new_extra->sector_size = extra->sector_size; -+ new_extra->journal_size = extra->journal_size; -+ new_extra->journal_watermark = extra->journal_watermark; -+ new_extra->journal_commit_time = extra->journal_commit_time; -+ new_extra->interleave_sectors = extra->interleave_sectors; -+ new_extra->tag_size = extra->tag_size; -+ new_extra->buffer_sectors = extra->buffer_sectors; -+ -+ return new_extra; -+} -+ -+/** -+ * bd_crypto_integrity_extra_free: (skip) -+ * @extra: (allow-none): %BDCryptoIntegrityExtra to free -+ * -+ * Frees @extra. -+ */ -+void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) { -+ if (extra == NULL) -+ return; -+ -+ g_free (extra); -+} -+ -+/** -+ * bd_crypto_integrity_extra_new: (constructor) -+ * @sector_size: integrity sector size, 0 for default (512) -+ * @journal_size: size of journal in bytes -+ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit -+ * @journal_commit_time: journal commit time (or bitmap flush time) in ms -+ * @interleave_sectors: number of interleave sectors (power of two) -+ * @tag_size: tag size per-sector in bytes -+ * @buffer_sectors: number of sectors in one buffer -+ * -+ * Returns: (transfer full): a new Integrity extra argument -+ */ -+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) { -+ BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1); -+ ret->sector_size = sector_size; -+ ret->journal_size = journal_size; -+ ret->journal_watermark = journal_watermark; -+ ret->journal_commit_time = journal_commit_time; -+ ret->interleave_sectors = interleave_sectors; -+ ret->tag_size = tag_size; -+ ret->buffer_sectors = buffer_sectors; -+ -+ return ret; -+} -+ -+GType bd_crypto_integrity_extra_get_type () { -+ static GType type = 0; -+ -+ if (G_UNLIKELY(type == 0)) { -+ type = g_boxed_type_register_static("BDCryptoIntegrityExtra", -+ (GBoxedCopyFunc) bd_crypto_integrity_extra_copy, -+ (GBoxedFreeFunc) bd_crypto_integrity_extra_free); -+ } -+ -+ return type; -+} -+ -+typedef enum { -+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, -+ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, -+#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP -+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, -+#endif -+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, -+#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET -+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, -+#endif -+ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, -+} BDCryptoIntegrityOpenFlags; -+ - #define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ()) - GType bd_crypto_luks_info_get_type(); - -@@ -857,6 +967,53 @@ BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error) - */ - BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error); - -+/** -+ * bd_crypto_integrity_format: -+ * @device: a device to format as integrity -+ * @algorithm: integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default -+ * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums -+ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed -+ * @key_size: size the integrity key and @key_data -+ * @extra: (allow-none): extra arguments for integrity format creation -+ * @error: (out): place to store error (if any) -+ * -+ * Formats the given @device as integrity according to the other parameters given. -+ * -+ * Returns: whether the given @device was successfully formatted as integrity or not -+ * (the @error) contains the error in such cases) -+ * -+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE -+ */ -+gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error); -+ -+/** -+ * bd_crypto_integrity_open: -+ * @device: integrity device to open -+ * @name: name for the opened @device -+ * @algorithm: (allow-none): integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default -+ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed -+ * @key_size: size the integrity key and @key_data -+ * @flags: flags for the integrity device activation -+ * @extra: (allow-none): extra arguments for integrity open -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the @device was successfully opened or not -+ * -+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE -+ */ -+gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error); -+ -+/** -+ * bd_crypto_integrity_close: -+ * @integrity_device: integrity device to close -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the given @integrity_device was successfully closed or not -+ * -+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE -+ */ -+gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error); -+ - /** - * bd_crypto_device_seems_encrypted: - * @device: the queried device -diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c -index 4fad9a8..b1b0700 100644 ---- a/src/plugins/crypto.c -+++ b/src/plugins/crypto.c -@@ -50,6 +50,18 @@ - - #define SECTOR_SIZE 512 - -+#define DEFAULT_LUKS_KEYSIZE_BITS 256 -+#define DEFAULT_LUKS_CIPHER "aes-xts-plain64" -+ -+#ifdef LIBCRYPTSETUP_23 -+/* 0 for autodetect since 2.3.0 */ -+#define DEFAULT_INTEGRITY_TAG_SIZE 0 -+#else -+/* we need some sane default for older versions, users should specify tag size when using -+ other algorithms than the default crc32c */ -+#define DEFAULT_INTEGRITY_TAG_SIZE 4 -+#endif -+ - #define UNUSED __attribute__((unused)) - - /** -@@ -146,6 +158,43 @@ BDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar - return ret; - } - -+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) { -+ BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1); -+ ret->sector_size = sector_size; -+ ret->journal_size = journal_size; -+ ret->journal_watermark = journal_watermark; -+ ret->journal_commit_time = journal_commit_time; -+ ret->interleave_sectors = interleave_sectors; -+ ret->tag_size = tag_size; -+ ret->buffer_sectors = buffer_sectors; -+ -+ return ret; -+} -+ -+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) { -+ if (extra == NULL) -+ return NULL; -+ -+ BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1); -+ -+ new_extra->sector_size = extra->sector_size; -+ new_extra->journal_size = extra->journal_size; -+ new_extra->journal_watermark = extra->journal_watermark; -+ new_extra->journal_commit_time = extra->journal_commit_time; -+ new_extra->interleave_sectors = extra->interleave_sectors; -+ new_extra->tag_size = extra->tag_size; -+ new_extra->buffer_sectors = extra->buffer_sectors; -+ -+ return new_extra; -+} -+ -+void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) { -+ if (extra == NULL) -+ return; -+ -+ g_free (extra); -+} -+ - void bd_crypto_luks_info_free (BDCryptoLUKSInfo *info) { - if (info == NULL) - return; -@@ -346,15 +395,15 @@ gboolean bd_crypto_is_tech_avail (BDCryptoTech tech, guint64 mode, GError **erro - "Integrity technology requires libcryptsetup >= 2.0"); - return FALSE; - #endif -- ret = mode & (BD_CRYPTO_TECH_MODE_QUERY); -+ ret = mode & (BD_CRYPTO_TECH_MODE_CREATE|BD_CRYPTO_TECH_MODE_OPEN_CLOSE|BD_CRYPTO_TECH_MODE_QUERY); - if (ret != mode) { - g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, -- "Only 'query' supported for Integrity"); -+ "Only 'create', 'open' and 'query' supported for Integrity"); - return FALSE; - } else - return TRUE; - case BD_CRYPTO_TECH_BITLK: --#ifndef LIBCRYPTSETUP_BITLK -+#ifndef LIBCRYPTSETUP_23 - g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, - "BITLK technology requires libcryptsetup >= 2.3.0"); - return FALSE; -@@ -2035,6 +2084,208 @@ BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **e - } - #endif - -+static int _wipe_progress (guint64 size, guint64 offset, void *usrptr) { -+ /* "convert" the progress from 0-100 to 50-100 because wipe starts at 50 in bd_crypto_integrity_format */ -+ gdouble progress = 50 + (((gdouble) offset / size) * 100) / 2; -+ bd_utils_report_progress (*(guint64 *) usrptr, progress, "Integrity device wipe in progress"); -+ -+ return 0; -+} -+ -+/** -+ * bd_crypto_integrity_format: -+ * @device: a device to format as integrity -+ * @algorithm: integrity algorithm specification (e.g. "crc32c" or "sha256") -+ * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums -+ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed -+ * @key_size: size the integrity key and @key_data -+ * @extra: (allow-none): extra arguments for integrity format creation -+ * @error: (out): place to store error (if any) -+ * -+ * Formats the given @device as integrity according to the other parameters given. -+ * -+ * Returns: whether the given @device was successfully formatted as integrity or not -+ * (the @error) contains the error in such cases) -+ * -+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE -+ */ -+gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error) { -+ struct crypt_device *cd = NULL; -+ gint ret; -+ guint64 progress_id = 0; -+ gchar *msg = NULL; -+ struct crypt_params_integrity params = ZERO_INIT; -+ g_autofree gchar *tmp_name = NULL; -+ g_autofree gchar *tmp_path = NULL; -+ g_autofree gchar *dev_name = NULL; -+ -+ msg = g_strdup_printf ("Started formatting '%s' as integrity device", device); -+ progress_id = bd_utils_report_started (msg); -+ g_free (msg); -+ -+ ret = crypt_init (&cd, device); -+ if (ret != 0) { -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, -+ "Failed to initialize device: %s", strerror_l (-ret, c_locale)); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+ } -+ -+ if (extra) { -+ params.sector_size = extra->sector_size; -+ params.journal_size = extra->journal_size; -+ params.journal_watermark = extra->journal_watermark; -+ params.journal_commit_time = extra->journal_commit_time; -+ params.interleave_sectors = extra->interleave_sectors; -+ params.tag_size = extra->tag_size; -+ params.buffer_sectors = extra->buffer_sectors; -+ } -+ -+ params.integrity_key_size = key_size; -+ params.integrity = algorithm; -+ params.tag_size = params.tag_size ? params.tag_size : DEFAULT_INTEGRITY_TAG_SIZE; -+ -+ ret = crypt_format (cd, CRYPT_INTEGRITY, NULL, NULL, NULL, NULL, 0, ¶ms); -+ if (ret != 0) { -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED, -+ "Failed to format device: %s", strerror_l (-ret, c_locale)); -+ crypt_free (cd); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+ } -+ -+ if (wipe) { -+ bd_utils_report_progress (progress_id, 50, "Format created"); -+ -+ dev_name = g_path_get_basename (device); -+ tmp_name = g_strdup_printf ("bd-temp-integrity-%s-%d", dev_name, g_random_int ()); -+ tmp_path = g_strdup_printf ("%s/%s", crypt_get_dir (), tmp_name); -+ -+ ret = crypt_activate_by_volume_key (cd, tmp_name, (const char *) key_data, key_size, -+ CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL); -+ if (ret != 0) { -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, -+ "Failed to activate the newly created integrity device for wiping: %s", -+ strerror_l (-ret, c_locale)); -+ crypt_free (cd); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+ } -+ -+ bd_utils_report_progress (progress_id, 50, "Starting to wipe the newly created integrity device"); -+ ret = crypt_wipe (cd, tmp_path, CRYPT_WIPE_ZERO, 0, 0, 1048576, -+ 0, &_wipe_progress, &progress_id); -+ bd_utils_report_progress (progress_id, 100, "Wipe finished"); -+ if (ret != 0) { -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, -+ "Failed to wipe the newly created integrity device: %s", -+ strerror_l (-ret, c_locale)); -+ -+ ret = crypt_deactivate (cd, tmp_name); -+ if (ret != 0) -+ g_warning ("Failed to deactivate temporary device %s", tmp_name); -+ -+ crypt_free (cd); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+ } -+ -+ ret = crypt_deactivate (cd, tmp_name); -+ if (ret != 0) -+ g_warning ("Failed to deactivate temporary device %s", tmp_name); -+ -+ } else -+ bd_utils_report_finished (progress_id, "Completed"); -+ -+ crypt_free (cd); -+ -+ return TRUE; -+} -+ -+/** -+ * bd_crypto_integrity_open: -+ * @device: integrity device to open -+ * @name: name for the opened @device -+ * @algorithm: (allow-none): integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default -+ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed -+ * @key_size: size the integrity key and @key_data -+ * @flags: flags for the integrity device activation -+ * @extra: (allow-none): extra arguments for integrity open -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the @device was successfully opened or not -+ * -+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE -+ */ -+gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error) { -+ struct crypt_device *cd = NULL; -+ gint ret = 0; -+ guint64 progress_id = 0; -+ gchar *msg = NULL; -+ struct crypt_params_integrity params = ZERO_INIT; -+ -+ params.integrity = algorithm; -+ params.integrity_key_size = key_size; -+ -+ if (extra) { -+ params.sector_size = extra->sector_size; -+ params.journal_size = extra->journal_size; -+ params.journal_watermark = extra->journal_watermark; -+ params.journal_commit_time = extra->journal_commit_time; -+ params.interleave_sectors = extra->interleave_sectors; -+ params.tag_size = extra->tag_size; -+ params.buffer_sectors = extra->buffer_sectors; -+ } -+ -+ msg = g_strdup_printf ("Started opening '%s' integrity device", device); -+ progress_id = bd_utils_report_started (msg); -+ g_free (msg); -+ -+ ret = crypt_init (&cd, device); -+ if (ret != 0) { -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, -+ "Failed to initialize device: %s", strerror_l (-ret, c_locale)); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+ } -+ -+ ret = crypt_load (cd, CRYPT_INTEGRITY, ¶ms); -+ if (ret != 0) { -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, -+ "Failed to load device's parameters: %s", strerror_l (-ret, c_locale)); -+ crypt_free (cd); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+ } -+ -+ ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, flags); -+ if (ret < 0) { -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, -+ "Failed to activate device: %s", strerror_l (-ret, c_locale)); -+ -+ crypt_free (cd); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+ } -+ -+ crypt_free (cd); -+ bd_utils_report_finished (progress_id, "Completed"); -+ return TRUE; -+} -+ -+/** -+ * bd_crypto_integrity_close: -+ * @integrity_device: integrity device to close -+ * @error: (out): place to store error (if any) -+ * -+ * Returns: whether the given @integrity_device was successfully closed or not -+ * -+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE -+ */ -+gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error) { -+ return _crypto_close (integrity_device, "integrity", error); -+} -+ - /** - * bd_crypto_device_seems_encrypted: - * @device: the queried device -@@ -2472,7 +2723,7 @@ gboolean bd_crypto_escrow_device (const gchar *device, const gchar *passphrase, - * - * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE - */ --#ifndef LIBCRYPTSETUP_BITLK -+#ifndef LIBCRYPTSETUP_23 - gboolean bd_crypto_bitlk_open (const gchar *device UNUSED, const gchar *name UNUSED, const guint8* pass_data UNUSED, gsize data_len UNUSED, gboolean read_only UNUSED, GError **error) { - /* this will return FALSE and set error, because BITLK technology is not available */ - return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_BITLK, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error); -@@ -2542,7 +2793,7 @@ gboolean bd_crypto_bitlk_open (const gchar *device, const gchar *name, const gui - * - * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE - */ --#ifndef LIBCRYPTSETUP_BITLK -+#ifndef LIBCRYPTSETUP_23 - gboolean bd_crypto_bitlk_close (const gchar *bitlk_device UNUSED, GError **error) { - /* this will return FALSE and set error, because BITLK technology is not available */ - return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_BITLK, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error); -diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h -index a38724d..166e558 100644 ---- a/src/plugins/crypto.h -+++ b/src/plugins/crypto.h -@@ -116,6 +116,43 @@ void bd_crypto_luks_extra_free (BDCryptoLUKSExtra *extra); - BDCryptoLUKSExtra* bd_crypto_luks_extra_copy (BDCryptoLUKSExtra *extra); - BDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar *data_device, const gchar *integrity, guint64 sector_size, const gchar *label, const gchar *subsystem, BDCryptoLUKSPBKDF *pbkdf); - -+/** -+ * BDCryptoIntegrityExtra: -+ * @sector_size: integrity sector size -+ * @journal_size: size of journal in bytes -+ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit -+ * @journal_commit_time: journal commit time (or bitmap flush time) in ms -+ * @interleave_sectors: number of interleave sectors (power of two) -+ * @tag_size: tag size per-sector in bytes -+ * @buffer_sectors: number of sectors in one buffer -+ */ -+typedef struct BDCryptoIntegrityExtra { -+ guint32 sector_size; -+ guint64 journal_size; -+ guint journal_watermark; -+ guint journal_commit_time; -+ guint32 interleave_sectors; -+ guint32 tag_size; -+ guint32 buffer_sectors; -+} BDCryptoIntegrityExtra; -+ -+void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra); -+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra); -+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors); -+ -+typedef enum { -+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, -+ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, -+#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP -+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, -+#endif -+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, -+#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET -+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, -+#endif -+ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, -+} BDCryptoIntegrityOpenFlags; -+ - /** - * BDCryptoLUKSInfo: - * @version: LUKS version -@@ -209,6 +246,10 @@ gboolean bd_crypto_luks_header_restore (const gchar *device, const gchar *backup - BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error); - BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error); - -+gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error); -+gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error); -+gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error); -+ - gboolean bd_crypto_device_seems_encrypted (const gchar *device, GError **error); - gboolean bd_crypto_tc_open (const gchar *device, const gchar *name, const guint8* pass_data, gsize data_len, gboolean read_only, GError **error); - gboolean bd_crypto_tc_open_full (const gchar *device, const gchar *name, const guint8* pass_data, gsize data_len, const gchar **keyfiles, gboolean hidden, gboolean system, gboolean veracrypt, guint32 veracrypt_pim, gboolean read_only, GError **error); -diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py -index 715a262..71bcd31 100644 ---- a/src/python/gi/overrides/BlockDev.py -+++ b/src/python/gi/overrides/BlockDev.py -@@ -276,6 +276,30 @@ def crypto_bitlk_open(device, name, passphrase, read_only=False): - __all__.append("crypto_bitlk_open") - - -+class CryptoIntegrityExtra(BlockDev.CryptoIntegrityExtra): -+ def __new__(cls, sector_size=0, journal_size=0, journal_watermark=0, journal_commit_time=0, interleave_sectors=0, tag_size=0, buffer_sectors=0): -+ ret = BlockDev.CryptoIntegrityExtra.new(sector_size, journal_size, journal_watermark, journal_commit_time, interleave_sectors, tag_size, buffer_sectors) -+ ret.__class__ = cls -+ return ret -+ def __init__(self, *args, **kwargs): # pylint: disable=unused-argument -+ super(CryptoIntegrityExtra, self).__init__() #pylint: disable=bad-super-call -+CryptoIntegrityExtra = override(CryptoIntegrityExtra) -+__all__.append("CryptoIntegrityExtra") -+ -+ -+_crypto_integrity_format = BlockDev.crypto_integrity_format -+@override(BlockDev.crypto_integrity_format) -+def crypto_integrity_format(device, algorithm=None, wipe=True, key_data=None, extra=None): -+ return _crypto_integrity_format(device, algorithm, wipe, key_data, extra) -+__all__.append("crypto_integrity_format") -+ -+_crypto_integrity_open = BlockDev.crypto_integrity_open -+@override(BlockDev.crypto_integrity_open) -+def crypto_integrity_open(device, name, algorithm, key_data=None, flags=0, extra=None): -+ return _crypto_integrity_open(device, name, algorithm, key_data, flags, extra) -+__all__.append("crypto_integrity_open") -+ -+ - _dm_create_linear = BlockDev.dm_create_linear - @override(BlockDev.dm_create_linear) - def dm_create_linear(map_name, device, length, uuid=None): -diff --git a/tests/crypto_test.py b/tests/crypto_test.py -index 0aecc03..1c6832e 100644 ---- a/tests/crypto_test.py -+++ b/tests/crypto_test.py -@@ -2,6 +2,7 @@ import unittest - import os - import tempfile - import overrides_hack -+import secrets - import shutil - import subprocess - import six -@@ -42,6 +43,8 @@ class CryptoTestCase(unittest.TestCase): - - requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "loop")) - -+ _dm_name = "libblockdevTestLUKS" -+ - @classmethod - def setUpClass(cls): - unittest.TestCase.setUpClass() -@@ -72,7 +75,7 @@ class CryptoTestCase(unittest.TestCase): - - def _clean_up(self): - try: -- BlockDev.crypto_luks_close("libblockdevTestLUKS") -+ BlockDev.crypto_luks_close(self._dm_name) - except: - pass - -@@ -964,7 +967,8 @@ class CryptoTestInfo(CryptoTestCase): - succ = BlockDev.crypto_luks_close("libblockdevTestLUKS") - self.assertTrue(succ) - --class CryptoTestIntegrity(CryptoTestCase): -+ -+class CryptoTestLUKS2Integrity(CryptoTestCase): - @tag_test(TestTags.SLOW) - @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") - def test_luks2_integrity(self): -@@ -1151,3 +1155,92 @@ class CryptoTestBitlk(CryptoTestCase): - succ = BlockDev.crypto_bitlk_close("libblockdevTestBitlk") - self.assertTrue(succ) - self.assertFalse(os.path.exists("/dev/mapper/libblockdevTestBitlk")) -+ -+ -+class CryptoTestIntegrity(CryptoTestCase): -+ -+ _dm_name = "libblockdevTestIntegrity" -+ -+ @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") -+ def test_integrity(self): -+ # basic format+open+close test -+ succ = BlockDev.crypto_integrity_format(self.loop_dev, "sha256", False) -+ self.assertTrue(succ) -+ -+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "sha256") -+ self.assertTrue(succ) -+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ -+ info = BlockDev.crypto_integrity_info(self._dm_name) -+ self.assertEqual(info.algorithm, "sha256") -+ -+ succ = BlockDev.crypto_integrity_close(self._dm_name) -+ self.assertTrue(succ) -+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ -+ # same now with a keyed algorithm -+ key = list(secrets.token_bytes(64)) -+ -+ succ = BlockDev.crypto_integrity_format(self.loop_dev, "hmac(sha256)", False, key) -+ self.assertTrue(succ) -+ -+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "hmac(sha256)", key) -+ self.assertTrue(succ) -+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ -+ info = BlockDev.crypto_integrity_info(self._dm_name) -+ self.assertEqual(info.algorithm, "hmac(sha256)") -+ -+ succ = BlockDev.crypto_integrity_close(self._dm_name) -+ self.assertTrue(succ) -+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ -+ # same with some custom parameters -+ extra = BlockDev.CryptoIntegrityExtra(sector_size=4096, interleave_sectors=65536) -+ succ = BlockDev.crypto_integrity_format(self.loop_dev, "crc32c", wipe=False, extra=extra) -+ self.assertTrue(succ) -+ -+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "crc32c") -+ self.assertTrue(succ) -+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ -+ info = BlockDev.crypto_integrity_info(self._dm_name) -+ self.assertEqual(info.algorithm, "crc32c") -+ self.assertEqual(info.sector_size, 4096) -+ self.assertEqual(info.interleave_sectors, 65536) -+ -+ succ = BlockDev.crypto_integrity_close(self._dm_name) -+ self.assertTrue(succ) -+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ -+ @tag_test(TestTags.SLOW) -+ @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") -+ def test_integrity_wipe(self): -+ # also check that wipe progress reporting works -+ progress_log = [] -+ -+ def _my_progress_func(_task, _status, completion, msg): -+ progress_log.append((completion, msg)) -+ -+ succ = BlockDev.utils_init_prog_reporting(_my_progress_func) -+ self.assertTrue(succ) -+ self.addCleanup(BlockDev.utils_init_prog_reporting, None) -+ -+ succ = BlockDev.crypto_integrity_format(self.loop_dev, "sha256", True) -+ self.assertTrue(succ) -+ -+ # at least one message "Integrity device wipe in progress" should be logged -+ self.assertTrue(any(prog[1] == "Integrity device wipe in progress" for prog in progress_log)) -+ -+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "sha256") -+ self.assertTrue(succ) -+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ -+ # check the devices was wiped and the checksums recalculated -+ # (mkfs reads some blocks first so without checksums it would fail) -+ ret, _out, err = run_command("mkfs.ext2 /dev/mapper/%s " % self._dm_name) -+ self.assertEqual(ret, 0, msg="Failed to create ext2 filesystem on integrity: %s" % err) -+ -+ succ = BlockDev.crypto_integrity_close(self._dm_name) -+ self.assertTrue(succ) -+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) --- -2.31.1 - - -From 4dcb7a42a2cb33f7a63021d72889c9a9688adfd3 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 30 Sep 2021 16:01:40 +0200 -Subject: [PATCH 2/3] Create smaller test images for integrity tests - -We are going to overwrite the entire device in test_integrity_wipe -so we need to make sure the sparse actually fits to /tmp which -can be smaller than 1 GiB. ---- - tests/crypto_test.py | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/tests/crypto_test.py b/tests/crypto_test.py -index 1c6832e..b7ec251 100644 ---- a/tests/crypto_test.py -+++ b/tests/crypto_test.py -@@ -44,6 +44,7 @@ class CryptoTestCase(unittest.TestCase): - requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "loop")) - - _dm_name = "libblockdevTestLUKS" -+ _sparse_size = 1024**3 - - @classmethod - def setUpClass(cls): -@@ -57,8 +58,8 @@ class CryptoTestCase(unittest.TestCase): - - def setUp(self): - self.addCleanup(self._clean_up) -- self.dev_file = create_sparse_tempfile("crypto_test", 1024**3) -- self.dev_file2 = create_sparse_tempfile("crypto_test2", 1024**3) -+ self.dev_file = create_sparse_tempfile("crypto_test", self._sparse_size) -+ self.dev_file2 = create_sparse_tempfile("crypto_test2", self._sparse_size) - try: - self.loop_dev = create_lio_device(self.dev_file) - except RuntimeError as e: -@@ -1160,6 +1161,7 @@ class CryptoTestBitlk(CryptoTestCase): - class CryptoTestIntegrity(CryptoTestCase): - - _dm_name = "libblockdevTestIntegrity" -+ _sparse_size = 100 * 1024**2 - - @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") - def test_integrity(self): --- -2.31.1 - - -From 3b82f9085c0df2e58b673716cdefd747495738e2 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 20 Oct 2021 10:27:41 +0200 -Subject: [PATCH 3/3] crypto: Do not use libcryptsetup flags directly in - crypto.h - -We can "translate" our flags in the implementation instead to -avoid including libcryptsetup.h in our header and API files. ---- - src/lib/plugin_apis/crypto.api | 17 ++++++----------- - src/plugins/crypto.c | 34 +++++++++++++++++++++++++++++++++- - src/plugins/crypto.h | 16 ++++++---------- - tests/crypto_test.py | 14 ++++++++++++++ - 4 files changed, 59 insertions(+), 22 deletions(-) - -diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api -index 40e32c8..cf87979 100644 ---- a/src/lib/plugin_apis/crypto.api -+++ b/src/lib/plugin_apis/crypto.api -@@ -1,6 +1,5 @@ - #include - #include --#include - - #define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB - -@@ -343,16 +342,12 @@ GType bd_crypto_integrity_extra_get_type () { - } - - typedef enum { -- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, -- BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, --#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP -- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, --#endif -- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, --#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET -- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, --#endif -- BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, -+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = 1 << 0, -+ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = 1 << 1, -+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = 1 << 2, -+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = 1 << 3, -+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = 1 << 4, -+ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5, - } BDCryptoIntegrityOpenFlags; - - #define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ()) -diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c -index b1b0700..8a4d64a 100644 ---- a/src/plugins/crypto.c -+++ b/src/plugins/crypto.c -@@ -2223,6 +2223,7 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const - guint64 progress_id = 0; - gchar *msg = NULL; - struct crypt_params_integrity params = ZERO_INIT; -+ guint32 activate_flags = 0; - - params.integrity = algorithm; - params.integrity_key_size = key_size; -@@ -2237,6 +2238,37 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const - params.buffer_sectors = extra->buffer_sectors; - } - -+ -+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL) -+ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL; -+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECOVERY) -+ activate_flags |= CRYPT_ACTIVATE_RECOVERY; -+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE) -+ activate_flags |= CRYPT_ACTIVATE_RECALCULATE; -+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS) -+ activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; -+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP) { -+#ifndef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, -+ "Cannot activate %s with bitmap, installed version of cryptsetup doesn't support this option.", device); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+#else -+ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP; -+#endif -+ } -+ -+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET) { -+#ifndef CRYPT_ACTIVATE_RECALCULATE_RESET -+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, -+ "Cannot reset integrity recalculation while activating %s, installed version of cryptsetup doesn't support this option.", device); -+ bd_utils_report_finished (progress_id, (*error)->message); -+ return FALSE; -+#else -+ activate_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET; -+#endif -+ } -+ - msg = g_strdup_printf ("Started opening '%s' integrity device", device); - progress_id = bd_utils_report_started (msg); - g_free (msg); -@@ -2258,7 +2290,7 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const - return FALSE; - } - -- ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, flags); -+ ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, activate_flags); - if (ret < 0) { - g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, - "Failed to activate device: %s", strerror_l (-ret, c_locale)); -diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h -index 166e558..b5f133c 100644 ---- a/src/plugins/crypto.h -+++ b/src/plugins/crypto.h -@@ -141,16 +141,12 @@ BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra * - BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors); - - typedef enum { -- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, -- BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, --#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP -- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, --#endif -- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, --#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET -- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, --#endif -- BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, -+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = 1 << 0, -+ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = 1 << 1, -+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = 1 << 2, -+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = 1 << 3, -+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = 1 << 4, -+ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5, - } BDCryptoIntegrityOpenFlags; - - /** -diff --git a/tests/crypto_test.py b/tests/crypto_test.py -index b7ec251..673d8b8 100644 ---- a/tests/crypto_test.py -+++ b/tests/crypto_test.py -@@ -1215,6 +1215,20 @@ class CryptoTestIntegrity(CryptoTestCase): - self.assertTrue(succ) - self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) - -+ # open with flags -+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "crc32c", -+ flags=BlockDev.CryptoIntegrityOpenFlags.ALLOW_DISCARDS) -+ self.assertTrue(succ) -+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ -+ # check that discard is enabled for the mapped device -+ _ret, out, _err = run_command("dmsetup table %s" % self._dm_name) -+ self.assertIn("allow_discards", out) -+ -+ succ = BlockDev.crypto_integrity_close(self._dm_name) -+ self.assertTrue(succ) -+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) -+ - @tag_test(TestTags.SLOW) - @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") - def test_integrity_wipe(self): --- -2.31.1 - diff --git a/0011-tests-Wait-for-raid-and-mirrored-LVs-to-be-synced-be.patch b/0011-tests-Wait-for-raid-and-mirrored-LVs-to-be-synced-be.patch deleted file mode 100644 index 938a8a4..0000000 --- a/0011-tests-Wait-for-raid-and-mirrored-LVs-to-be-synced-be.patch +++ /dev/null @@ -1,278 +0,0 @@ -From d0ba031e679d480855bea61060acea597d5ffbbd Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 15 Dec 2021 14:14:19 +0100 -Subject: [PATCH 1/2] tests: Wait for raid and mirrored LVs to be synced before - removing - -Resolves: rhbz#2030647 ---- - tests/lvm_dbus_tests.py | 31 +++++++++++++++++++++++++------ - tests/lvm_test.py | 31 +++++++++++++++++++++++++------ - 2 files changed, 50 insertions(+), 12 deletions(-) - -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index 5516afe..5ce653e 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -7,6 +7,8 @@ import six - import re - import shutil - import subprocess -+import time -+from contextlib import contextmanager - from distutils.version import LooseVersion - from itertools import chain - -@@ -18,6 +20,21 @@ sb = dbus.SystemBus() - lvm_dbus_running = any("lvmdbus" in name for name in chain(sb.list_names(), sb.list_activatable_names())) - - -+@contextmanager -+def wait_for_sync(vg_name, lv_name): -+ try: -+ yield -+ finally: -+ time.sleep(2) -+ while True: -+ ret, out, _err = run_command("LC_ALL=C lvs -o copy_percent --noheadings %s/%s" % (vg_name, lv_name)) -+ if ret != 0: -+ break -+ if int(float(out)) == 100: -+ break -+ time.sleep(1) -+ -+ - class LVMTestCase(unittest.TestCase): - @classmethod - def setUpClass(cls): -@@ -801,9 +818,10 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - succ = BlockDev.lvm_lvremove("testVG", "testLV", True, None) - self.assertTrue(succ) - -- # try to create a mirrored LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) -- self.assertTrue(succ) -+ with wait_for_sync("testVG", "testLV"): -+ # try to create a mirrored LV -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) -+ self.assertTrue(succ) - - # verify that the LV has the requested segtype - info = BlockDev.lvm_lvinfo("testVG", "testLV") -@@ -812,9 +830,10 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - succ = BlockDev.lvm_lvremove("testVG", "testLV", True, None) - self.assertTrue(succ) - -- # try to create a raid1 LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) -- self.assertTrue(succ) -+ with wait_for_sync("testVG", "testLV"): -+ # try to create a raid1 LV -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) -+ self.assertTrue(succ) - - # verify that the LV has the requested segtype - info = BlockDev.lvm_lvinfo("testVG", "testLV") -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index e349817..12b78ca 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -7,12 +7,29 @@ import six - import re - import shutil - import subprocess -+import time -+from contextlib import contextmanager - from distutils.version import LooseVersion - - from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command, read_file - from gi.repository import BlockDev, GLib - - -+@contextmanager -+def wait_for_sync(vg_name, lv_name): -+ try: -+ yield -+ finally: -+ time.sleep(2) -+ while True: -+ info = BlockDev.lvm_lvinfo(vg_name, lv_name) -+ if not info: -+ break -+ if info.copy_percent == 100: -+ break -+ time.sleep(1) -+ -+ - class LVMTestCase(unittest.TestCase): - - @classmethod -@@ -737,9 +754,10 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - succ = BlockDev.lvm_lvremove("testVG", "testLV", True, None) - self.assertTrue(succ) - -- # try to create a mirrored LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) -- self.assertTrue(succ) -+ with wait_for_sync("testVG", "testLV"): -+ # try to create a mirrored LV -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) -+ self.assertTrue(succ) - - # verify that the LV has the requested segtype - info = BlockDev.lvm_lvinfo("testVG", "testLV") -@@ -748,9 +766,10 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - succ = BlockDev.lvm_lvremove("testVG", "testLV", True, None) - self.assertTrue(succ) - -- # try to create a raid1 LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) -- self.assertTrue(succ) -+ with wait_for_sync("testVG", "testLV"): -+ # try to create a raid1 LV -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) -+ self.assertTrue(succ) - - # verify that the LV has the requested segtype - info = BlockDev.lvm_lvinfo("testVG", "testLV") --- -2.31.1 - - -From 36dbac970bc4a052dbd97f51eb47379036d15b6e Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 16 Dec 2021 12:27:33 +0100 -Subject: [PATCH 2/2] tests: Make smaller images for test_lvcreate_type - -We are now waiting for the initial resync for the RAID/mirror LVs -which means we are trying to overwrite the entire 1 GB image which -doesn't fit in /tmp on our CI machines. ---- - tests/lvm_dbus_tests.py | 16 +++++++++++----- - tests/lvm_test.py | 15 ++++++++++----- - 2 files changed, 21 insertions(+), 10 deletions(-) - -diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py -index 5ce653e..723aabb 100644 ---- a/tests/lvm_dbus_tests.py -+++ b/tests/lvm_dbus_tests.py -@@ -313,14 +313,17 @@ class LvmNoDevTestCase(LVMTestCase): - - @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") - class LvmPVonlyTestCase(LVMTestCase): -+ -+ _sparse_size = 1024**3 -+ - # :TODO: - # * test pvmove (must create two PVs, a VG, a VG and some data in it - # first) - # * some complex test for pvs, vgs, lvs, pvinfo, vginfo and lvinfo - def setUp(self): - self.addCleanup(self._clean_up) -- self.dev_file = create_sparse_tempfile("lvm_test", 1024**3) -- self.dev_file2 = create_sparse_tempfile("lvm_test", 1024**3) -+ self.dev_file = create_sparse_tempfile("lvm_test", self._sparse_size) -+ self.dev_file2 = create_sparse_tempfile("lvm_test", self._sparse_size) - try: - self.loop_dev = create_lio_device(self.dev_file) - except RuntimeError as e: -@@ -795,6 +798,9 @@ class LvmTestLVcreateWithExtra(LvmPVVGLVTestCase): - - @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") - class LvmTestLVcreateType(LvmPVVGLVTestCase): -+ -+ _sparse_size = 200 * 1024**2 -+ - def test_lvcreate_type(self): - """Verify it's possible to create LVs with various types""" - -@@ -808,7 +814,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - self.assertTrue(succ) - - # try to create a striped LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "striped", [self.loop_dev, self.loop_dev2], None) -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "striped", [self.loop_dev, self.loop_dev2], None) - self.assertTrue(succ) - - # verify that the LV has the requested segtype -@@ -820,7 +826,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - - with wait_for_sync("testVG", "testLV"): - # try to create a mirrored LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) - self.assertTrue(succ) - - # verify that the LV has the requested segtype -@@ -832,7 +838,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - - with wait_for_sync("testVG", "testLV"): - # try to create a raid1 LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) - self.assertTrue(succ) - - # verify that the LV has the requested segtype -diff --git a/tests/lvm_test.py b/tests/lvm_test.py -index 12b78ca..97f6c69 100644 ---- a/tests/lvm_test.py -+++ b/tests/lvm_test.py -@@ -302,14 +302,17 @@ class LvmNoDevTestCase(LVMTestCase): - BlockDev.lvm_cache_get_mode_from_str("bla") - - class LvmPVonlyTestCase(LVMTestCase): -+ -+ _sparse_size = 1024**3 -+ - # :TODO: - # * test pvmove (must create two PVs, a VG, a VG and some data in it - # first) - # * some complex test for pvs, vgs, lvs, pvinfo, vginfo and lvinfo - def setUp(self): - self.addCleanup(self._clean_up) -- self.dev_file = create_sparse_tempfile("lvm_test", 1024**3) -- self.dev_file2 = create_sparse_tempfile("lvm_test", 1024**3) -+ self.dev_file = create_sparse_tempfile("lvm_test", self._sparse_size) -+ self.dev_file2 = create_sparse_tempfile("lvm_test", self._sparse_size) - try: - self.loop_dev = create_lio_device(self.dev_file) - except RuntimeError as e: -@@ -731,6 +734,8 @@ class LvmTestLVcreateWithExtra(LvmPVVGLVTestCase): - self.assertTrue(succ) - - class LvmTestLVcreateType(LvmPVVGLVTestCase): -+ _sparse_size = 200 * 1024**2 -+ - def test_lvcreate_type(self): - """Verify it's possible to create LVs with various types""" - -@@ -744,7 +749,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - self.assertTrue(succ) - - # try to create a striped LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "striped", [self.loop_dev, self.loop_dev2], None) -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "striped", [self.loop_dev, self.loop_dev2], None) - self.assertTrue(succ) - - # verify that the LV has the requested segtype -@@ -756,7 +761,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - - with wait_for_sync("testVG", "testLV"): - # try to create a mirrored LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) - self.assertTrue(succ) - - # verify that the LV has the requested segtype -@@ -768,7 +773,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): - - with wait_for_sync("testVG", "testLV"): - # try to create a raid1 LV -- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) -+ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) - self.assertTrue(succ) - - # verify that the LV has the requested segtype --- -2.31.1 - diff --git a/0012-tests-Lower-expected-free-space-on-newly-created-Ext-filesystems.patch b/0012-tests-Lower-expected-free-space-on-newly-created-Ext-filesystems.patch deleted file mode 100644 index 66b5999..0000000 --- a/0012-tests-Lower-expected-free-space-on-newly-created-Ext-filesystems.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 8978b7e6913f904bea887b0c542f9f82c969c2cf Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Wed, 1 Sep 2021 11:36:29 +0200 -Subject: [PATCH] tests: Lower expected free space on newly created Ext - filesystems - -With e2fsprogs 1.46.4 we now see less than 90 % of free blocks on -newly created devices in our tests. ---- - tests/fs_test.py | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - -diff --git a/tests/fs_test.py b/tests/fs_test.py -index 551b6a7b..6b0134bf 100644 ---- a/tests/fs_test.py -+++ b/tests/fs_test.py -@@ -425,8 +425,8 @@ def _test_ext_get_info(self, mkfs_function, info_function): - self.assertTrue(fi) - self.assertEqual(fi.block_size, 1024) - self.assertEqual(fi.block_count, 100 * 1024**2 / 1024) -- # at least 90 % should be available, so it should be reported -- self.assertGreater(fi.free_blocks, 0.90 * 100 * 1024**2 / 1024) -+ # at least 80 % should be available, so it should be reported -+ self.assertGreater(fi.free_blocks, 0.80 * 100 * 1024**2 / 1024) - self.assertEqual(fi.label, "") - # should be an non-empty string - self.assertTrue(fi.uuid) -@@ -436,8 +436,8 @@ def _test_ext_get_info(self, mkfs_function, info_function): - fi = BlockDev.fs_ext4_get_info(self.loop_dev) - self.assertEqual(fi.block_size, 1024) - self.assertEqual(fi.block_count, 100 * 1024**2 / 1024) -- # at least 90 % should be available, so it should be reported -- self.assertGreater(fi.free_blocks, 0.90 * 100 * 1024**2 / 1024) -+ # at least 80 % should be available, so it should be reported -+ self.assertGreater(fi.free_blocks, 0.80 * 100 * 1024**2 / 1024) - self.assertEqual(fi.label, "") - # should be an non-empty string - self.assertTrue(fi.uuid) -@@ -515,8 +515,8 @@ def _test_ext_resize(self, mkfs_function, info_function, resize_function): - self.assertTrue(fi) - self.assertEqual(fi.block_size, 1024) - self.assertEqual(fi.block_count, 100 * 1024**2 / 1024) -- # at least 90 % should be available, so it should be reported -- self.assertGreater(fi.free_blocks, 0.90 * 100 * 1024**2 / 1024) -+ # at least 80 % should be available, so it should be reported -+ self.assertGreater(fi.free_blocks, 0.80 * 100 * 1024**2 / 1024) - - succ = resize_function(self.loop_dev, 50 * 1024**2, None) - self.assertTrue(succ) -@@ -532,8 +532,8 @@ def _test_ext_resize(self, mkfs_function, info_function, resize_function): - self.assertTrue(fi) - self.assertEqual(fi.block_size, 1024) - self.assertEqual(fi.block_count, 100 * 1024**2 / 1024) -- # at least 90 % should be available, so it should be reported -- self.assertGreater(fi.free_blocks, 0.90 * 100 * 1024**2 / 1024) -+ # at least 80 % should be available, so it should be reported -+ self.assertGreater(fi.free_blocks, 0.80 * 100 * 1024**2 / 1024) - - # resize again - succ = resize_function(self.loop_dev, 50 * 1024**2, None) -@@ -550,8 +550,8 @@ def _test_ext_resize(self, mkfs_function, info_function, resize_function): - self.assertTrue(fi) - self.assertEqual(fi.block_size, 1024) - self.assertEqual(fi.block_count, 100 * 1024**2 / 1024) -- # at least 90 % should be available, so it should be reported -- self.assertGreater(fi.free_blocks, 0.90 * 100 * 1024**2 / 1024) -+ # at least 80 % should be available, so it should be reported -+ self.assertGreater(fi.free_blocks, 0.80 * 100 * 1024**2 / 1024) - - def test_ext2_resize(self): - """Verify that it is possible to resize an ext2 file system""" diff --git a/0013-ddf-mdadm-uuid-parse-fix.patch b/0013-ddf-mdadm-uuid-parse-fix.patch deleted file mode 100644 index 7206cee..0000000 --- a/0013-ddf-mdadm-uuid-parse-fix.patch +++ /dev/null @@ -1,275 +0,0 @@ -From 9bcaddbe97067f10e643a7d99fa13716126f6e60 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 25 Aug 2020 14:09:18 +0200 -Subject: [PATCH 1/4] mdraid: Do not ignore errors from bd_md_canonicalize_uuid - in bd_md_examine - ---- - src/plugins/mdraid.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c -index b97bc641..d41b6372 100644 ---- a/src/plugins/mdraid.c -+++ b/src/plugins/mdraid.c -@@ -983,12 +983,24 @@ BDMDExamineData* bd_md_examine (const gchar *device, GError **error) { - orig_data = ret->uuid; - if (orig_data) { - ret->uuid = bd_md_canonicalize_uuid (orig_data, error); -+ if (!ret->uuid) { -+ g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", orig_data); -+ g_free (orig_data); -+ bd_md_examine_data_free (ret); -+ return NULL; -+ } - g_free (orig_data); - } - - orig_data = ret->dev_uuid; - if (orig_data) { - ret->dev_uuid = bd_md_canonicalize_uuid (orig_data, error); -+ if (!ret->uuid) { -+ g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", orig_data); -+ g_free (orig_data); -+ bd_md_examine_data_free (ret); -+ return NULL; -+ } - g_free (orig_data); - } - --- -2.37.1 - - -From 1805734e8315d5fb73f036dae043312c88f3c3ec Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Tue, 25 Aug 2020 14:12:52 +0200 -Subject: [PATCH 2/4] mdraid: Try harder to get container UUID in bd_md_examine - -For containers UUID is not printed in 'mdadm --examine' but it is -printed when using the '--export' option. ---- - src/plugins/mdraid.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c -index d41b6372..3a23cf2e 100644 ---- a/src/plugins/mdraid.c -+++ b/src/plugins/mdraid.c -@@ -1023,6 +1023,17 @@ BDMDExamineData* bd_md_examine (const gchar *device, GError **error) { - value++; - g_free (ret->level); - ret->level = g_strdup (value); -+ } else if (!ret->uuid && g_str_has_prefix (output_fields[i], "MD_UUID=")) { -+ value = strchr (output_fields[i], '='); -+ value++; -+ ret->uuid = bd_md_canonicalize_uuid (value, error); -+ if (!ret->uuid) { -+ g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", orig_data); -+ g_free (orig_data); -+ bd_md_examine_data_free (ret); -+ g_strfreev (output_fields); -+ return NULL; -+ } - } - g_strfreev (output_fields); - --- -2.37.1 - - -From 166756338f90d90b32ae0989db706dd52f7df234 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 4 Aug 2022 12:47:53 +0200 -Subject: [PATCH 3/4] mdraid: Try harder to get container UUID in bd_md_detail - -Similarly to bd_md_examine (see a10ad4e0), "mdadm --detail" -doesn't contain container UUID, we need to need "--export" for -that. ---- - src/plugins/mdraid.c | 43 +++++++++++++++++++++++++++++++++++-------- - 1 file changed, 35 insertions(+), 8 deletions(-) - -diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c -index 3a23cf2e..67bdc1f9 100644 ---- a/src/plugins/mdraid.c -+++ b/src/plugins/mdraid.c -@@ -1093,13 +1093,16 @@ BDMDExamineData* bd_md_examine (const gchar *device, GError **error) { - * Tech category: %BD_MD_TECH_MDRAID-%BD_MD_TECH_MODE_QUERY - */ - BDMDDetailData* bd_md_detail (const gchar *raid_spec, GError **error) { -- const gchar *argv[] = {"mdadm", "--detail", NULL, NULL}; -+ const gchar *argv[] = {"mdadm", "--detail", NULL, NULL, NULL}; - gchar *output = NULL; - gboolean success = FALSE; - GHashTable *table = NULL; - guint num_items = 0; - gchar *orig_uuid = NULL; -- gchar *mdadm_spec = NULL; -+ g_autofree gchar *mdadm_spec = NULL; -+ gchar *value = NULL; -+ gchar **output_fields = NULL; -+ guint i = 0; - BDMDDetailData *ret = NULL; - - if (!check_deps (&avail_deps, DEPS_MDADM_MASK, deps, DEPS_LAST, &deps_check_lock, error)) -@@ -1113,16 +1116,13 @@ BDMDDetailData* bd_md_detail (const gchar *raid_spec, GError **error) { - argv[2] = mdadm_spec; - - success = bd_utils_exec_and_capture_output (argv, NULL, &output, error); -- if (!success) { -- g_free (mdadm_spec); -+ if (!success) - /* error is already populated */ - return NULL; -- } - - table = parse_mdadm_vars (output, "\n", ":", &num_items); - g_free (output); - if (!table || (num_items == 0)) { -- g_free (mdadm_spec); - /* something bad happened or some expected items were missing */ - g_set_error (error, BD_MD_ERROR, BD_MD_ERROR_PARSE, "Failed to parse mddetail data"); - if (table) -@@ -1132,7 +1132,6 @@ BDMDDetailData* bd_md_detail (const gchar *raid_spec, GError **error) { - - ret = get_detail_data_from_table (table, TRUE); - if (!ret) { -- g_free (mdadm_spec); - g_set_error (error, BD_MD_ERROR, BD_MD_ERROR_PARSE, "Failed to get mddetail data"); - return NULL; - } -@@ -1145,7 +1144,35 @@ BDMDDetailData* bd_md_detail (const gchar *raid_spec, GError **error) { - g_free (orig_uuid); - } - -- g_free (mdadm_spec); -+ if (!ret->uuid) { -+ argv[2] = "--export"; -+ argv[3] = mdadm_spec; -+ success = bd_utils_exec_and_capture_output (argv, NULL, &output, error); -+ if (!success) { -+ /* error is already populated */ -+ bd_md_detail_data_free (ret); -+ return NULL; -+ } -+ -+ /* try to get a better information about RAID level because it may be -+ missing in the output without --export */ -+ output_fields = g_strsplit (output, "\n", 0); -+ g_free (output); -+ output = NULL; -+ for (i = 0; (i < g_strv_length (output_fields) - 1); i++) -+ if (g_str_has_prefix (output_fields[i], "MD_UUID=")) { -+ value = strchr (output_fields[i], '='); -+ value++; -+ ret->uuid = bd_md_canonicalize_uuid (value, error); -+ if (!ret->uuid) { -+ g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", value); -+ bd_md_detail_data_free (ret); -+ g_strfreev (output_fields); -+ return NULL; -+ } -+ } -+ g_strfreev (output_fields); -+ } - - return ret; - } --- -2.37.1 - - -From 25dd2f8c7cc3cf540902fc40e808faabda3c691a Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 4 Aug 2022 12:51:48 +0200 -Subject: [PATCH 4/4] Add a test case for DDF arrays/containers - ---- - tests/mdraid_test.py | 51 ++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 47 insertions(+), 4 deletions(-) - -diff --git a/tests/mdraid_test.py b/tests/mdraid_test.py -index 0b2bdc9b..38f43a0d 100644 ---- a/tests/mdraid_test.py -+++ b/tests/mdraid_test.py -@@ -6,7 +6,7 @@ from contextlib import contextmanager - import overrides_hack - import six - --from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test -+from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command - from gi.repository import BlockDev, GLib - - -@@ -90,14 +90,16 @@ class MDNoDevTestCase(MDTest): - - class MDTestCase(MDTest): - -+ _sparse_size = 10 * 1024**2 -+ - def setUp(self): - if os.uname()[-1] == "i686": - self.skipTest("Skipping hanging MD RAID tests on i686") - - self.addCleanup(self._clean_up) -- self.dev_file = create_sparse_tempfile("md_test", 10 * 1024**2) -- self.dev_file2 = create_sparse_tempfile("md_test", 10 * 1024**2) -- self.dev_file3 = create_sparse_tempfile("md_test", 10 * 1024**2) -+ self.dev_file = create_sparse_tempfile("md_test", self._sparse_size) -+ self.dev_file2 = create_sparse_tempfile("md_test", self._sparse_size) -+ self.dev_file3 = create_sparse_tempfile("md_test", self._sparse_size) - - try: - self.loop_dev = create_lio_device(self.dev_file) -@@ -586,6 +588,47 @@ class MDTestRequestSyncAction(MDTestCase): - action = f.read().strip() - self.assertEqual(action, "check") - -+ -+class MDTestDDFRAID(MDTestCase): -+ -+ _sparse_size = 50 * 1024**2 -+ -+ def _clean_up(self): -+ try: -+ BlockDev.md_deactivate("bd_test_ddf") -+ except: -+ pass -+ try: -+ BlockDev.md_deactivate(BlockDev.md_node_from_name("bd_test_ddf")) -+ except: -+ pass -+ -+ super(MDTestDDFRAID, self)._clean_up() -+ -+ def test_examine_ddf_container(self): -+ succ = BlockDev.md_create("bd_test_md", "container", -+ [self.loop_dev, self.loop_dev2], -+ 0, "ddf", False) -+ self.assertTrue(succ) -+ -+ # we cannot create the array with libblockdev because we cannot pass the --raid-devices option -+ ret, _out, err = run_command("mdadm --create /dev/md/bd_test_ddf --run --level=raid0 --raid-devices=2 /dev/md/bd_test_md") -+ self.assertEqual(ret, 0, msg="Failed to create RAID for DDF test: %s" % err) -+ -+ edata = BlockDev.md_examine(self.loop_dev) -+ self.assertIsNotNone(edata) -+ self.assertIsNotNone(edata.uuid) -+ self.assertEqual(edata.level, "container") -+ self.assertEqual(edata.metadata, "ddf") -+ -+ ddata = BlockDev.md_detail("bd_test_md") -+ self.assertIsNotNone(ddata) -+ self.assertIsNotNone(ddata.uuid) -+ self.assertEqual(ddata.uuid, edata.uuid) -+ self.assertEqual(ddata.level, "container") -+ self.assertEqual(ddata.metadata, "ddf") -+ -+ - class FakeMDADMutilTest(MDTest): - # no setUp nor tearDown needed, we are gonna use fake utils - @tag_test(TestTags.NOSTORAGE) --- -2.37.1 - diff --git a/0014-mdraid-Fix-copy-paste-error-when-checking-return-val.patch b/0014-mdraid-Fix-copy-paste-error-when-checking-return-val.patch deleted file mode 100644 index 5ff61dc..0000000 --- a/0014-mdraid-Fix-copy-paste-error-when-checking-return-val.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 04a8baf87820d8a13926e0b8db5cfa55f9f04420 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:26:57 +0200 -Subject: [PATCH 1/2] mdraid: Fix copy-paste error when checking return value - ---- - src/plugins/mdraid.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c -index 67bdc1f9..48abb72f 100644 ---- a/src/plugins/mdraid.c -+++ b/src/plugins/mdraid.c -@@ -995,7 +995,7 @@ BDMDExamineData* bd_md_examine (const gchar *device, GError **error) { - orig_data = ret->dev_uuid; - if (orig_data) { - ret->dev_uuid = bd_md_canonicalize_uuid (orig_data, error); -- if (!ret->uuid) { -+ if (!ret->dev_uuid) { - g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", orig_data); - g_free (orig_data); - bd_md_examine_data_free (ret); --- -2.37.1 - - -From 16a34bc5ddb19bc6dd1a845d87e8b748cbaedd2c Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Fri, 25 Sep 2020 14:41:20 +0200 -Subject: [PATCH 2/2] mdraid: Fix use after free - -Another copy-paste error. ---- - src/plugins/mdraid.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c -index 48abb72f..75143ea7 100644 ---- a/src/plugins/mdraid.c -+++ b/src/plugins/mdraid.c -@@ -1028,8 +1028,7 @@ BDMDExamineData* bd_md_examine (const gchar *device, GError **error) { - value++; - ret->uuid = bd_md_canonicalize_uuid (value, error); - if (!ret->uuid) { -- g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", orig_data); -- g_free (orig_data); -+ g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", value); - bd_md_examine_data_free (ret); - g_strfreev (output_fields); - return NULL; --- -2.37.1 - diff --git a/0015-tests-Fix-expected-extended-partition-flags-with-new.patch b/0015-tests-Fix-expected-extended-partition-flags-with-new.patch deleted file mode 100644 index 6acdd26..0000000 --- a/0015-tests-Fix-expected-extended-partition-flags-with-new.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 33b1cda56fdc76fdf96fe409f0308e1913965d16 Mon Sep 17 00:00:00 2001 -From: Vojtech Trefny -Date: Thu, 26 May 2022 12:44:47 +0200 -Subject: [PATCH] tests: Fix expected extended partition flags with new parted - -Latest libparted now creates all extended partitions as -PARTITION_EXT_LBA with the lba flag enabled by default. ---- - tests/part_test.py | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/tests/part_test.py b/tests/part_test.py -index 7408b479..762dc534 100644 ---- a/tests/part_test.py -+++ b/tests/part_test.py -@@ -356,7 +356,7 @@ class PartCreatePartFullCase(PartTestCase): - # as is the start of the first part from the start of the disk - self.assertTrue(abs(ps4.start - (ps3.start + ps3.size + 1)) < ps.start) - self.assertEqual(ps4.size, 10 * 1024**2) -- self.assertEqual(ps4.flags, 0) # no flags (combination of bit flags) -+ self.assertIn(ps4.flags, [0, 128]) # no flags or extended+lba (combination of bit flags) - - # no more primary partitions allowed in the MSDOS table - with self.assertRaises(GLib.GError): -@@ -404,7 +404,7 @@ class PartCreatePartFullCase(PartTestCase): - # as is the start of the first part from the start of the disk - self.assertTrue(abs(ps3.start - (ps2.start + ps2.size + 1)) < ps.start) - self.assertEqual(ps3.size, 30 * 1024**2) -- self.assertEqual(ps3.flags, 0) # no flags (combination of bit flags) -+ self.assertIn(ps3.flags, [0, 128]) # no flags or extended+lba (combination of bit flags) - - # the logical partition has number 5 even though the extended partition - # has number 3 -@@ -871,7 +871,7 @@ class PartGetPartByPos(PartTestCase): - # as is the start of the first part from the start of the disk - self.assertTrue(abs(ps3.start - (ps2.start + ps2.size + 1)) < ps.start) - self.assertEqual(ps3.size, 35 * 1024**2) -- self.assertEqual(ps3.flags, 0) # no flags (combination of bit flags) -+ self.assertIn(ps3.flags, [0, 128]) # no flags or extended+lba (combination of bit flags) - - # the logical partition has number 5 even though the extended partition - # has number 3 --- -2.37.1 - diff --git a/libblockdev.spec b/libblockdev.spec index 328f592..241d66f 100644 --- a/libblockdev.spec +++ b/libblockdev.spec @@ -124,28 +124,15 @@ %define configure_opts %{?python2_copts} %{?python3_copts} %{?bcache_copts} %{?lvm_dbus_copts} %{?btrfs_copts} %{?crypto_copts} %{?dm_copts} %{?loop_copts} %{?lvm_copts} %{?lvm_dbus_copts} %{?mdraid_copts} %{?mpath_copts} %{?swap_copts} %{?kbd_copts} %{?part_copts} %{?fs_copts} %{?nvdimm_copts} %{?vdo_copts} %{?tools_copts} %{?gi_copts} Name: libblockdev -Version: 2.25 -Release: 14%{?dist} +Version: 2.28 +Release: 1%{?dist} Summary: A library for low-level manipulation with block devices License: LGPLv2+ URL: https://github.com/storaged-project/libblockdev Source0: https://github.com/storaged-project/libblockdev/releases/download/%{version}-%{release}/%{name}-%{version}.tar.gz Patch0: libblockdev-gcc11.patch -Patch1: 0001-Fix-comparing-DM-RAID-member-devices-UUID.patch -Patch2: 0002-Fix-default-key-size-for-non-XTS-ciphers.patch -Patch3: 0003-Memory-leaks-fixes-backport.patch -Patch4: 0004-Adapt-to-dosfstools-4.2-changes.patch -Patch5: 0005-Add-workarounds-for-some-LVM-test-issues.patch -Patch6: 0006-Misc-test-fixes-backport.patch -Patch7: 0007-lvm-devices-file-support.patch -Patch8: 0008-lvm-Fix-reading-statistics-for-VDO-pools-with-VDO-8.patch -Patch9: 0009-vdo_stats-Default-to-100-savings-for-invalid-savings.patch -Patch10: 0010-Add-support-for-creating-and-activating-integrity-de.patch -Patch11: 0011-tests-Wait-for-raid-and-mirrored-LVs-to-be-synced-be.patch -Patch12: 0012-tests-Lower-expected-free-space-on-newly-created-Ext-filesystems.patch -Patch13: 0013-ddf-mdadm-uuid-parse-fix.patch -Patch14: 0014-mdraid-Fix-copy-paste-error-when-checking-return-val.patch -Patch15: 0015-tests-Fix-expected-extended-partition-flags-with-new.patch +Patch1: 0001-lvm-devices-file-support.patch +Patch2: 0002-Add-support-for-creating-and-activating-integrity-de.patch BuildRequires: make BuildRequires: glib2-devel @@ -167,6 +154,8 @@ BuildRequires: gtk-doc BuildRequires: glib2-doc BuildRequires: autoconf-archive +Requires: %{name}-utils%{?_isa} = %{version}-%{release} + # Needed for the escrow tests in tests/crypto_test.py, but not used to build # BuildRequires: volume_key # BuildRequires: nss-tools @@ -188,6 +177,7 @@ no information about VGs when creating an LV). Summary: Development files for libblockdev Requires: %{name}%{?_isa} = %{version}-%{release} Requires: glib2-devel +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} %description devel This package contains header files and pkg-config files needed for development @@ -244,7 +234,7 @@ with the libblockdev-utils library. %package btrfs BuildRequires: libbytesize-devel Summary: The BTRFS plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} Requires: btrfs-progs %description btrfs @@ -255,7 +245,7 @@ providing the BTRFS-related functionality. Summary: Development files for the libblockdev-btrfs plugin/library Requires: %{name}-btrfs%{?_isa} = %{version}-%{release} Requires: glib2-devel -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} %description btrfs-devel This package contains header files and pkg-config files needed for development @@ -265,6 +255,7 @@ with the libblockdev-btrfs plugin/library. %if %{with_crypto} %package crypto +Requires: %{name}-utils%{?_isa} = %{version}-%{release} BuildRequires: cryptsetup-devel BuildRequires: libblkid-devel @@ -282,6 +273,7 @@ providing the functionality related to encrypted devices (LUKS). %package crypto-devel Summary: Development files for the libblockdev-crypto plugin/library Requires: %{name}-crypto%{?_isa} = %{version}-%{release} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description crypto-devel @@ -298,7 +290,7 @@ BuildRequires: dmraid-devel %endif BuildRequires: systemd-devel Summary: The Device Mapper plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} Requires: device-mapper %if %{with_dmraid} Requires: dmraid @@ -317,7 +309,7 @@ Requires: systemd-devel %if %{with_dmraid} Requires: dmraid-devel %endif -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} %description dm-devel This package contains header files and pkg-config files needed for development @@ -331,7 +323,7 @@ BuildRequires: parted-devel BuildRequires: libblkid-devel BuildRequires: libmount-devel Summary: The FS plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} %description fs The libblockdev library plugin (and in the same time a standalone library) @@ -340,7 +332,7 @@ providing the functionality related to operations with file systems. %package fs-devel Summary: Development files for the libblockdev-fs plugin/library Requires: %{name}-fs%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel Requires: xfsprogs Requires: dosfstools @@ -355,7 +347,7 @@ with the libblockdev-fs plugin/library. %package kbd BuildRequires: libbytesize-devel Summary: The KBD plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} %if %{with_bcache} Requires: bcache-tools >= 1.0.8 %endif @@ -368,7 +360,7 @@ Bcache). %package kbd-devel Summary: Development files for the libblockdev-kbd plugin/library Requires: %{name}-kbd%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description kbd-devel @@ -380,7 +372,7 @@ with the libblockdev-kbd plugin/library. %if %{with_loop} %package loop Summary: The loop plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} %description loop The libblockdev library plugin (and in the same time a standalone library) @@ -389,7 +381,7 @@ providing the functionality related to loop devices. %package loop-devel Summary: Development files for the libblockdev-loop plugin/library Requires: %{name}-loop%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description loop-devel @@ -402,10 +394,8 @@ with the libblockdev-loop plugin/library. %package lvm BuildRequires: device-mapper-devel Summary: The LVM plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} Requires: lvm2 -# for thin_metadata_size -Requires: device-mapper-persistent-data %description lvm The libblockdev library plugin (and in the same time a standalone library) @@ -426,10 +416,8 @@ with the libblockdev-lvm plugin/library. %package lvm-dbus BuildRequires: device-mapper-devel Summary: The LVM plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 1.4 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} Requires: lvm2-dbusd >= 2.02.156 -# for thin_metadata_size -Requires: device-mapper-persistent-data %description lvm-dbus The libblockdev library plugin (and in the same time a standalone library) @@ -451,7 +439,7 @@ with the libblockdev-lvm-dbus plugin/library. %package mdraid BuildRequires: libbytesize-devel Summary: The MD RAID plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} Requires: mdadm %description mdraid @@ -461,7 +449,7 @@ providing the functionality related to MD RAID. %package mdraid-devel Summary: Development files for the libblockdev-mdraid plugin/library Requires: %{name}-mdraid%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description mdraid-devel @@ -474,8 +462,8 @@ with the libblockdev-mdraid plugin/library. %package mpath BuildRequires: device-mapper-devel Summary: The multipath plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 -Recommends: device-mapper-multipath +Requires: %{name}-utils%{?_isa} = %{version}-%{release} +Requires: device-mapper-multipath %description mpath The libblockdev library plugin (and in the same time a standalone library) @@ -484,7 +472,7 @@ providing the functionality related to multipath devices. %package mpath-devel Summary: Development files for the libblockdev-mpath plugin/library Requires: %{name}-mpath%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description mpath-devel @@ -497,7 +485,7 @@ with the libblockdev-mpath plugin/library. BuildRequires: ndctl-devel BuildRequires: libuuid-devel Summary: The NVDIMM plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} Requires: ndctl %description nvdimm @@ -507,7 +495,7 @@ providing the functionality related to operations with NVDIMM devices. %package nvdimm-devel Summary: Development files for the libblockdev-nvdimm plugin/library Requires: %{name}-nvdimm%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description nvdimm-devel @@ -520,7 +508,7 @@ with the libblockdev-nvdimm plugin/library. %package part BuildRequires: parted-devel Summary: The partitioning plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} Requires: gdisk Requires: util-linux @@ -531,7 +519,7 @@ providing the functionality related to partitioning. %package part-devel Summary: Development files for the libblockdev-part plugin/library Requires: %{name}-part%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description part-devel @@ -544,7 +532,7 @@ with the libblockdev-part plugin/library. %package swap BuildRequires: libblkid-devel Summary: The swap plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} Requires: util-linux %description swap @@ -554,7 +542,7 @@ providing the functionality related to swap devices. %package swap-devel Summary: Development files for the libblockdev-swap plugin/library Requires: %{name}-swap%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description swap-devel @@ -568,7 +556,7 @@ with the libblockdev-swap plugin/library. BuildRequires: libbytesize-devel BuildRequires: libyaml-devel Summary: The vdo plugin for the libblockdev library -Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: %{name}-utils%{?_isa} = %{version}-%{release} # weak dependencies doesn't work on older RHEL %if (0%{?rhel} && 0%{?rhel} <= 7) @@ -588,7 +576,7 @@ providing the functionality related to VDO devices. %package vdo-devel Summary: Development files for the libblockdev-vdo plugin/library Requires: %{name}-vdo%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description vdo-devel @@ -599,8 +587,8 @@ with the libblockdev-vdo plugin/library. %if %{with_tools} %package tools Summary: Various nice tools based on libblockdev -Requires: %{name} -Requires: %{name}-lvm +Requires: %{name} = %{version}-%{release} +Requires: %{name}-lvm = %{version}-%{release} BuildRequires: libbytesize-devel %if %{with_lvm_dbus} == 1 Recommends: %{name}-lvm-dbus @@ -615,6 +603,7 @@ Various nice storage-related tools based on libblockdev. %package s390 Summary: The s390 plugin for the libblockdev library Requires: s390utils +Requires: %{name}-utils%{?_isa} = %{version}-%{release} %description s390 The libblockdev library plugin (and in the same time a standalone library) @@ -623,7 +612,7 @@ providing the functionality related to s390 devices. %package s390-devel Summary: Development files for the libblockdev-s390 plugin/library Requires: %{name}-s390%{?_isa} = %{version}-%{release} -Requires: %{name}-utils-devel%{?_isa} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} Requires: glib2-devel %description s390-devel @@ -700,19 +689,6 @@ A meta-package that pulls all the libblockdev plugins as dependencies. %patch0 -p1 %patch1 -p1 %patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 %build autoreconf -ivf @@ -1016,6 +992,14 @@ find %{buildroot} -type f -name "*.la" | xargs %{__rm} %files plugins-all %changelog +* Wed Sep 14 2022 Vojtech Trefny - 2.28-1 +- Rebase to the latest upstream release 2.28 + Resolves: rhbz#2123346 +- Add dependency on device-mapper-multipath to libblockdev-mpath + Resolves: rhbz#2121072 +- Fix spec issues found by rpminspect + Resolves: rhbz#2116544 + * Mon Aug 08 2022 Vojtech Trefny - 2.25-14 - tests: Fix expected extended partition flags with new parted Related: rhbz#2109026 diff --git a/sources b/sources index 2c30c6a..acee312 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (libblockdev-2.25.tar.gz) = 628d05f3a257b44208a9d0b5d84ae248fefd415812d9a93d132c03039b09fefc4d6110beb9aa0d3072e3f0c992e642d7867d0241209056538f132f86a748e195 +SHA512 (libblockdev-2.28.tar.gz) = 9e01c41db4f728c8e81e710c6bb4725bbe34b3a7de25ff7f57b7b88ca6b7b5debbe858947585d314770036b2c3c533f9f8ff3d038b7ca50eee3d18f9fbe0d392