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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
+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 <vtrefny@redhat.com>
+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 <vtrefny@redhat.com>
+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 <vtrefny@redhat.com>
+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 <vtrefny@redhat.com>
+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 <vtrefny@redhat.com>
+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 <vtrefny@redhat.com>
+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 <vtrefny@redhat.com>
+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 <glib.h>
+ #include <blockdev/utils.h>
++#include <libcryptsetup.h>
+ 
+ #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, &params);
++    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, &params);
++    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 <vtrefny@redhat.com>
+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 <vtrefny@redhat.com>
+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 <glib.h>
+ #include <blockdev/utils.h>
+-#include <libcryptsetup.h>
+ 
+ #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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <blockdev/utils.h>
- 
- #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 <glib.h>
- #include <blockdev/utils.h>
- 
--#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 <vtrefny@redhat.com>
-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 <glib.h>
- #include <blockdev/utils.h>
-+#include <libdevmapper.h>
- 
- #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 <vtrefny@redhat.com>
-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 <glib.h>
- #include <math.h>
- #include <string.h>
--#include <libdevmapper.h>
- #include <unistd.h>
- #include <blockdev/utils.h>
- #include <gio/gio.h>
-@@ -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 <glib.h>
- #include <math.h>
- #include <string.h>
--#include <libdevmapper.h>
- #include <unistd.h>
- #include <blockdev/utils.h>
- 
-@@ -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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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/<pool>/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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <glib.h>
- #include <blockdev/utils.h>
-+#include <libcryptsetup.h>
- 
- #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, &params);
-+    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, &params);
-+    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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <glib.h>
- #include <blockdev/utils.h>
--#include <libcryptsetup.h>
- 
- #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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com>
-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 <vtrefny@redhat.com> - 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 <vtrefny@redhat.com> - 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