commit 59cf00642d1f233684b05192be62525b5ec884c9 Author: Toshaan Bharvani Date: Mon May 23 08:59:55 2022 +0200 initial package creation Signed-off-by: Toshaan Bharvani diff --git a/SOURCES/0001-Fix-comparing-DM-RAID-member-devices-UUID.patch b/SOURCES/0001-Fix-comparing-DM-RAID-member-devices-UUID.patch new file mode 100644 index 0000000..0c3eedc --- /dev/null +++ b/SOURCES/0001-Fix-comparing-DM-RAID-member-devices-UUID.patch @@ -0,0 +1,27 @@ +From 2da13152619ee7233650339797657b45088b2219 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 18 Aug 2020 09:44:29 +0200 +Subject: [PATCH] dm: Fix comparing DM RAID member devices UUID + +There is no "UUID" property in UDev we must use the "ID_FS_UUID" +one. +This comparison works only because most DM RAID members don't have +UUID so the check is skipped, but it fails for DDF RAID members +which have a special GUID/UUID in UDev database. +--- + src/plugins/dm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/plugins/dm.c b/src/plugins/dm.c +index a6412028..4ab0d2a4 100644 +--- a/src/plugins/dm.c ++++ b/src/plugins/dm.c +@@ -482,7 +482,7 @@ static gboolean raid_dev_matches_spec (struct raid_dev *raid_dev, const gchar *n + + context = udev_new (); + device = udev_device_new_from_subsystem_sysname (context, "block", dev_name); +- dev_uuid = udev_device_get_property_value (device, "UUID"); ++ dev_uuid = udev_device_get_property_value (device, "ID_FS_UUID"); + major_str = udev_device_get_property_value (device, "MAJOR"); + minor_str = udev_device_get_property_value (device, "MINOR"); + diff --git a/SOURCES/0002-Fix-default-key-size-for-non-XTS-ciphers.patch b/SOURCES/0002-Fix-default-key-size-for-non-XTS-ciphers.patch new file mode 100644 index 0000000..6292ac7 --- /dev/null +++ b/SOURCES/0002-Fix-default-key-size-for-non-XTS-ciphers.patch @@ -0,0 +1,97 @@ +From 5d29bc014a33d9bdc1c5fb4b8add2f38850f46a8 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 24 Feb 2021 14:44:03 +0100 +Subject: [PATCH] crypto: Fix default key size for non XTS ciphers + +512 bits should be default only for AES-XTS which needs two keys, +default for other modes must be 256 bits. + +resolves: rhbz#1931847 +--- + src/plugins/crypto.c | 11 +++++++++-- + src/plugins/crypto.h | 2 +- + tests/crypto_test.py | 36 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 46 insertions(+), 3 deletions(-) + +diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c +index f4a2e8f0..1e7043fa 100644 +--- a/src/plugins/crypto.c ++++ b/src/plugins/crypto.c +@@ -774,8 +774,15 @@ static gboolean luks_format (const gchar *device, const gchar *cipher, guint64 k + return FALSE; + } + +- /* resolve requested/default key_size (should be in bytes) */ +- key_size = (key_size != 0) ? (key_size / 8) : (DEFAULT_LUKS_KEYSIZE_BITS / 8); ++ if (key_size == 0) { ++ if (g_str_has_prefix (cipher_specs[1], "xts-")) ++ key_size = DEFAULT_LUKS_KEYSIZE_BITS * 2; ++ else ++ key_size = DEFAULT_LUKS_KEYSIZE_BITS; ++ } ++ ++ /* key_size should be in bytes */ ++ key_size = key_size / 8; + + /* wait for enough random data entropy (if requested) */ + if (min_entropy > 0) { +diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h +index 71a1438d..a38724d9 100644 +--- a/src/plugins/crypto.h ++++ b/src/plugins/crypto.h +@@ -36,7 +36,7 @@ typedef enum { + /* 20 chars * 6 bits per char (64-item charset) = 120 "bits of security" */ + #define BD_CRYPTO_BACKUP_PASSPHRASE_LENGTH 20 + +-#define DEFAULT_LUKS_KEYSIZE_BITS 512 ++#define DEFAULT_LUKS_KEYSIZE_BITS 256 + #define DEFAULT_LUKS_CIPHER "aes-xts-plain64" + #define DEFAULT_LUKS2_SECTOR_SIZE 512 + +diff --git a/tests/crypto_test.py b/tests/crypto_test.py +index 0609a070..0aecc032 100644 +--- a/tests/crypto_test.py ++++ b/tests/crypto_test.py +@@ -236,6 +236,42 @@ def test_luks2_format(self): + self.fail("Failed to get pbkdf information from:\n%s %s" % (out, err)) + self.assertEqual(int(m.group(1)), 5) + ++ def _get_luks1_key_size(self, device): ++ _ret, out, err = run_command("cryptsetup luksDump %s" % device) ++ m = re.search(r"MK bits:\s*(\S+)\s*", out) ++ if not m or len(m.groups()) != 1: ++ self.fail("Failed to get key size information from:\n%s %s" % (out, err)) ++ key_size = m.group(1) ++ if not key_size.isnumeric(): ++ self.fail("Failed to get key size information from: %s" % key_size) ++ return int(key_size) ++ ++ @tag_test(TestTags.SLOW, TestTags.CORE) ++ def test_luks_format_key_size(self): ++ """Verify that formating device as LUKS works""" ++ ++ # aes-xts: key size should default to 512 ++ succ = BlockDev.crypto_luks_format(self.loop_dev, "aes-xts-plain64", 0, PASSWD, None, 0) ++ self.assertTrue(succ) ++ ++ key_size = self._get_luks1_key_size(self.loop_dev) ++ self.assertEqual(key_size, 512) ++ ++ # aes-cbc: key size should default to 256 ++ succ = BlockDev.crypto_luks_format(self.loop_dev, "aes-cbc-essiv:sha256", 0, PASSWD, None, 0) ++ self.assertTrue(succ) ++ ++ key_size = self._get_luks1_key_size(self.loop_dev) ++ self.assertEqual(key_size, 256) ++ ++ # try specifying key size for aes-xts ++ succ = BlockDev.crypto_luks_format(self.loop_dev, "aes-xts-plain64", 256, PASSWD, None, 0) ++ self.assertTrue(succ) ++ ++ key_size = self._get_luks1_key_size(self.loop_dev) ++ self.assertEqual(key_size, 256) ++ ++ + class CryptoTestResize(CryptoTestCase): + + def _get_key_location(self, device): diff --git a/SOURCES/0003-Memory-leaks-fixes-backport.patch b/SOURCES/0003-Memory-leaks-fixes-backport.patch new file mode 100644 index 0000000..5c19421 --- /dev/null +++ b/SOURCES/0003-Memory-leaks-fixes-backport.patch @@ -0,0 +1,178 @@ +From 98cb3b9cf2046ba6e33db6ff400449c6a4827932 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Thu, 29 Apr 2021 12:38:49 +0200 +Subject: [PATCH 1/8] kbd: Fix memory leak + +--- + src/plugins/kbd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/plugins/kbd.c b/src/plugins/kbd.c +index a2908ecb..d5ae0ed7 100644 +--- a/src/plugins/kbd.c ++++ b/src/plugins/kbd.c +@@ -1035,6 +1035,7 @@ gboolean bd_kbd_bcache_destroy (const gchar *bcache_device, GError **error) { + + if (c_set_uuid) { + path = g_strdup_printf ("/sys/fs/bcache/%s/stop", c_set_uuid); ++ g_free (c_set_uuid); + success = bd_utils_echo_str_to_file ("1", path, error); + g_free (path); + if (!success) { + +From c6d226c70996f6006a3f6eff13f8264f03e95c4f Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 25 Sep 2020 14:22:58 +0200 +Subject: [PATCH 2/8] crypto: Fix memory leak + +--- + src/plugins/crypto.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c +index 1e7043fa..4fad9a85 100644 +--- a/src/plugins/crypto.c ++++ b/src/plugins/crypto.c +@@ -1275,6 +1275,7 @@ gboolean bd_crypto_luks_add_key (const gchar *device, const gchar *pass, const g + success = g_file_get_contents (nkey_file, &nkey_buf, &nbuf_len, error); + if (!success) { + g_prefix_error (error, "Failed to load key from file '%s': ", nkey_file); ++ g_free (key_buf); + return FALSE; + } + } else + +From 41b460fb81cf066e7ddc0bdda7f34db5e90b9f79 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 25 Sep 2020 14:23:24 +0200 +Subject: [PATCH 3/8] dm: Fix memory leak in the DM plugin and DM logging + redirect function + +--- + src/plugins/dm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/plugins/dm.c b/src/plugins/dm.c +index fb4e50b5..c9a735ed 100644 +--- a/src/plugins/dm.c ++++ b/src/plugins/dm.c +@@ -245,7 +245,8 @@ gchar* bd_dm_name_from_node (const gchar *dm_node, GError **error) { + g_free (sys_path); + + if (!success) { +- /* errror is already populated */ ++ /* error is already populated */ ++ g_free (ret); + return NULL; + } + + +From 8d085fbb15c18ca91a5eff89192391c5a0b3bb7a Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 25 Sep 2020 14:24:14 +0200 +Subject: [PATCH 4/8] fs: Fix memory leak + +--- + src/plugins/fs/mount.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/plugins/fs/mount.c b/src/plugins/fs/mount.c +index 43d64e8c..46e03ca4 100644 +--- a/src/plugins/fs/mount.c ++++ b/src/plugins/fs/mount.c +@@ -541,6 +541,7 @@ static gboolean run_as_user (MountFunc func, MountArgs *args, uid_t run_as_uid, + "Unknoen error while reading error."); + g_io_channel_unref (channel); + close (pipefd[0]); ++ g_free (error_msg); + return FALSE; + } + + +From 6c45f4ef1fc898d71cc2f13670adb508a6037c66 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 25 Sep 2020 14:26:24 +0200 +Subject: [PATCH 5/8] kbd: Fix memory leak + +--- + src/plugins/kbd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/plugins/kbd.c b/src/plugins/kbd.c +index d5ae0ed7..ff8bde17 100644 +--- a/src/plugins/kbd.c ++++ b/src/plugins/kbd.c +@@ -1255,6 +1255,7 @@ static gboolean get_cache_size_used (const gchar *cache_dev_sys, guint64 *size, + g_io_channel_unref (file); + + if (!found) { ++ g_free (line); + g_set_error (error, BD_KBD_ERROR, BD_KBD_ERROR_BCACHE_INVAL, + "Failed to get cache usage data"); + return FALSE; + +From 4f4e93dfca36421eb0e0cb2dec5d48df5bc2f363 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 25 Sep 2020 14:26:37 +0200 +Subject: [PATCH 6/8] lvm-dbus: Fix memory leak + +--- + src/plugins/lvm-dbus.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index b7b4480e..144551f5 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -2927,6 +2927,7 @@ gboolean bd_lvm_cache_detach (const gchar *vg_name, const gchar *cached_lv, gboo + lv_id = g_strdup_printf ("%s/%s", vg_name, cached_lv); + call_lvm_obj_method_sync (lv_id, CACHED_LV_INTF, "DetachCachePool", params, NULL, extra, TRUE, error); + g_free (lv_id); ++ g_free (cache_pool_name); + return ((*error) == NULL); + } + + +From 410a10bc2cfceeb550d72456573d4722b4207ddc Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 25 Sep 2020 14:27:22 +0200 +Subject: [PATCH 7/8] mdraid: Fix memory leak + +--- + src/plugins/mdraid.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c +index 74af744c..b97bc641 100644 +--- a/src/plugins/mdraid.c ++++ b/src/plugins/mdraid.c +@@ -1332,6 +1332,7 @@ gchar* bd_md_name_from_node (const gchar *node, GError **error) { + continue; + } + node_name = g_path_get_basename (dev_path); ++ g_free (dev_path); + if (g_strcmp0 (node_name, node) == 0) { + found = TRUE; + name = g_path_get_basename (*path_p); + +From 0d49e5d190e24fa89ae2795714d0276f24285b19 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 25 Sep 2020 14:27:54 +0200 +Subject: [PATCH 8/8] swap: Fix memory leak + +--- + src/plugins/swap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/plugins/swap.c b/src/plugins/swap.c +index 102780a7..115f8fca 100644 +--- a/src/plugins/swap.c ++++ b/src/plugins/swap.c +@@ -417,6 +417,7 @@ gboolean bd_swap_swapstatus (const gchar *device, GError **error) { + if (!real_device) { + /* the device doesn't exist and thus is not an active swap */ + g_clear_error (error); ++ g_free (file_content); + return FALSE; + } + } diff --git a/SOURCES/0004-Adapt-to-dosfstools-4.2-changes.patch b/SOURCES/0004-Adapt-to-dosfstools-4.2-changes.patch new file mode 100644 index 0000000..a32e4ae --- /dev/null +++ b/SOURCES/0004-Adapt-to-dosfstools-4.2-changes.patch @@ -0,0 +1,296 @@ +From cc522ec3717d909370af6181c7859c62fa0167df Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Mon, 22 Feb 2021 15:40:56 +0100 +Subject: [PATCH 1/2] fs: Allow using empty label for vfat with newest + dosfstools + +--- + src/plugins/fs/vfat.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/plugins/fs/vfat.c b/src/plugins/fs/vfat.c +index ff0c35a3..ce13f147 100644 +--- a/src/plugins/fs/vfat.c ++++ b/src/plugins/fs/vfat.c +@@ -232,10 +232,21 @@ gboolean bd_fs_vfat_repair (const gchar *device, const BDExtraArg **extra, GErro + */ + gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError **error) { + const gchar *args[4] = {"fatlabel", device, label, NULL}; ++ UtilDep dep = {"fatlabel", "4.2", "--version", "fatlabel\\s+([\\d\\.]+).+"}; ++ gboolean new_vfat = FALSE; + + if (!check_deps (&avail_deps, DEPS_FATLABEL_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; + ++ if (!label || g_strcmp0 (label, "") == 0) { ++ /* fatlabel >= 4.2 refuses to set empty label */ ++ new_vfat = bd_utils_check_util_version (dep.name, dep.version, ++ dep.ver_arg, dep.ver_regexp, ++ NULL); ++ if (new_vfat) ++ args[2] = "--reset"; ++ } ++ + return bd_utils_exec_and_report_error (args, NULL, error); + } + + +From c3c3583409c8ed8f99a840e0c70cc92ca1dd3c93 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 27 Apr 2021 14:06:59 +0200 +Subject: [PATCH 2/2] tests: Call fs_vfat_mkfs with "--mbr=n" extra option in + tests + +Without the option the newest dosfstools 4.2 will create a valid +MBR partition table with a simgle partition on the disk, see +dosfstools/dosfstools#95 for details. +--- + src/plugins/fs/vfat.c | 5 ++- + tests/fs_test.py | 76 +++++++++++++++++++++++++++++++++---------- + 2 files changed, 62 insertions(+), 19 deletions(-) + +diff --git a/src/plugins/fs/vfat.c b/src/plugins/fs/vfat.c +index ce13f147..6cb82537 100644 +--- a/src/plugins/fs/vfat.c ++++ b/src/plugins/fs/vfat.c +@@ -234,6 +234,7 @@ gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError * + const gchar *args[4] = {"fatlabel", device, label, NULL}; + UtilDep dep = {"fatlabel", "4.2", "--version", "fatlabel\\s+([\\d\\.]+).+"}; + gboolean new_vfat = FALSE; ++ GError *loc_error = NULL; + + if (!check_deps (&avail_deps, DEPS_FATLABEL_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; +@@ -242,9 +243,11 @@ gboolean bd_fs_vfat_set_label (const gchar *device, const gchar *label, GError * + /* fatlabel >= 4.2 refuses to set empty label */ + new_vfat = bd_utils_check_util_version (dep.name, dep.version, + dep.ver_arg, dep.ver_regexp, +- NULL); ++ &loc_error); + if (new_vfat) + args[2] = "--reset"; ++ else ++ g_clear_error (&loc_error); + } + + return bd_utils_exec_and_report_error (args, NULL, error); +diff --git a/tests/fs_test.py b/tests/fs_test.py +index 239cb47c..2233db4f 100644 +--- a/tests/fs_test.py ++++ b/tests/fs_test.py +@@ -5,10 +5,13 @@ + import tempfile + from contextlib import contextmanager + import utils +-from utils import run, create_sparse_tempfile, mount, umount, TestTags, tag_test ++from utils import run, create_sparse_tempfile, mount, umount, TestTags, tag_test, run_command ++import re + import six + import overrides_hack + ++from distutils.version import LooseVersion ++ + from gi.repository import BlockDev, GLib + + +@@ -29,9 +32,20 @@ def mounted(device, where, ro=False): + yield + umount(where) + ++ ++def _get_dosfstools_version(): ++ _ret, out, _err = run_command("mkfs.vfat --help") ++ # mkfs.fat 4.1 (2017-01-24) ++ m = re.search(r"mkfs\.fat ([\d\.]+)", out) ++ if not m or len(m.groups()) != 1: ++ raise RuntimeError("Failed to determine dosfstools version from: %s" % out) ++ return LooseVersion(m.groups()[0]) ++ ++ + class FSTestCase(unittest.TestCase): + + requested_plugins = BlockDev.plugin_specs_from_names(("fs", "loop")) ++ _vfat_version = _get_dosfstools_version() + + @classmethod + def setUpClass(cls): +@@ -66,6 +80,11 @@ def setUp(self): + + self.mount_dir = tempfile.mkdtemp(prefix="libblockdev.", suffix="ext4_test") + ++ if self._vfat_version <= LooseVersion("4.1"): ++ self._mkfs_options = None ++ else: ++ self._mkfs_options = [BlockDev.ExtraArg.new("--mbr=n", "")] ++ + def _clean_up(self): + try: + utils.delete_lio_device(self.loop_dev) +@@ -120,7 +139,10 @@ def test_generic_wipe(self): + + # vfat has multiple signatures on the device so it allows us to test the + # 'all' argument of fs_wipe() +- ret = run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) ++ if self._vfat_version >= LooseVersion("4.2"): ++ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1 --mbr=n" % self.loop_dev) ++ else: ++ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) + self.assertEqual(ret, 0) + + time.sleep(0.5) +@@ -142,7 +164,10 @@ def test_generic_wipe(self): + self.assertEqual(fs_type, b"") + + # now do the wipe all in a one step +- ret = run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) ++ if self._vfat_version >= LooseVersion("4.2"): ++ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1 --mbr=n" % self.loop_dev) ++ else: ++ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) + self.assertEqual(ret, 0) + + succ = BlockDev.fs_wipe(self.loop_dev, True) +@@ -197,7 +222,10 @@ def test_clean(self): + + # vfat has multiple signatures on the device so it allows us to test + # that clean removes all signatures +- ret = run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) ++ if self._vfat_version >= LooseVersion("4.2"): ++ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1 --mbr=n" % self.loop_dev) ++ else: ++ ret = utils.run("mkfs.vfat -I %s >/dev/null 2>&1" % self.loop_dev) + self.assertEqual(ret, 0) + + time.sleep(0.5) +@@ -744,9 +772,9 @@ def test_vfat_mkfs(self): + """Verify that it is possible to create a new vfat file system""" + + with self.assertRaises(GLib.GError): +- BlockDev.fs_vfat_mkfs("/non/existing/device", None) ++ BlockDev.fs_vfat_mkfs("/non/existing/device", self._mkfs_options) + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + # just try if we can mount the file system +@@ -764,7 +792,10 @@ def test_vfat_mkfs_with_label(self): + """Verify that it is possible to create an vfat file system with label""" + + ea = BlockDev.ExtraArg.new("-n", "TEST_LABEL") +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, [ea]) ++ if self._mkfs_options: ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, [ea] + self._mkfs_options) ++ else: ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, [ea]) + self.assertTrue(succ) + + fi = BlockDev.fs_vfat_get_info(self.loop_dev) +@@ -775,7 +806,7 @@ class VfatTestWipe(FSTestCase): + def test_vfat_wipe(self): + """Verify that it is possible to wipe an vfat file system""" + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + succ = BlockDev.fs_vfat_wipe(self.loop_dev) +@@ -805,7 +836,7 @@ class VfatTestCheck(FSTestCase): + def test_vfat_check(self): + """Verify that it is possible to check an vfat file system""" + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + succ = BlockDev.fs_vfat_check(self.loop_dev, None) +@@ -818,7 +849,7 @@ class VfatTestRepair(FSTestCase): + def test_vfat_repair(self): + """Verify that it is possible to repair an vfat file system""" + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + succ = BlockDev.fs_vfat_repair(self.loop_dev, None) +@@ -828,7 +859,7 @@ class VfatGetInfo(FSTestCase): + def test_vfat_get_info(self): + """Verify that it is possible to get info about an vfat file system""" + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + fi = BlockDev.fs_vfat_get_info(self.loop_dev) +@@ -841,7 +872,7 @@ class VfatSetLabel(FSTestCase): + def test_vfat_set_label(self): + """Verify that it is possible to set label of an vfat file system""" + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + fi = BlockDev.fs_vfat_get_info(self.loop_dev) +@@ -870,7 +901,7 @@ class VfatResize(FSTestCase): + def test_vfat_resize(self): + """Verify that it is possible to resize an vfat file system""" + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + # shrink +@@ -999,7 +1030,7 @@ def _remove_user(self): + def test_mount(self): + """ Test basic mounting and unmounting """ + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + tmp = tempfile.mkdtemp(prefix="libblockdev.", suffix="mount_test") +@@ -1104,7 +1135,7 @@ def test_mount_fstab(self): + fstab = utils.read_file("/etc/fstab") + self.addCleanup(utils.write_file, "/etc/fstab", fstab) + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + tmp = tempfile.mkdtemp(prefix="libblockdev.", suffix="mount_fstab_test") +@@ -1139,7 +1170,7 @@ def test_mount_fstab_user(self): + fstab = utils.read_file("/etc/fstab") + self.addCleanup(utils.write_file, "/etc/fstab", fstab) + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + tmp = tempfile.mkdtemp(prefix="libblockdev.", suffix="mount_fstab_user_test") +@@ -1423,7 +1454,16 @@ def expected_size(fi): + @tag_test(TestTags.UNSTABLE) + def test_vfat_generic_resize(self): + """Test generic resize function with a vfat file system""" +- self._test_generic_resize(mkfs_function=BlockDev.fs_vfat_mkfs) ++ def mkfs_vfat(device, options=None): ++ if self._vfat_version >= LooseVersion("4.2"): ++ if options: ++ return BlockDev.fs_vfat_mkfs(device, options + [BlockDev.ExtraArg.new("--mbr=n", "")]) ++ else: ++ return BlockDev.fs_vfat_mkfs(device, [BlockDev.ExtraArg.new("--mbr=n", "")]) ++ else: ++ return BlockDev.fs_vfat_mkfs(device, options) ++ ++ self._test_generic_resize(mkfs_function=mkfs_vfat) + + def _destroy_lvm(self): + run("vgremove --yes libbd_fs_tests >/dev/null 2>&1") +@@ -1539,7 +1579,7 @@ def test_freeze_xfs(self): + def test_freeze_vfat(self): + """ Test basic freezing and un-freezing with FAT """ + +- succ = BlockDev.fs_vfat_mkfs(self.loop_dev, None) ++ succ = BlockDev.fs_vfat_mkfs(self.loop_dev, self._mkfs_options) + self.assertTrue(succ) + + tmp = tempfile.mkdtemp(prefix="libblockdev.", suffix="freeze_test") diff --git a/SOURCES/0005-Add-workarounds-for-some-LVM-test-issues.patch b/SOURCES/0005-Add-workarounds-for-some-LVM-test-issues.patch new file mode 100644 index 0000000..c41d687 --- /dev/null +++ b/SOURCES/0005-Add-workarounds-for-some-LVM-test-issues.patch @@ -0,0 +1,157 @@ +From 7c31cc534f96766dd2e3427b09d0affca66b0745 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 23 Mar 2021 13:54:02 +0100 +Subject: [PATCH 1/3] tests: Do not try to remove VG before removing the VDO + pool + +--- + tests/lvm_dbus_tests.py | 6 +++--- + tests/lvm_test.py | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 8f2bb95d..b599fdd0 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1517,14 +1517,14 @@ def setUp(self): + self.assertTrue(succ) + + def _clean_up(self): +- BlockDev.lvm_vgremove("testVDOVG") +- BlockDev.lvm_pvremove(self.loop_dev) +- + try: + BlockDev.lvm_lvremove("testVDOVG", "vdoPool", True, None) + except: + pass + ++ BlockDev.lvm_vgremove("testVDOVG") ++ BlockDev.lvm_pvremove(self.loop_dev) ++ + try: + delete_lio_device(self.loop_dev) + except RuntimeError: +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 6f80a3ba..6c04faf9 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1437,14 +1437,14 @@ def setUp(self): + self.assertTrue(succ) + + def _clean_up(self): +- BlockDev.lvm_vgremove("testVDOVG") +- BlockDev.lvm_pvremove(self.loop_dev) +- + try: + BlockDev.lvm_lvremove("testVDOVG", "vdoPool", True, None) + except: + pass + ++ BlockDev.lvm_vgremove("testVDOVG") ++ BlockDev.lvm_pvremove(self.loop_dev) ++ + try: + delete_lio_device(self.loop_dev) + except RuntimeError: + +From 41b9d745b8c1a33221e15683f390bae180d1e960 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 23 Mar 2021 13:59:24 +0100 +Subject: [PATCH 2/3] tests: Force remove LVM VG /dev/ entry not removed by + vgremove + +The directory is sometimes not removed. This is a known bug that +causes subsequent test cases to fail. +--- + tests/lvm_dbus_tests.py | 6 ++++++ + tests/lvm_test.py | 6 ++++++ + 2 files changed, 12 insertions(+) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index b599fdd0..3278716e 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -399,6 +399,9 @@ def _clean_up(self): + except: + pass + ++ # XXX remove lingering /dev entries ++ shutil.rmtree("/dev/testVG", ignore_errors=True) ++ + LvmPVonlyTestCase._clean_up(self) + + @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") +@@ -1525,6 +1528,9 @@ def _clean_up(self): + BlockDev.lvm_vgremove("testVDOVG") + BlockDev.lvm_pvremove(self.loop_dev) + ++ # XXX remove lingering /dev entries ++ shutil.rmtree("/dev/testVDOVG", ignore_errors=True) ++ + try: + delete_lio_device(self.loop_dev) + except RuntimeError: +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 6c04faf9..d7e1f84c 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -378,6 +378,9 @@ def _clean_up(self): + except: + pass + ++ # XXX remove lingering /dev entries ++ shutil.rmtree("/dev/testVG", ignore_errors=True) ++ + LvmPVonlyTestCase._clean_up(self) + + class LvmTestVGcreateRemove(LvmPVVGTestCase): +@@ -1445,6 +1448,9 @@ def _clean_up(self): + BlockDev.lvm_vgremove("testVDOVG") + BlockDev.lvm_pvremove(self.loop_dev) + ++ # XXX remove lingering /dev entries ++ shutil.rmtree("/dev/testVDOVG", ignore_errors=True) ++ + try: + delete_lio_device(self.loop_dev) + except RuntimeError: + +From 4ecf0075cedf3a1d275d34b94ce5bb512c4e970e Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 23 Mar 2021 14:03:44 +0100 +Subject: [PATCH 3/3] tests: Tag LvmPVVGLVcachePoolCreateRemoveTestCase as + unstable + +LVM randomly fails to activate the newly created metadata LV. +Issue is reported to LVM and not yet fixed. +--- + tests/lvm_dbus_tests.py | 2 +- + tests/lvm_test.py | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 3278716e..4882da88 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1213,7 +1213,7 @@ def _clean_up(self): + + @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") + class LvmPVVGLVcachePoolCreateRemoveTestCase(LvmPVVGLVcachePoolTestCase): +- @tag_test(TestTags.SLOW) ++ @tag_test(TestTags.SLOW, TestTags.UNSTABLE) + def test_cache_pool_create_remove(self): + """Verify that is it possible to create and remove a cache pool""" + +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index d7e1f84c..eb94c917 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1129,7 +1129,7 @@ def _clean_up(self): + LvmPVVGLVTestCase._clean_up(self) + + class LvmPVVGLVcachePoolCreateRemoveTestCase(LvmPVVGLVcachePoolTestCase): +- @tag_test(TestTags.SLOW) ++ @tag_test(TestTags.SLOW, TestTags.UNSTABLE) + def test_cache_pool_create_remove(self): + """Verify that is it possible to create and remove a cache pool""" + diff --git a/SOURCES/0006-Misc-test-fixes-backport.patch b/SOURCES/0006-Misc-test-fixes-backport.patch new file mode 100644 index 0000000..12746c5 --- /dev/null +++ b/SOURCES/0006-Misc-test-fixes-backport.patch @@ -0,0 +1,144 @@ +From 77b8d17b0baf96a7a552fb8963afdbe8c3b18da7 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 2 Jun 2021 12:53:24 +0200 +Subject: [PATCH 1/4] tests: Make sure the test temp mount is always unmounted + +With try-finally the unmount function will always run even if the +test case fails. +--- + tests/fs_test.py | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/tests/fs_test.py b/tests/fs_test.py +index 2233db4f..de685b5f 100644 +--- a/tests/fs_test.py ++++ b/tests/fs_test.py +@@ -29,8 +29,10 @@ def check_output(args, ignore_retcode=True): + @contextmanager + def mounted(device, where, ro=False): + mount(device, where, ro) +- yield +- umount(where) ++ try: ++ yield ++ finally: ++ utils.umount(where) + + + def _get_dosfstools_version(): + +From aa802b6a2c9038069cfea7f821333367840a43ca Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 2 Jun 2021 13:05:17 +0200 +Subject: [PATCH 2/4] tests: Do not check that XFS shrink fails with xfsprogs + >= 5.12 + +xfsprogs 5.12 now has experimental support for shrinking, we need +more changes to support it properly so just skip this check for +now. +--- + tests/fs_test.py | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/tests/fs_test.py b/tests/fs_test.py +index de685b5f..551b6a7b 100644 +--- a/tests/fs_test.py ++++ b/tests/fs_test.py +@@ -44,6 +44,14 @@ def _get_dosfstools_version(): + return LooseVersion(m.groups()[0]) + + ++def _get_xfs_version(): ++ _ret, out, _err = utils.run_command("mkfs.xfs -V") ++ m = re.search(r"mkfs\.xfs version ([\d\.]+)", out) ++ if not m or len(m.groups()) != 1: ++ raise RuntimeError("Failed to determine xfsprogs version from: %s" % out) ++ return LooseVersion(m.groups()[0]) ++ ++ + class FSTestCase(unittest.TestCase): + + requested_plugins = BlockDev.plugin_specs_from_names(("fs", "loop")) +@@ -736,9 +744,11 @@ def test_xfs_resize(self): + self.assertEqual(fi.block_size * fi.block_count, 50 * 1024**2) + + # (still) impossible to shrink an XFS file system +- with mounted(lv, self.mount_dir): +- with self.assertRaises(GLib.GError): +- succ = BlockDev.fs_xfs_resize(self.mount_dir, 40 * 1024**2 / fi.block_size, None) ++ xfs_version = _get_xfs_version() ++ if xfs_version < LooseVersion("5.1.12"): ++ with mounted(lv, self.mount_dir): ++ with self.assertRaises(GLib.GError): ++ succ = BlockDev.fs_resize(lv, 40 * 1024**2) + + run("lvresize -L70M libbd_fs_tests/xfs_test >/dev/null 2>&1") + # should grow +@@ -1503,9 +1513,11 @@ def test_xfs_generic_resize(self): + self.assertEqual(fi.block_size * fi.block_count, 50 * 1024**2) + + # (still) impossible to shrink an XFS file system +- with mounted(lv, self.mount_dir): +- with self.assertRaises(GLib.GError): +- succ = BlockDev.fs_resize(lv, 40 * 1024**2) ++ xfs_version = _get_xfs_version() ++ if xfs_version < LooseVersion("5.1.12"): ++ with mounted(lv, self.mount_dir): ++ with self.assertRaises(GLib.GError): ++ succ = BlockDev.fs_resize(lv, 40 * 1024**2) + + run("lvresize -L70M libbd_fs_tests/xfs_test >/dev/null 2>&1") + # should grow + +From ca01b6021cce3ea6a2318e74de408757f933d947 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 2 Jun 2021 13:06:41 +0200 +Subject: [PATCH 3/4] tests: Temporarily skip + test_snapshotcreate_lvorigin_snapshotmerge + +With LVM DBus API the lvconvert job is never finished which means +the test run never finishes in our CI. +--- + tests/skip.yml | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tests/skip.yml b/tests/skip.yml +index 145d321d..e22e712d 100644 +--- a/tests/skip.yml ++++ b/tests/skip.yml +@@ -137,3 +137,9 @@ + - distro: "fedora" + version: ["31", "32"] + reason: "working with old-style LVM snapshots leads to deadlock in LVM tools" ++ ++- test: lvm_dbus_tests.LvmTestLVsnapshots.test_snapshotcreate_lvorigin_snapshotmerge ++ skip_on: ++ - distro: "centos" ++ version: "9" ++ reason: "snapshot merge doesn't work on CentOS 9 Stream with LVM DBus API" + +From d0c44cd3d182599433f352901796af7c403239eb Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 2 Jun 2021 13:08:09 +0200 +Subject: [PATCH 4/4] Fix skipping tests on Debian testing + +Testing now identifies itself as "Debian GNU/Linux 11 (bullseye)" +so the tests that should be skipped on testing needs to be skipped +on "11" too. +--- + tests/skip.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/skip.yml b/tests/skip.yml +index e22e712d..4134ee87 100644 +--- a/tests/skip.yml ++++ b/tests/skip.yml +@@ -37,7 +37,7 @@ + - test: fs_test.MountTest.test_mount_ntfs_ro + skip_on: + - distro: "debian" +- version: ["9", "10", "testing"] ++ version: ["9", "10", "11", "testing"] + reason: "NTFS mounting of read-only devices doesn't work as expected on Debian" + + - test: kbd_test.KbdZRAM* diff --git a/SOURCES/0007-lvm-devices-file-support.patch b/SOURCES/0007-lvm-devices-file-support.patch new file mode 100644 index 0000000..bc7c55c --- /dev/null +++ b/SOURCES/0007-lvm-devices-file-support.patch @@ -0,0 +1,1908 @@ +From e364883416785d51ff8eb132b63bd802ab0ccfe9 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 13 Jul 2021 13:22:05 +0200 +Subject: [PATCH 1/8] lvm: Allow configuring global "device filter" for LVM + commands + +Starting with 2.03.12 LVM introduces a new system for telling LVM +which devices it should use. The old device filters in config are +no longer working and we need to use either the system.devices +config file in /etc/lvm/devices (default behaviour) or specify +all allowed devices using the new --devices option. Because this +option must be specified for every call which might be incovenient +for our users, this commit introduces a new function to configure +this globally, which we already do for the --config option. +--- + src/lib/plugin_apis/lvm.api | 23 +++ + src/plugins/lvm-dbus.c | 74 ++++++++- + src/plugins/lvm.c | 97 ++++++++++-- + src/plugins/lvm.h | 4 + + tests/library_test.py | 304 ++++++++++++++++++++---------------- + tests/lvm_dbus_tests.py | 47 +++++- + tests/lvm_test.py | 50 ++++++ + tests/overrides_test.py | 23 ++- + 8 files changed, 469 insertions(+), 153 deletions(-) + +diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api +index 563c104..62f602f 100644 +--- a/src/lib/plugin_apis/lvm.api ++++ b/src/lib/plugin_apis/lvm.api +@@ -601,6 +601,7 @@ typedef enum { + BD_LVM_TECH_CACHE_CALCS, + BD_LVM_TECH_GLOB_CONF, + BD_LVM_TECH_VDO, ++ BD_LVM_TECH_DEVICES, + } BDLVMTech; + + typedef enum { +@@ -1214,6 +1215,28 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error); + */ + gchar* bd_lvm_get_global_config (GError **error); + ++/** ++ * bd_lvm_set_devices_filter: ++ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the devices filter was successfully set or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error); ++ ++/** ++ * bd_lvm_get_devices_filter: ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of ++ * the currently set LVM devices filter ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gchar** bd_lvm_get_devices_filter (GError **error); ++ + /** + * bd_lvm_cache_get_default_md_size: + * @cache_size: size of the cache to determine MD size for +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index 144551f..d1726ed 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -35,6 +35,8 @@ + static GMutex global_config_lock; + static gchar *global_config_str = NULL; + ++static gchar *global_devices_str = NULL; ++ + #define LVM_BUS_NAME "com.redhat.lvmdbus1" + #define LVM_OBJ_PREFIX "/com/redhat/lvmdbus1" + #define MANAGER_OBJ "/com/redhat/lvmdbus1/Manager" +@@ -247,6 +249,14 @@ static volatile guint avail_features = 0; + static volatile guint avail_module_deps = 0; + static GMutex deps_check_lock; + ++#define DEPS_LVMDEVICES 0 ++#define DEPS_LVMDEVICES_MASK (1 << DEPS_LVMDEVICES) ++#define DEPS_LAST 1 ++ ++static const UtilDep deps[DEPS_LAST] = { ++ {"lvmdevices", NULL, NULL, NULL}, ++}; ++ + #define DBUS_DEPS_LVMDBUSD 0 + #define DBUS_DEPS_LVMDBUSD_MASK (1 << DBUS_DEPS_LVMDBUSD) + #define DBUS_DEPS_LAST 1 +@@ -385,6 +395,8 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) { + return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error) && + check_features (&avail_features, FEATURES_VDO_MASK, features, FEATURES_LAST, &deps_check_lock, error) && + check_module_deps (&avail_module_deps, MODULE_DEPS_VDO_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error); ++ case BD_LVM_TECH_DEVICES: ++ return check_deps (&avail_deps, DEPS_LVMDEVICES_MASK, deps, DEPS_LAST, &deps_check_lock, error); + default: + /* everything is supported by this implementation of the plugin */ + return check_dbus_deps (&avail_dbus_deps, DBUS_DEPS_LVMDBUSD_MASK, dbus_deps, DBUS_DEPS_LAST, &deps_check_lock, error); +@@ -522,6 +534,7 @@ static gboolean unbox_params_and_add (GVariant *params, GVariantBuilder *builder + + static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gchar *method, GVariant *params, GVariant *extra_params, const BDExtraArg **extra_args, guint64 *task_id, guint64 *progress_id, gboolean lock_config, GError **error) { + GVariant *config = NULL; ++ GVariant *devices = NULL; + GVariant *param = NULL; + GVariantIter iter; + GVariantBuilder builder; +@@ -543,8 +556,8 @@ static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gch + if (lock_config) + g_mutex_lock (&global_config_lock); + +- if (global_config_str || extra_params || extra_args) { +- if (global_config_str || extra_args) { ++ if (global_config_str || global_devices_str || extra_params || extra_args) { ++ if (global_config_str || global_devices_str || extra_args) { + /* add the global config to the extra_params */ + g_variant_builder_init (&extra_builder, G_VARIANT_TYPE_DICTIONARY); + +@@ -565,6 +578,11 @@ static GVariant* call_lvm_method (const gchar *obj, const gchar *intf, const gch + g_variant_builder_add (&extra_builder, "{sv}", "--config", config); + added_extra = TRUE; + } ++ if (global_devices_str) { ++ devices = g_variant_new ("s", global_devices_str); ++ g_variant_builder_add (&extra_builder, "{sv}", "--devices", devices); ++ added_extra = TRUE; ++ } + + if (added_extra) + config_extra_params = g_variant_builder_end (&extra_builder); +@@ -2651,6 +2669,58 @@ gchar* bd_lvm_get_global_config (GError **error UNUSED) { + return ret; + } + ++/** ++ * bd_lvm_set_devices_filter: ++ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the devices filter was successfully set or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) { ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ g_mutex_lock (&global_config_lock); ++ ++ /* first free the old value */ ++ g_free (global_devices_str); ++ ++ /* now store the new one */ ++ if (!devices || !(*devices)) ++ global_devices_str = NULL; ++ else ++ global_devices_str = g_strjoinv (",", (gchar **) devices); ++ ++ g_mutex_unlock (&global_config_lock); ++ return TRUE; ++} ++ ++/** ++ * bd_lvm_get_devices_filter: ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of ++ * the currently set LVM devices filter ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gchar** bd_lvm_get_devices_filter (GError **error UNUSED) { ++ gchar **ret = NULL; ++ ++ g_mutex_lock (&global_config_lock); ++ ++ if (global_devices_str) ++ ret = g_strsplit (global_devices_str, ",", -1); ++ else ++ ret = NULL; ++ ++ g_mutex_unlock (&global_config_lock); ++ ++ return ret; ++} ++ + /** + * bd_lvm_cache_get_default_md_size: + * @cache_size: size of the cache to determine MD size for +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 2be1dbd..c0d8198 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -34,6 +34,8 @@ + static GMutex global_config_lock; + static gchar *global_config_str = NULL; + ++static gchar *global_devices_str = NULL; ++ + /** + * SECTION: lvm + * @short_description: plugin for operations with LVM +@@ -212,10 +214,13 @@ static GMutex deps_check_lock; + + #define DEPS_LVM 0 + #define DEPS_LVM_MASK (1 << DEPS_LVM) +-#define DEPS_LAST 1 ++#define DEPS_LVMDEVICES 1 ++#define DEPS_LVMDEVICES_MASK (1 << DEPS_LVMDEVICES) ++#define DEPS_LAST 2 + + static const UtilDep deps[DEPS_LAST] = { + {"lvm", LVM_MIN_VERSION, "version", "LVM version:\\s+([\\d\\.]+)"}, ++ {"lvmdevices", NULL, NULL, NULL}, + }; + + #define FEATURES_VDO 0 +@@ -327,6 +332,8 @@ gboolean bd_lvm_is_tech_avail (BDLVMTech tech, guint64 mode, GError **error) { + case BD_LVM_TECH_VDO: + return check_features (&avail_features, FEATURES_VDO_MASK, features, FEATURES_LAST, &deps_check_lock, error) && + check_module_deps (&avail_module_deps, MODULE_DEPS_VDO_MASK, module_deps, MODULE_DEPS_LAST, &deps_check_lock, error); ++ case BD_LVM_TECH_DEVICES: ++ return check_deps (&avail_deps, DEPS_LVMDEVICES_MASK, deps, DEPS_LAST, &deps_check_lock, error); + default: + /* everything is supported by this implementation of the plugin */ + return check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error); +@@ -337,6 +344,8 @@ static gboolean call_lvm_and_report_error (const gchar **args, const BDExtraArg + gboolean success = FALSE; + guint i = 0; + guint args_length = g_strv_length ((gchar **) args); ++ g_autofree gchar *config_arg = NULL; ++ g_autofree gchar *devices_arg = NULL; + + if (!check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; +@@ -345,20 +354,26 @@ static gboolean call_lvm_and_report_error (const gchar **args, const BDExtraArg + if (lock_config) + g_mutex_lock (&global_config_lock); + +- /* allocate enough space for the args plus "lvm", "--config" and NULL */ +- const gchar **argv = g_new0 (const gchar*, args_length + 3); ++ /* allocate enough space for the args plus "lvm", "--config", "--devices" and NULL */ ++ const gchar **argv = g_new0 (const gchar*, args_length + 4); + + /* construct argv from args with "lvm" prepended */ + argv[0] = "lvm"; + for (i=0; i < args_length; i++) + argv[i+1] = args[i]; +- argv[args_length + 1] = global_config_str ? g_strdup_printf("--config=%s", global_config_str) : NULL; +- argv[args_length + 2] = NULL; ++ if (global_config_str) { ++ config_arg = g_strdup_printf("--config=%s", global_config_str); ++ argv[++args_length] = config_arg; ++ } ++ if (global_devices_str) { ++ devices_arg = g_strdup_printf("--devices=%s", global_devices_str); ++ argv[++args_length] = devices_arg; ++ } ++ argv[++args_length] = NULL; + + success = bd_utils_exec_and_report_error (argv, extra, error); + if (lock_config) + g_mutex_unlock (&global_config_lock); +- g_free ((gchar *) argv[args_length + 1]); + g_free (argv); + + return success; +@@ -368,6 +383,8 @@ static gboolean call_lvm_and_capture_output (const gchar **args, const BDExtraAr + gboolean success = FALSE; + guint i = 0; + guint args_length = g_strv_length ((gchar **) args); ++ g_autofree gchar *config_arg = NULL; ++ g_autofree gchar *devices_arg = NULL; + + if (!check_deps (&avail_deps, DEPS_LVM_MASK, deps, DEPS_LAST, &deps_check_lock, error)) + return FALSE; +@@ -375,19 +392,25 @@ static gboolean call_lvm_and_capture_output (const gchar **args, const BDExtraAr + /* don't allow global config string changes during the run */ + g_mutex_lock (&global_config_lock); + +- /* allocate enough space for the args plus "lvm", "--config" and NULL */ +- const gchar **argv = g_new0 (const gchar*, args_length + 3); ++ /* allocate enough space for the args plus "lvm", "--config", "--devices" and NULL */ ++ const gchar **argv = g_new0 (const gchar*, args_length + 4); + + /* construct argv from args with "lvm" prepended */ + argv[0] = "lvm"; + for (i=0; i < args_length; i++) + argv[i+1] = args[i]; +- argv[args_length + 1] = global_config_str ? g_strdup_printf("--config=%s", global_config_str) : NULL; +- argv[args_length + 2] = NULL; ++ if (global_config_str) { ++ config_arg = g_strdup_printf("--config=%s", global_config_str); ++ argv[++args_length] = config_arg; ++ } ++ if (global_devices_str) { ++ devices_arg = g_strdup_printf("--devices=%s", global_devices_str); ++ argv[++args_length] = devices_arg; ++ } ++ argv[++args_length] = NULL; + + success = bd_utils_exec_and_capture_output (argv, extra, output, error); + g_mutex_unlock (&global_config_lock); +- g_free ((gchar *) argv[args_length + 1]); + g_free (argv); + + return success; +@@ -2018,6 +2041,58 @@ gchar* bd_lvm_get_global_config (GError **error UNUSED) { + return ret; + } + ++/** ++ * bd_lvm_set_devices_filter: ++ * @devices: (allow-none) (array zero-terminated=1): list of devices for lvm commands to work on ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the devices filter was successfully set or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error) { ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ g_mutex_lock (&global_config_lock); ++ ++ /* first free the old value */ ++ g_free (global_devices_str); ++ ++ /* now store the new one */ ++ if (!devices || !(*devices)) ++ global_devices_str = NULL; ++ else ++ global_devices_str = g_strjoinv (",", (gchar **) devices); ++ ++ g_mutex_unlock (&global_config_lock); ++ return TRUE; ++} ++ ++/** ++ * bd_lvm_get_devices_filter: ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: (transfer full) (array zero-terminated=1): a copy of a string representation of ++ * the currently set LVM devices filter ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gchar** bd_lvm_get_devices_filter (GError **error UNUSED) { ++ gchar **ret = NULL; ++ ++ g_mutex_lock (&global_config_lock); ++ ++ if (global_devices_str) ++ ret = g_strsplit (global_devices_str, ",", -1); ++ else ++ ret = NULL; ++ ++ g_mutex_unlock (&global_config_lock); ++ ++ return ret; ++} ++ + /** + * bd_lvm_cache_get_default_md_size: + * @cache_size: size of the cache to determine MD size for +diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h +index 2162d76..8063693 100644 +--- a/src/plugins/lvm.h ++++ b/src/plugins/lvm.h +@@ -216,6 +216,7 @@ typedef enum { + BD_LVM_TECH_CACHE_CALCS, + BD_LVM_TECH_GLOB_CONF, + BD_LVM_TECH_VDO, ++ BD_LVM_TECH_DEVICES, + } BDLVMTech; + + typedef enum { +@@ -289,6 +290,9 @@ gboolean bd_lvm_thsnapshotcreate (const gchar *vg_name, const gchar *origin_name + gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error); + gchar* bd_lvm_get_global_config (GError **error); + ++gboolean bd_lvm_set_devices_filter (const gchar **devices, GError **error); ++gchar** bd_lvm_get_devices_filter (GError **error); ++ + guint64 bd_lvm_cache_get_default_md_size (guint64 cache_size, GError **error); + const gchar* bd_lvm_cache_get_mode_str (BDLVMCacheMode mode, GError **error); + BDLVMCacheMode bd_lvm_cache_get_mode_from_str (const gchar *mode_str, GError **error); +diff --git a/tests/library_test.py b/tests/library_test.py +index 08e44fd..efd17bd 100644 +--- a/tests/library_test.py ++++ b/tests/library_test.py +@@ -13,18 +13,178 @@ class LibraryOpsTestCase(unittest.TestCase): + # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all + # the dependencies on CentOS/Debian and we don't need them for this test + requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "dm", +- "kbd", "loop", "lvm", ++ "kbd", "loop", + "mdraid", "part", "swap")) + ++ @classmethod ++ def setUpClass(cls): ++ if not BlockDev.is_initialized(): ++ BlockDev.init(cls.requested_plugins, None) ++ else: ++ BlockDev.reinit(cls.requested_plugins, True, None) ++ ++ @classmethod ++ def tearDownClass(cls): ++ BlockDev.switch_init_checks(True) ++ ++ def my_log_func(self, level, msg): ++ # not much to verify here ++ self.assertTrue(isinstance(level, int)) ++ self.assertTrue(isinstance(msg, str)) ++ ++ self.log += msg + "\n" ++ ++ @tag_test(TestTags.CORE) ++ def test_logging_setup(self): ++ """Verify that setting up logging works as expected""" ++ ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self.my_log_func)) ++ ++ succ = BlockDev.utils_exec_and_report_error(["true"]) ++ self.assertTrue(succ) ++ ++ # reinit with no logging function should change nothing about logging ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, None)) ++ ++ succ, out = BlockDev.utils_exec_and_capture_output(["echo", "hi"]) ++ self.assertTrue(succ) ++ self.assertEqual(out, "hi\n") ++ ++ match = re.search(r'Running \[(\d+)\] true', self.log) ++ self.assertIsNot(match, None) ++ task_id1 = match.group(1) ++ match = re.search(r'Running \[(\d+)\] echo hi', self.log) ++ self.assertIsNot(match, None) ++ task_id2 = match.group(1) ++ ++ self.assertIn("...done [%s] (exit code: 0)" % task_id1, self.log) ++ self.assertIn("stdout[%s]:" % task_id1, self.log) ++ self.assertIn("stderr[%s]:" % task_id1, self.log) ++ ++ self.assertIn("stdout[%s]: hi" % task_id2, self.log) ++ self.assertIn("stderr[%s]:" % task_id2, self.log) ++ self.assertIn("...done [%s] (exit code: 0)" % task_id2, self.log) ++ ++ @tag_test(TestTags.CORE) ++ def test_require_plugins(self): ++ """Verify that loading only required plugins works as expected""" ++ ++ ps = BlockDev.PluginSpec() ++ ps.name = BlockDev.Plugin.SWAP ++ ps.so_name = "" ++ self.assertTrue(BlockDev.reinit([ps], True, None)) ++ self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ ++ @tag_test(TestTags.CORE) ++ def test_not_implemented(self): ++ """Verify that unloaded/unimplemented functions report errors""" ++ ++ # should be loaded and working ++ self.assertTrue(BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236")) ++ ++ ps = BlockDev.PluginSpec() ++ ps.name = BlockDev.Plugin.SWAP ++ ps.so_name = "" ++ self.assertTrue(BlockDev.reinit([ps], True, None)) ++ self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) ++ ++ # no longer loaded ++ with self.assertRaises(GLib.GError): ++ BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") ++ ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ ++ # loaded again ++ self.assertTrue(BlockDev.md_canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236")) ++ ++ def test_ensure_init(self): ++ """Verify that ensure_init just returns when already initialized""" ++ ++ # the library is already initialized, ensure_init() shonuld do nothing ++ avail_plugs = BlockDev.get_available_plugin_names() ++ self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) ++ self.assertEqual(avail_plugs, BlockDev.get_available_plugin_names()) ++ ++ # reinit with a subset of plugins ++ plugins = BlockDev.plugin_specs_from_names(["swap", "part"]) ++ self.assertTrue(BlockDev.reinit(plugins, True, None)) ++ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part"])) ++ ++ # ensure_init with the same subset -> nothing should change ++ self.assertTrue(BlockDev.ensure_init(plugins, None)) ++ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part"])) ++ ++ # ensure_init with more plugins -> extra plugins should be loaded ++ plugins = BlockDev.plugin_specs_from_names(["swap", "part", "crypto"]) ++ self.assertTrue(BlockDev.ensure_init(plugins, None)) ++ self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "part", "crypto"])) ++ ++ # reinit to unload all plugins ++ self.assertTrue(BlockDev.reinit([], True, None)) ++ self.assertEqual(BlockDev.get_available_plugin_names(), []) ++ ++ # ensure_init to load all plugins back ++ self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) ++ self.assertGreaterEqual(len(BlockDev.get_available_plugin_names()), 7) ++ ++ def test_try_reinit(self): ++ """Verify that try_reinit() works as expected""" ++ ++ # try reinitializing with only some utilities being available and thus ++ # only some plugins able to load ++ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "swaplabel"]): ++ succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None) ++ self.assertFalse(succ) ++ for plug_name in ("swap", "crypto"): ++ self.assertIn(plug_name, loaded) ++ ++ # reset back to all plugins ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ ++ # now the same with a subset of plugins requested ++ plugins = BlockDev.plugin_specs_from_names(["swap", "crypto"]) ++ with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "swaplabel"]): ++ succ, loaded = BlockDev.try_reinit(plugins, True, None) ++ self.assertTrue(succ) ++ self.assertEqual(set(loaded), set(["swap", "crypto"])) ++ ++ def test_non_en_init(self): ++ """Verify that the library initializes with lang different from en_US""" ++ ++ orig_lang = os.environ.get("LANG") ++ os.environ["LANG"] = "cs.CZ_UTF-8" ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ if orig_lang: ++ os.environ["LANG"] = orig_lang ++ else: ++ del os.environ["LANG"] ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++ ++ ++class PluginsTestCase(unittest.TestCase): ++ # only LVM plugin for this test ++ requested_plugins = BlockDev.plugin_specs_from_names(("lvm",)) ++ + orig_config_dir = "" + + @classmethod + def setUpClass(cls): ++ BlockDev.switch_init_checks(False) + if not BlockDev.is_initialized(): + BlockDev.init(cls.requested_plugins, None) + else: + BlockDev.reinit(cls.requested_plugins, True, None) + ++ try: ++ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) ++ except: ++ cls.devices_avail = False ++ ++ @classmethod ++ def tearDownClass(cls): ++ BlockDev.switch_init_checks(True) ++ + def setUp(self): + self.orig_config_dir = os.environ.get("LIBBLOCKDEV_CONFIG_DIR", "") + self.addCleanup(self._clean_up) +@@ -185,6 +345,12 @@ class LibraryOpsTestCase(unittest.TestCase): + def test_plugin_fallback(self): + """Verify that fallback when loading plugins works as expected""" + ++ if not self.devices_avail: ++ self.skipTest("skipping plugin fallback test: missing some LVM dependencies") ++ ++ BlockDev.switch_init_checks(True) ++ self.addCleanup(BlockDev.switch_init_checks, False) ++ + # library should be successfully initialized + self.assertTrue(BlockDev.is_initialized()) + +@@ -206,7 +372,7 @@ class LibraryOpsTestCase(unittest.TestCase): + + # now reinit the library with the config preferring the new build + orig_conf_dir = os.environ.get("LIBBLOCKDEV_CONFIG_DIR") +- os.environ["LIBBLOCKDEV_CONFIG_DIR"] = "tests/plugin_prio_conf.d" ++ os.environ["LIBBLOCKDEV_CONFIG_DIR"] = "tests/test_configs/plugin_prio_conf.d" + self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) + + # the original plugin should be loaded because the new one should fail +@@ -243,139 +409,9 @@ class LibraryOpsTestCase(unittest.TestCase): + + self.assertEqual(BlockDev.lvm_get_max_lv_size(), orig_max_size) + +- def my_log_func(self, level, msg): +- # not much to verify here +- self.assertTrue(isinstance(level, int)) +- self.assertTrue(isinstance(msg, str)) +- +- self.log += msg + "\n" +- +- @tag_test(TestTags.CORE) +- def test_logging_setup(self): +- """Verify that setting up logging works as expected""" +- +- self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self.my_log_func)) +- +- succ = BlockDev.utils_exec_and_report_error(["true"]) +- self.assertTrue(succ) +- +- # reinit with no logging function should change nothing about logging +- self.assertTrue(BlockDev.reinit(self.requested_plugins, False, None)) +- +- succ, out = BlockDev.utils_exec_and_capture_output(["echo", "hi"]) +- self.assertTrue(succ) +- self.assertEqual(out, "hi\n") +- +- match = re.search(r'Running \[(\d+)\] true', self.log) +- self.assertIsNot(match, None) +- task_id1 = match.group(1) +- match = re.search(r'Running \[(\d+)\] echo hi', self.log) +- self.assertIsNot(match, None) +- task_id2 = match.group(1) +- +- self.assertIn("...done [%s] (exit code: 0)" % task_id1, self.log) +- self.assertIn("stdout[%s]:" % task_id1, self.log) +- self.assertIn("stderr[%s]:" % task_id1, self.log) +- +- self.assertIn("stdout[%s]: hi" % task_id2, self.log) +- self.assertIn("stderr[%s]:" % task_id2, self.log) +- self.assertIn("...done [%s] (exit code: 0)" % task_id2, self.log) +- +- @tag_test(TestTags.CORE) +- def test_require_plugins(self): +- """Verify that loading only required plugins works as expected""" +- +- ps = BlockDev.PluginSpec() +- ps.name = BlockDev.Plugin.SWAP +- ps.so_name = "" +- self.assertTrue(BlockDev.reinit([ps], True, None)) +- self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +- +- @tag_test(TestTags.CORE) +- def test_not_implemented(self): +- """Verify that unloaded/unimplemented functions report errors""" +- +- # should be loaded and working +- self.assertTrue(BlockDev.lvm_get_max_lv_size() > 0) + +- ps = BlockDev.PluginSpec() +- ps.name = BlockDev.Plugin.SWAP +- ps.so_name = "" +- self.assertTrue(BlockDev.reinit([ps], True, None)) +- self.assertEqual(BlockDev.get_available_plugin_names(), ["swap"]) +- +- # no longer loaded +- with self.assertRaises(GLib.GError): +- BlockDev.lvm_get_max_lv_size() +- +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +- +- # loaded again +- self.assertTrue(BlockDev.lvm_get_max_lv_size() > 0) +- +- def test_ensure_init(self): +- """Verify that ensure_init just returns when already initialized""" +- +- # the library is already initialized, ensure_init() shonuld do nothing +- avail_plugs = BlockDev.get_available_plugin_names() +- self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) +- self.assertEqual(avail_plugs, BlockDev.get_available_plugin_names()) +- +- # reinit with a subset of plugins +- plugins = BlockDev.plugin_specs_from_names(["swap", "lvm"]) +- self.assertTrue(BlockDev.reinit(plugins, True, None)) +- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm"])) +- +- # ensure_init with the same subset -> nothing should change +- self.assertTrue(BlockDev.ensure_init(plugins, None)) +- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm"])) +- +- # ensure_init with more plugins -> extra plugins should be loaded +- plugins = BlockDev.plugin_specs_from_names(["swap", "lvm", "crypto"]) +- self.assertTrue(BlockDev.ensure_init(plugins, None)) +- self.assertEqual(set(BlockDev.get_available_plugin_names()), set(["swap", "lvm", "crypto"])) +- +- # reinit to unload all plugins +- self.assertTrue(BlockDev.reinit([], True, None)) +- self.assertEqual(BlockDev.get_available_plugin_names(), []) +- +- # ensure_init to load all plugins back +- self.assertTrue(BlockDev.ensure_init(self.requested_plugins, None)) +- self.assertGreaterEqual(len(BlockDev.get_available_plugin_names()), 8) +- +- def test_try_reinit(self): +- """Verify that try_reinit() works as expected""" +- +- # try reinitializing with only some utilities being available and thus +- # only some plugins able to load +- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm", "swaplabel"]): +- succ, loaded = BlockDev.try_reinit(self.requested_plugins, True, None) +- self.assertFalse(succ) +- for plug_name in ("swap", "lvm", "crypto"): +- self.assertIn(plug_name, loaded) +- +- # reset back to all plugins +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +- +- # now the same with a subset of plugins requested +- plugins = BlockDev.plugin_specs_from_names(["lvm", "swap", "crypto"]) +- with fake_path("tests/lib_missing_utils", keep_utils=["swapon", "swapoff", "mkswap", "lvm","swaplabel"]): +- succ, loaded = BlockDev.try_reinit(plugins, True, None) +- self.assertTrue(succ) +- self.assertEqual(set(loaded), set(["swap", "lvm", "crypto"])) +- +- def test_non_en_init(self): +- """Verify that the library initializes with lang different from en_US""" +- +- orig_lang = os.environ.get("LANG") +- os.environ["LANG"] = "cs.CZ_UTF-8" +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +- if orig_lang: +- os.environ["LANG"] = orig_lang +- else: +- del os.environ["LANG"] +- self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) ++class DepChecksTestCase(unittest.TestCase): ++ requested_plugins = BlockDev.plugin_specs_from_names(( "swap",)) + + def test_dep_checks_disabled(self): + """Verify that disabling runtime dep checks works""" +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 4882da8..35ace37 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -33,6 +33,11 @@ class LVMTestCase(unittest.TestCase): + else: + BlockDev.reinit([cls.ps, cls.ps2], True, None) + ++ try: ++ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) ++ except: ++ cls.devices_avail = False ++ + @classmethod + def _get_lvm_version(cls): + _ret, out, _err = run_command("lvm version") +@@ -44,8 +49,7 @@ class LVMTestCase(unittest.TestCase): + @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") + class LvmNoDevTestCase(LVMTestCase): + +- def __init__(self, *args, **kwargs): +- super(LvmNoDevTestCase, self).__init__(*args, **kwargs) ++ def setUp(self): + self._log = "" + + @tag_test(TestTags.NOSTORAGE) +@@ -227,6 +231,45 @@ class LvmNoDevTestCase(LVMTestCase): + succ = BlockDev.lvm_set_global_config(None) + self.assertTrue(succ) + ++ @tag_test(TestTags.NOSTORAGE) ++ def test_get_set_global_devices_filter(self): ++ """Verify that getting and setting LVM devices filter works as expected""" ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices filter test: not supported") ++ ++ # setup logging ++ self.assertTrue(BlockDev.reinit([self.ps], False, self._store_log)) ++ ++ # no global config set initially ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) ++ ++ # set and try to get back ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) ++ self.assertTrue(succ) ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sda"]) ++ ++ # reset and try to get back ++ succ = BlockDev.lvm_set_devices_filter(None) ++ self.assertTrue(succ) ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) ++ ++ # set twice and try to get back twice ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) ++ self.assertTrue(succ) ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb"]) ++ self.assertTrue(succ) ++ self.assertEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sdb"]) ++ ++ # set something sane and check it's really used ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb", "/dev/sdc"]) ++ BlockDev.lvm_pvscan() ++ self.assertIn("'--devices'", self._log) ++ self.assertIn("'/dev/sdb,/dev/sdc'", self._log) ++ ++ # reset back to default ++ succ = BlockDev.lvm_set_devices_filter(None) ++ self.assertTrue(succ) ++ + @tag_test(TestTags.NOSTORAGE) + def test_cache_get_default_md_size(self): + """Verify that default cache metadata size is calculated properly""" +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index eb94c91..b37a879 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -22,10 +22,17 @@ class LVMTestCase(unittest.TestCase): + ps.so_name = "libbd_lvm.so.2" + cls.requested_plugins = [ps] + ++ BlockDev.switch_init_checks(False) + if not BlockDev.is_initialized(): + BlockDev.init(cls.requested_plugins, None) + else: + BlockDev.reinit(cls.requested_plugins, True, None) ++ BlockDev.switch_init_checks(True) ++ ++ try: ++ cls.devices_avail = BlockDev.lvm_is_tech_avail(BlockDev.LVMTech.DEVICES, 0) ++ except: ++ cls.devices_avail = False + + @classmethod + def _get_lvm_version(cls): +@@ -39,6 +46,8 @@ class LVMTestCase(unittest.TestCase): + class LvmNoDevTestCase(LVMTestCase): + def __init__(self, *args, **kwargs): + super(LvmNoDevTestCase, self).__init__(*args, **kwargs) ++ ++ def setUp(self): + self._log = "" + + @tag_test(TestTags.NOSTORAGE) +@@ -213,6 +222,44 @@ class LvmNoDevTestCase(LVMTestCase): + succ = BlockDev.lvm_set_global_config(None) + self.assertTrue(succ) + ++ @tag_test(TestTags.NOSTORAGE) ++ def test_get_set_global_devices_filter(self): ++ """Verify that getting and setting LVM devices filter works as expected""" ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices filter test: not supported") ++ ++ # setup logging ++ self.assertTrue(BlockDev.reinit(self.requested_plugins, False, self._store_log)) ++ ++ # no global config set initially ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) ++ ++ # set and try to get back ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) ++ self.assertTrue(succ) ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sda"]) ++ ++ # reset and try to get back ++ succ = BlockDev.lvm_set_devices_filter(None) ++ self.assertTrue(succ) ++ self.assertListEqual(BlockDev.lvm_get_devices_filter(), []) ++ ++ # set twice and try to get back twice ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sda"]) ++ self.assertTrue(succ) ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb"]) ++ self.assertTrue(succ) ++ self.assertEqual(BlockDev.lvm_get_devices_filter(), ["/dev/sdb"]) ++ ++ # set something sane and check it's really used ++ succ = BlockDev.lvm_set_devices_filter(["/dev/sdb", "/dev/sdc"]) ++ BlockDev.lvm_lvs(None) ++ self.assertIn("--devices=/dev/sdb,/dev/sdc", self._log) ++ ++ # reset back to default ++ succ = BlockDev.lvm_set_devices_filter(None) ++ self.assertTrue(succ) ++ + @tag_test(TestTags.NOSTORAGE) + def test_cache_get_default_md_size(self): + """Verify that default cache metadata size is calculated properly""" +@@ -1335,6 +1382,9 @@ class LvmPVVGcachedThpoolstatsTestCase(LvmPVVGLVTestCase): + + class LVMUnloadTest(LVMTestCase): + def setUp(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM unload test: missing some LVM dependencies") ++ + # make sure the library is initialized with all plugins loaded for other + # tests + self.addCleanup(BlockDev.reinit, self.requested_plugins, True, None) +diff --git a/tests/overrides_test.py b/tests/overrides_test.py +index 8e7f5a5..d3faf3c 100644 +--- a/tests/overrides_test.py ++++ b/tests/overrides_test.py +@@ -15,10 +15,12 @@ class OverridesTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): ++ BlockDev.switch_init_checks(False) + if not BlockDev.is_initialized(): + BlockDev.init(cls.requested_plugins, None) + else: + BlockDev.reinit(cls.requested_plugins, True, None) ++ BlockDev.switch_init_checks(True) + + class OverridesTestCase(OverridesTest): + @tag_test(TestTags.NOSTORAGE, TestTags.CORE) +@@ -65,7 +67,20 @@ class OverridesTestCase(OverridesTest): + self.assertEqual(BlockDev.lvm_get_thpool_padding(11 * 1024**2), + expected_padding) + +-class OverridesUnloadTestCase(OverridesTest): ++class OverridesUnloadTestCase(unittest.TestCase): ++ # all plugins except for 'btrfs', 'fs' and 'mpath' -- these don't have all ++ # the dependencies on CentOS/Debian and we don't need them for this test ++ requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "dm", ++ "kbd", "loop", ++ "mdraid", "part", "swap")) ++ ++ @classmethod ++ def setUpClass(cls): ++ if not BlockDev.is_initialized(): ++ BlockDev.init(cls.requested_plugins, None) ++ else: ++ BlockDev.reinit(cls.requested_plugins, True, None) ++ + def tearDown(self): + # make sure the library is initialized with all plugins loaded for other + # tests +@@ -80,7 +95,7 @@ class OverridesUnloadTestCase(OverridesTest): + + # no longer loaded + with self.assertRaises(BlockDev.BlockDevNotImplementedError): +- BlockDev.lvm.get_max_lv_size() ++ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") + + # load the plugins back + self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +@@ -92,9 +107,9 @@ class OverridesUnloadTestCase(OverridesTest): + + # the exception should be properly inherited from two classes + with self.assertRaises(NotImplementedError): +- BlockDev.lvm.get_max_lv_size() ++ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") + with self.assertRaises(BlockDev.BlockDevError): +- BlockDev.lvm.get_max_lv_size() ++ BlockDev.md.canonicalize_uuid("3386ff85:f5012621:4a435f06:1eb47236") + + # load the plugins back + self.assertTrue(BlockDev.reinit(self.requested_plugins, True, None)) +-- +2.31.1 + + +From bebd74962db6fb7b5314be411a4d02b21554d80f Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 13 Jul 2021 13:27:32 +0200 +Subject: [PATCH 2/8] lvm: Add functions for managing LVM devices file + +Currently covers only --adddev and --deldev from the lvmdevices +command. +--- + src/lib/plugin_apis/lvm.api | 26 +++++++++++++++ + src/plugins/lvm-dbus.c | 52 +++++++++++++++++++++++++++++ + src/plugins/lvm.c | 52 +++++++++++++++++++++++++++++ + src/plugins/lvm.h | 3 ++ + src/python/gi/overrides/BlockDev.py | 15 +++++++++ + tests/lvm_dbus_tests.py | 37 +++++++++++++++++++- + tests/lvm_test.py | 37 +++++++++++++++++++- + 7 files changed, 220 insertions(+), 2 deletions(-) + +diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api +index 62f602f..bce2920 100644 +--- a/src/lib/plugin_apis/lvm.api ++++ b/src/lib/plugin_apis/lvm.api +@@ -1685,4 +1685,30 @@ GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_n + */ + BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error); + ++/** ++ * bd_lvm_devices_add: ++ * @device: device (PV) to add to the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully added to @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); ++ ++/** ++ * bd_lvm_devices_delete: ++ * @device: device (PV) to delete from the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully removed from @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); ++ + #endif /* BD_LVM_API */ +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index d1726ed..44d2794 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -3938,3 +3938,55 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam + + return stats; + } ++ ++/** ++ * bd_lvm_devices_add: ++ * @device: device (PV) to add to the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully added to @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { ++ const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL}; ++ g_autofree gchar *devfile = NULL; ++ ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ if (devices_file) { ++ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); ++ args[3] = devfile; ++ } ++ ++ return bd_utils_exec_and_report_error (args, extra, error); ++} ++ ++/** ++ * bd_lvm_devices_delete: ++ * @device: device (PV) to delete from the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully removed from @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { ++ const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL}; ++ g_autofree gchar *devfile = NULL; ++ ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ if (devices_file) { ++ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); ++ args[3] = devfile; ++ } ++ ++ return bd_utils_exec_and_report_error (args, extra, error); ++} +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index c0d8198..94c6a22 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -3235,3 +3235,55 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam + + return stats; + } ++ ++/** ++ * bd_lvm_devices_add: ++ * @device: device (PV) to add to the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully added to @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { ++ const gchar *args[5] = {"lvmdevices", "--adddev", device, NULL, NULL}; ++ g_autofree gchar *devfile = NULL; ++ ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ if (devices_file) { ++ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); ++ args[3] = devfile; ++ } ++ ++ return bd_utils_exec_and_report_error (args, extra, error); ++} ++ ++/** ++ * bd_lvm_devices_delete: ++ * @device: device (PV) to delete from the devices file ++ * @devices_file: (allow-none): LVM devices file or %NULL for default ++ * @extra: (allow-none) (array zero-terminated=1): extra options for the lvmdevices command ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully removed from @devices_file or not ++ * ++ * Tech category: %BD_LVM_TECH_DEVICES no mode (it is ignored) ++ */ ++gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error) { ++ const gchar *args[5] = {"lvmdevices", "--deldev", device, NULL, NULL}; ++ g_autofree gchar *devfile = NULL; ++ ++ if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) ++ return FALSE; ++ ++ if (devices_file) { ++ devfile = g_strdup_printf ("--devicesfile=%s", devices_file); ++ args[3] = devfile; ++ } ++ ++ return bd_utils_exec_and_report_error (args, extra, error); ++} +diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h +index 8063693..5ca2a9d 100644 +--- a/src/plugins/lvm.h ++++ b/src/plugins/lvm.h +@@ -333,4 +333,7 @@ BDLVMVDOWritePolicy bd_lvm_get_vdo_write_policy_from_str (const gchar *policy_st + BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_name, GError **error); + GHashTable* bd_lvm_vdo_get_stats_full (const gchar *vg_name, const gchar *pool_name, GError **error); + ++gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); ++gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, const BDExtraArg **extra, GError **error); ++ + #endif /* BD_LVM */ +diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py +index f768c8b..715a262 100644 +--- a/src/python/gi/overrides/BlockDev.py ++++ b/src/python/gi/overrides/BlockDev.py +@@ -724,6 +724,21 @@ def lvm_vdo_pool_convert(vg_name, lv_name, pool_name, virtual_size, index_memory + return _lvm_vdo_pool_convert(vg_name, lv_name, pool_name, virtual_size, index_memory, compression, deduplication, write_policy, extra) + __all__.append("lvm_vdo_pool_convert") + ++_lvm_devices_add = BlockDev.lvm_devices_add ++@override(BlockDev.lvm_devices_add) ++def lvm_devices_add(device, devices_file=None, extra=None, **kwargs): ++ extra = _get_extra(extra, kwargs) ++ return _lvm_devices_add(device, devices_file, extra) ++__all__.append("lvm_devices_add") ++ ++_lvm_devices_delete = BlockDev.lvm_devices_delete ++@override(BlockDev.lvm_devices_delete) ++def lvm_devices_delete(device, devices_file=None, extra=None, **kwargs): ++ extra = _get_extra(extra, kwargs) ++ return _lvm_devices_delete(device, devices_file, extra) ++__all__.append("lvm_devices_delete") ++ ++ + _md_get_superblock_size = BlockDev.md_get_superblock_size + @override(BlockDev.md_get_superblock_size) + def md_get_superblock_size(size, version=None): +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 35ace37..fb1a9ed 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -10,7 +10,7 @@ import subprocess + from distutils.version import LooseVersion + from itertools import chain + +-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test ++from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, run_command, TestTags, tag_test, read_file + from gi.repository import BlockDev, GLib + + import dbus +@@ -1696,3 +1696,38 @@ class LVMVDOTest(LVMTestCase): + + full_stats = BlockDev.lvm_vdo_get_stats_full("testVDOVG", "vdoPool") + self.assertIn("writeAmplificationRatio", full_stats.keys()) ++ ++ ++class LvmTestDevicesFile(LvmPVonlyTestCase): ++ devicefile = "bd_lvm_dbus_tests.devices" ++ ++ @classmethod ++ def tearDownClass(cls): ++ shutil.rmtree("/etc/lvm/devices/" + cls.devicefile, ignore_errors=True) ++ ++ super(LvmTestDevicesFile, cls).tearDownClass() ++ ++ def test_devices_add_delete(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices file test: not supported") ++ ++ succ = BlockDev.lvm_pvcreate(self.loop_dev) ++ self.assertTrue(succ) ++ ++ with self.assertRaises(GLib.GError): ++ BlockDev.lvm_devices_add("/non/existing/device", self.devicefile) ++ ++ with self.assertRaises(GLib.GError): ++ BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) ++ ++ succ = BlockDev.lvm_devices_add(self.loop_dev, self.devicefile) ++ self.assertTrue(succ) ++ ++ dfile = read_file("/etc/lvm/devices/" + self.devicefile) ++ self.assertIn(self.loop_dev, dfile) ++ ++ succ = BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) ++ self.assertTrue(succ) ++ ++ dfile = read_file("/etc/lvm/devices/" + self.devicefile) ++ self.assertNotIn(self.loop_dev, dfile) +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index b37a879..786434f 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -9,7 +9,7 @@ import shutil + import subprocess + from distutils.version import LooseVersion + +-from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command ++from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command, read_file + from gi.repository import BlockDev, GLib + + +@@ -1682,3 +1682,38 @@ class LVMVDOTest(LVMTestCase): + + full_stats = BlockDev.lvm_vdo_get_stats_full("testVDOVG", "vdoPool") + self.assertIn("writeAmplificationRatio", full_stats.keys()) ++ ++ ++class LvmTestDevicesFile(LvmPVonlyTestCase): ++ devicefile = "bd_lvm_test.devices" ++ ++ @classmethod ++ def tearDownClass(cls): ++ shutil.rmtree("/etc/lvm/devices/" + cls.devicefile, ignore_errors=True) ++ ++ super(LvmTestDevicesFile, cls).tearDownClass() ++ ++ def test_devices_add_delete(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices file test: not supported") ++ ++ succ = BlockDev.lvm_pvcreate(self.loop_dev) ++ self.assertTrue(succ) ++ ++ with self.assertRaises(GLib.GError): ++ BlockDev.lvm_devices_add("/non/existing/device", self.devicefile) ++ ++ with self.assertRaises(GLib.GError): ++ BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) ++ ++ succ = BlockDev.lvm_devices_add(self.loop_dev, self.devicefile) ++ self.assertTrue(succ) ++ ++ dfile = read_file("/etc/lvm/devices/" + self.devicefile) ++ self.assertIn(self.loop_dev, dfile) ++ ++ succ = BlockDev.lvm_devices_delete(self.loop_dev, self.devicefile) ++ self.assertTrue(succ) ++ ++ dfile = read_file("/etc/lvm/devices/" + self.devicefile) ++ self.assertNotIn(self.loop_dev, dfile) +-- +2.31.1 + + +From 8d8cbe7169cb94b01e7064a0d00b7d86baf5e652 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 15 Oct 2021 13:18:54 +0200 +Subject: [PATCH 3/8] lvm: Report special error when system.devices file is not + enabled + +This can be disabled either in LVM by a compile time option or +by a lvm.conf option so we should report a specific error for this +case so users can distinguish between the feature not being enabled +and not being supported at all. +--- + src/lib/plugin_apis/lvm.api | 1 + + src/plugins/lvm-dbus.c | 70 +++++++++++++++++++++++++++++++++++++ + src/plugins/lvm.c | 60 +++++++++++++++++++++++++++++++ + src/plugins/lvm.h | 1 + + tests/lvm_dbus_tests.py | 15 ++++++++ + tests/lvm_test.py | 15 ++++++++ + 6 files changed, 162 insertions(+) + +diff --git a/src/lib/plugin_apis/lvm.api b/src/lib/plugin_apis/lvm.api +index bce2920..b96bcfd 100644 +--- a/src/lib/plugin_apis/lvm.api ++++ b/src/lib/plugin_apis/lvm.api +@@ -44,6 +44,7 @@ typedef enum { + BD_LVM_ERROR_FAIL, + BD_LVM_ERROR_NOT_SUPPORTED, + BD_LVM_ERROR_VDO_POLICY_INVAL, ++ BD_LVM_ERROR_DEVICES_DISABLED, + } BDLVMError; + + typedef enum { +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index 44d2794..22204d5 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -3939,6 +3939,64 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam + return stats; + } + ++/* check whether the LVM devices file is enabled by LVM ++ * we use the existence of the "lvmdevices" command to check whether the feature is available ++ * or not, but this can still be disabled either in LVM or in lvm.conf ++ */ ++static gboolean _lvm_devices_enabled () { ++ const gchar *args[6] = {"lvmconfig", "--typeconfig", NULL, "devices/use_devicesfile", NULL, NULL}; ++ gboolean ret = FALSE; ++ GError *loc_error = NULL; ++ gchar *output = NULL; ++ gboolean enabled = FALSE; ++ gint scanned = 0; ++ g_autofree gchar *config_arg = NULL; ++ ++ /* try current config first -- if we get something from this it means the feature is ++ explicitly enabled or disabled by system lvm.conf or using the --config option */ ++ args[2] = "current"; ++ ++ /* make sure to include the global config from us when getting the current config value */ ++ g_mutex_lock (&global_config_lock); ++ if (global_config_str) { ++ config_arg = g_strdup_printf ("--config=%s", global_config_str); ++ args[4] = config_arg; ++ } ++ ++ ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error); ++ g_mutex_unlock (&global_config_lock); ++ if (ret) { ++ scanned = sscanf (output, "use_devicesfile=%u", &enabled); ++ g_free (output); ++ if (scanned != 1) ++ return FALSE; ++ ++ return enabled; ++ } else { ++ g_clear_error (&loc_error); ++ g_free (output); ++ } ++ ++ output = NULL; ++ ++ /* now try default */ ++ args[2] = "default"; ++ ret = bd_utils_exec_and_capture_output (args, NULL, &output, &loc_error); ++ if (ret) { ++ scanned = sscanf (output, "# use_devicesfile=%u", &enabled); ++ g_free (output); ++ if (scanned != 1) ++ return FALSE; ++ ++ return enabled; ++ } else { ++ g_clear_error (&loc_error); ++ g_free (output); ++ } ++ ++ return FALSE; ++} ++ + /** + * bd_lvm_devices_add: + * @device: device (PV) to add to the devices file +@@ -3957,6 +4015,12 @@ gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, con + if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) + return FALSE; + ++ if (!_lvm_devices_enabled ()) { ++ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, ++ "LVM devices file not enabled."); ++ return FALSE; ++ } ++ + if (devices_file) { + devfile = g_strdup_printf ("--devicesfile=%s", devices_file); + args[3] = devfile; +@@ -3983,6 +4047,12 @@ gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, + if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) + return FALSE; + ++ if (!_lvm_devices_enabled ()) { ++ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, ++ "LVM devices file not enabled."); ++ return FALSE; ++ } ++ + if (devices_file) { + devfile = g_strdup_printf ("--devicesfile=%s", devices_file); + args[3] = devfile; +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 94c6a22..605fcb0 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -3236,6 +3236,54 @@ BDLVMVDOStats* bd_lvm_vdo_get_stats (const gchar *vg_name, const gchar *pool_nam + return stats; + } + ++/* check whether the LVM devices file is enabled by LVM ++ * we use the existence of the "lvmdevices" command to check whether the feature is available ++ * or not, but this can still be disabled either in LVM or in lvm.conf ++ */ ++static gboolean _lvm_devices_enabled () { ++ const gchar *args[5] = {"config", "--typeconfig", NULL, "devices/use_devicesfile", NULL}; ++ gboolean ret = FALSE; ++ GError *loc_error = NULL; ++ gchar *output = NULL; ++ gboolean enabled = FALSE; ++ gint scanned = 0; ++ ++ /* try current config first -- if we get something from this it means the feature is ++ explicitly enabled or disabled by system lvm.conf or using the --config option */ ++ args[2] = "current"; ++ ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); ++ if (ret) { ++ scanned = sscanf (output, "use_devicesfile=%u", &enabled); ++ g_free (output); ++ if (scanned != 1) ++ return FALSE; ++ ++ return enabled; ++ } else { ++ g_clear_error (&loc_error); ++ g_free (output); ++ } ++ ++ output = NULL; ++ ++ /* now try default */ ++ args[2] = "default"; ++ ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); ++ if (ret) { ++ scanned = sscanf (output, "# use_devicesfile=%u", &enabled); ++ g_free (output); ++ if (scanned != 1) ++ return FALSE; ++ ++ return enabled; ++ } else { ++ g_clear_error (&loc_error); ++ g_free (output); ++ } ++ ++ return FALSE; ++} ++ + /** + * bd_lvm_devices_add: + * @device: device (PV) to add to the devices file +@@ -3254,6 +3302,12 @@ gboolean bd_lvm_devices_add (const gchar *device, const gchar *devices_file, con + if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) + return FALSE; + ++ if (!_lvm_devices_enabled ()) { ++ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, ++ "LVM devices file not enabled."); ++ return FALSE; ++ } ++ + if (devices_file) { + devfile = g_strdup_printf ("--devicesfile=%s", devices_file); + args[3] = devfile; +@@ -3280,6 +3334,12 @@ gboolean bd_lvm_devices_delete (const gchar *device, const gchar *devices_file, + if (!bd_lvm_is_tech_avail (BD_LVM_TECH_DEVICES, 0, error)) + return FALSE; + ++ if (!_lvm_devices_enabled ()) { ++ g_set_error (error, BD_LVM_ERROR, BD_LVM_ERROR_DEVICES_DISABLED, ++ "LVM devices file not enabled."); ++ return FALSE; ++ } ++ + if (devices_file) { + devfile = g_strdup_printf ("--devicesfile=%s", devices_file); + args[3] = devfile; +diff --git a/src/plugins/lvm.h b/src/plugins/lvm.h +index 5ca2a9d..fabf091 100644 +--- a/src/plugins/lvm.h ++++ b/src/plugins/lvm.h +@@ -53,6 +53,7 @@ typedef enum { + BD_LVM_ERROR_FAIL, + BD_LVM_ERROR_NOT_SUPPORTED, + BD_LVM_ERROR_VDO_POLICY_INVAL, ++ BD_LVM_ERROR_DEVICES_DISABLED, + } BDLVMError; + + typedef enum { +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index fb1a9ed..c411c9e 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1731,3 +1731,18 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) ++ ++ def test_devices_enabled(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices file test: not supported") ++ ++ self.addCleanup(BlockDev.lvm_set_global_config, "") ++ ++ # checking if the feature is enabled or disabled is hard so lets just disable ++ # the devices file using the global config and check lvm_devices_add fails ++ # with the correct exception message ++ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=0 }") ++ self.assertTrue(succ) ++ ++ with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): ++ BlockDev.lvm_devices_add("", self.devicefile) +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 786434f..315dd07 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1717,3 +1717,18 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) ++ ++ def test_devices_enabled(self): ++ if not self.devices_avail: ++ self.skipTest("skipping LVM devices file test: not supported") ++ ++ self.addCleanup(BlockDev.lvm_set_global_config, "") ++ ++ # checking if the feature is enabled or disabled is hard so lets just disable ++ # the devices file using the global config and check lvm_devices_add fails ++ # with the correct exception message ++ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=0 }") ++ self.assertTrue(succ) ++ ++ with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): ++ BlockDev.lvm_devices_add("", self.devicefile) +-- +2.31.1 + + +From 81df85e7ea6e129e78074b6967f80c505d1b08f0 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 15 Oct 2021 14:21:03 +0200 +Subject: [PATCH 4/8] lvm: Force enable LVM devices file for LvmTestDevicesFile + +This feauture might be disabled in lvm.conf so to be able to test +it we need to override this. The correct handling of the disabled +state is checked in a separate test case. +--- + tests/lvm_dbus_tests.py | 8 ++++++++ + tests/lvm_test.py | 8 ++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index c411c9e..9cfc647 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1711,6 +1711,12 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + ++ self.addCleanup(BlockDev.lvm_set_global_config, "") ++ ++ # force-enable the feature, it might be disabled by default ++ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") ++ self.assertTrue(succ) ++ + succ = BlockDev.lvm_pvcreate(self.loop_dev) + self.assertTrue(succ) + +@@ -1732,6 +1738,8 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) + ++ BlockDev.lvm_set_global_config("") ++ + def test_devices_enabled(self): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 315dd07..ea3b7f8 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1697,6 +1697,12 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + ++ self.addCleanup(BlockDev.lvm_set_global_config, "") ++ ++ # force-enable the feature, it might be disabled by default ++ succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") ++ self.assertTrue(succ) ++ + succ = BlockDev.lvm_pvcreate(self.loop_dev) + self.assertTrue(succ) + +@@ -1718,6 +1724,8 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) + ++ BlockDev.lvm_set_global_config("") ++ + def test_devices_enabled(self): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") +-- +2.31.1 + + +From 01237b62bb8ad67def7c937185c42152503fbc6f Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 12 Nov 2021 14:51:39 +0100 +Subject: [PATCH 5/8] tests: Fix resetting global LVM config after LVM devices + file test + +We need to set the config to None/NULL not to an empty string. +--- + tests/lvm_dbus_tests.py | 6 +++--- + tests/lvm_test.py | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 9cfc647..d422869 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1711,7 +1711,7 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + +- self.addCleanup(BlockDev.lvm_set_global_config, "") ++ self.addCleanup(BlockDev.lvm_set_global_config, None) + + # force-enable the feature, it might be disabled by default + succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") +@@ -1738,13 +1738,13 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) + +- BlockDev.lvm_set_global_config("") ++ BlockDev.lvm_set_global_config(None) + + def test_devices_enabled(self): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + +- self.addCleanup(BlockDev.lvm_set_global_config, "") ++ self.addCleanup(BlockDev.lvm_set_global_config, None) + + # checking if the feature is enabled or disabled is hard so lets just disable + # the devices file using the global config and check lvm_devices_add fails +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index ea3b7f8..882cdf2 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1697,7 +1697,7 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + +- self.addCleanup(BlockDev.lvm_set_global_config, "") ++ self.addCleanup(BlockDev.lvm_set_global_config, None) + + # force-enable the feature, it might be disabled by default + succ = BlockDev.lvm_set_global_config("devices { use_devicesfile=1 }") +@@ -1724,13 +1724,13 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + dfile = read_file("/etc/lvm/devices/" + self.devicefile) + self.assertNotIn(self.loop_dev, dfile) + +- BlockDev.lvm_set_global_config("") ++ BlockDev.lvm_set_global_config(None) + + def test_devices_enabled(self): + if not self.devices_avail: + self.skipTest("skipping LVM devices file test: not supported") + +- self.addCleanup(BlockDev.lvm_set_global_config, "") ++ self.addCleanup(BlockDev.lvm_set_global_config, None) + + # checking if the feature is enabled or disabled is hard so lets just disable + # the devices file using the global config and check lvm_devices_add fails +-- +2.31.1 + + +From 2f33f2af18efa0b337f8383cb6f137d6211fe7fb Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 12 Nov 2021 15:10:45 +0100 +Subject: [PATCH 6/8] lvm: Do not set global config to and empty string + +If we set it to an empty string we end up running "--config" +without a parameter and lvm will use whatever is next parameter +like the device path for pvremove. +--- + src/plugins/lvm-dbus.c | 5 ++++- + src/plugins/lvm.c | 5 ++++- + tests/lvm_dbus_tests.py | 12 ++++++++++++ + tests/lvm_test.py | 12 ++++++++++++ + 4 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index 22204d5..b7bd019 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -2644,7 +2644,10 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error UNUSE + g_free (global_config_str); + + /* now store the new one */ +- global_config_str = g_strdup (new_config); ++ if (!new_config || g_strcmp0 (new_config, "") == 0) ++ global_config_str = NULL; ++ else ++ global_config_str = g_strdup (new_config); + + g_mutex_unlock (&global_config_lock); + return TRUE; +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 605fcb0..124fce7 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -2016,7 +2016,10 @@ gboolean bd_lvm_set_global_config (const gchar *new_config, GError **error UNUSE + g_free (global_config_str); + + /* now store the new one */ +- global_config_str = g_strdup (new_config); ++ if (!new_config || g_strcmp0 (new_config, "") == 0) ++ global_config_str = NULL; ++ else ++ global_config_str = g_strdup (new_config); + + g_mutex_unlock (&global_config_lock); + return TRUE; +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index d422869..5516afe 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -1754,3 +1754,15 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + + with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): + BlockDev.lvm_devices_add("", self.devicefile) ++ ++ ++class LvmConfigTestPvremove(LvmPVonlyTestCase): ++ ++ @tag_test(TestTags.REGRESSION) ++ def test_set_empty_config(self): ++ succ = BlockDev.lvm_pvcreate(self.loop_dev) ++ self.assertTrue(succ) ++ ++ BlockDev.lvm_set_global_config("") ++ succ = BlockDev.lvm_pvremove(self.loop_dev) ++ self.assertTrue(succ) +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 882cdf2..e349817 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -1740,3 +1740,15 @@ class LvmTestDevicesFile(LvmPVonlyTestCase): + + with self.assertRaisesRegex(GLib.GError, "LVM devices file not enabled."): + BlockDev.lvm_devices_add("", self.devicefile) ++ ++ ++class LvmConfigTestPvremove(LvmPVonlyTestCase): ++ ++ @tag_test(TestTags.REGRESSION) ++ def test_set_empty_config(self): ++ succ = BlockDev.lvm_pvcreate(self.loop_dev) ++ self.assertTrue(succ) ++ ++ BlockDev.lvm_set_global_config("") ++ succ = BlockDev.lvm_pvremove(self.loop_dev) ++ self.assertTrue(succ) +-- +2.31.1 + + +From 2a4e610027a2c2a315054b84a323ce973939ca2d Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 16 Mar 2021 12:05:37 +0100 +Subject: [PATCH 7/8] vdo: Do not use g_memdup in bd_vdo_stats_copy + +g_memdup is deprecated and the replacement g_memdup2 is not yet +available so lets just do the copy manually. +--- + src/lib/plugin_apis/vdo.api | 17 ++++++++++++++++- + src/plugins/vdo.c | 17 ++++++++++++++++- + 2 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/src/lib/plugin_apis/vdo.api b/src/lib/plugin_apis/vdo.api +index 936f8e0..312de4e 100644 +--- a/src/lib/plugin_apis/vdo.api ++++ b/src/lib/plugin_apis/vdo.api +@@ -170,7 +170,22 @@ void bd_vdo_stats_free (BDVDOStats *stats) { + * Deprecated: 2.24: Use LVM-VDO integration instead. + */ + BDVDOStats* bd_vdo_stats_copy (BDVDOStats *stats) { +- return g_memdup (stats, sizeof (BDVDOStats)); ++ if (stats == NULL) ++ return NULL; ++ ++ BDVDOStats *new_stats = g_new0 (BDVDOStats, 1); ++ ++ new_stats->block_size = stats->block_size; ++ new_stats->logical_block_size = stats->logical_block_size; ++ new_stats->physical_blocks = stats->physical_blocks; ++ new_stats->data_blocks_used = stats->data_blocks_used; ++ new_stats->overhead_blocks_used = stats->overhead_blocks_used; ++ new_stats->logical_blocks_used = stats->logical_blocks_used; ++ new_stats->used_percent = stats->used_percent; ++ new_stats->saving_percent = stats->saving_percent; ++ new_stats->write_amplification_ratio = stats->write_amplification_ratio; ++ ++ return new_stats; + } + + GType bd_vdo_stats_get_type () { +diff --git a/src/plugins/vdo.c b/src/plugins/vdo.c +index 2352394..d443099 100644 +--- a/src/plugins/vdo.c ++++ b/src/plugins/vdo.c +@@ -81,7 +81,22 @@ void bd_vdo_stats_free (BDVDOStats *stats) { + } + + BDVDOStats* bd_vdo_stats_copy (BDVDOStats *stats) { +- return g_memdup (stats, sizeof (BDVDOStats)); ++ if (stats == NULL) ++ return NULL; ++ ++ BDVDOStats *new_stats = g_new0 (BDVDOStats, 1); ++ ++ new_stats->block_size = stats->block_size; ++ new_stats->logical_block_size = stats->logical_block_size; ++ new_stats->physical_blocks = stats->physical_blocks; ++ new_stats->data_blocks_used = stats->data_blocks_used; ++ new_stats->overhead_blocks_used = stats->overhead_blocks_used; ++ new_stats->logical_blocks_used = stats->logical_blocks_used; ++ new_stats->used_percent = stats->used_percent; ++ new_stats->saving_percent = stats->saving_percent; ++ new_stats->write_amplification_ratio = stats->write_amplification_ratio; ++ ++ return new_stats; + } + + +-- +2.31.1 + + +From 577ea466e3b7af464137e087907ba980ad3994ee Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Fri, 26 Nov 2021 15:19:55 +0100 +Subject: [PATCH 8/8] lvm: Use "lvmconfig full" to get valid config instead of + "current" + +"lvmconfig current" doesn't work together with --config even if we +don't override the "use_devicefile" key. "lvmconfig full" seems to +be working in all cases. +--- + src/plugins/lvm-dbus.c | 4 ++-- + src/plugins/lvm.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/plugins/lvm-dbus.c b/src/plugins/lvm-dbus.c +index b7bd019..825c5e9 100644 +--- a/src/plugins/lvm-dbus.c ++++ b/src/plugins/lvm-dbus.c +@@ -3955,9 +3955,9 @@ static gboolean _lvm_devices_enabled () { + gint scanned = 0; + g_autofree gchar *config_arg = NULL; + +- /* try current config first -- if we get something from this it means the feature is ++ /* try full config first -- if we get something from this it means the feature is + explicitly enabled or disabled by system lvm.conf or using the --config option */ +- args[2] = "current"; ++ args[2] = "full"; + + /* make sure to include the global config from us when getting the current config value */ + g_mutex_lock (&global_config_lock); +diff --git a/src/plugins/lvm.c b/src/plugins/lvm.c +index 124fce7..21320f3 100644 +--- a/src/plugins/lvm.c ++++ b/src/plugins/lvm.c +@@ -3251,9 +3251,9 @@ static gboolean _lvm_devices_enabled () { + gboolean enabled = FALSE; + gint scanned = 0; + +- /* try current config first -- if we get something from this it means the feature is ++ /* try full config first -- if we get something from this it means the feature is + explicitly enabled or disabled by system lvm.conf or using the --config option */ +- args[2] = "current"; ++ args[2] = "full"; + ret = call_lvm_and_capture_output (args, NULL, &output, &loc_error); + if (ret) { + scanned = sscanf (output, "use_devicesfile=%u", &enabled); +-- +2.31.1 + diff --git a/SOURCES/0008-lvm-Fix-reading-statistics-for-VDO-pools-with-VDO-8.patch b/SOURCES/0008-lvm-Fix-reading-statistics-for-VDO-pools-with-VDO-8.patch new file mode 100644 index 0000000..4d3796b --- /dev/null +++ b/SOURCES/0008-lvm-Fix-reading-statistics-for-VDO-pools-with-VDO-8.patch @@ -0,0 +1,80 @@ +From e0fcbae856454dba9df3f8df800d74fde66731e5 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Tue, 31 Aug 2021 14:07:23 +0200 +Subject: [PATCH] lvm: Fix reading statistics for VDO pools with VDO 8 + +The statistics are no longer available in /sys/kvdo, in the latest +version of kvdo we need to use /sys/block//vdo/statistics. + +Resolves: rhbz#1994220 +--- + src/plugins/vdo_stats.c | 42 +++++++++++++++++++++++++++++++++++++---- + 1 file changed, 38 insertions(+), 4 deletions(-) + +diff --git a/src/plugins/vdo_stats.c b/src/plugins/vdo_stats.c +index ed04b51..2e244aa 100644 +--- a/src/plugins/vdo_stats.c ++++ b/src/plugins/vdo_stats.c +@@ -133,6 +133,23 @@ static void add_computed_stats (GHashTable *stats) { + add_journal_stats (stats); + } + ++static gchar* _dm_node_from_name (const gchar *map_name, GError **error) { ++ gchar *dev_path = NULL; ++ gchar *ret = NULL; ++ gchar *dev_mapper_path = g_strdup_printf ("/dev/mapper/%s", map_name); ++ ++ dev_path = bd_utils_resolve_device (dev_mapper_path, error); ++ g_free (dev_mapper_path); ++ if (!dev_path) ++ /* error is already populated */ ++ return NULL; ++ ++ ret = g_path_get_basename (dev_path); ++ g_free (dev_path); ++ ++ return ret; ++} ++ + GHashTable __attribute__ ((visibility ("hidden"))) + *vdo_get_stats_full (const gchar *name, GError **error) { + GHashTable *stats; +@@ -141,14 +158,31 @@ GHashTable __attribute__ ((visibility ("hidden"))) + const gchar *direntry; + gchar *s; + gchar *val = NULL; ++ g_autofree gchar *dm_node = NULL; + +- /* TODO: does the `name` need to be escaped? */ +- stats_dir = g_build_path (G_DIR_SEPARATOR_S, VDO_SYS_PATH, name, "statistics", NULL); ++ /* try "new" (kvdo >= 8) path first -- /sys/block/dm-X/vdo/statistics */ ++ dm_node = _dm_node_from_name (name, error); ++ if (dm_node == NULL) { ++ g_prefix_error (error, "Failed to get DM node for %s: ", name); ++ return NULL; ++ } ++ ++ stats_dir = g_build_path (G_DIR_SEPARATOR_S, "/sys/block", dm_node, "vdo/statistics", NULL); + dir = g_dir_open (stats_dir, 0, error); + if (dir == NULL) { +- g_prefix_error (error, "Error reading statistics from %s: ", stats_dir); ++ g_debug ("Failed to read VDO stats using the new API, falling back to %s: %s", ++ VDO_SYS_PATH, (*error)->message); + g_free (stats_dir); +- return NULL; ++ g_clear_error (error); ++ ++ /* lets try /sys/kvdo */ ++ stats_dir = g_build_path (G_DIR_SEPARATOR_S, VDO_SYS_PATH, name, "statistics", NULL); ++ dir = g_dir_open (stats_dir, 0, error); ++ if (dir == NULL) { ++ g_prefix_error (error, "Error reading statistics from %s: ", stats_dir); ++ g_free (stats_dir); ++ return NULL; ++ } + } + + stats = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +-- +2.31.1 + diff --git a/SOURCES/0009-vdo_stats-Default-to-100-savings-for-invalid-savings.patch b/SOURCES/0009-vdo_stats-Default-to-100-savings-for-invalid-savings.patch new file mode 100644 index 0000000..f1ada49 --- /dev/null +++ b/SOURCES/0009-vdo_stats-Default-to-100-savings-for-invalid-savings.patch @@ -0,0 +1,30 @@ +From 940346f14ee5644f2593817b4196c18de8a713f0 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Mon, 22 Nov 2021 14:16:02 +0100 +Subject: [PATCH] vdo_stats: Default to 100 % savings for invalid savings + values + +We are currently using "-1" when VDO logical_blocks_used is 0 +which doesn't match the LVM logic which returns 100 so to make +both values in vdo_info and vdo_stats equal we should return 100 +in this case too. +--- + src/plugins/vdo_stats.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/plugins/vdo_stats.c b/src/plugins/vdo_stats.c +index 3ec2d60..f3f0390 100644 +--- a/src/plugins/vdo_stats.c ++++ b/src/plugins/vdo_stats.c +@@ -96,7 +96,7 @@ static void add_block_stats (GHashTable *stats) { + g_hash_table_replace (stats, g_strdup ("oneKBlocksUsed"), g_strdup_printf ("%"G_GINT64_FORMAT, (data_blocks_used + overhead_blocks_used) * block_size / 1024)); + g_hash_table_replace (stats, g_strdup ("oneKBlocksAvailable"), g_strdup_printf ("%"G_GINT64_FORMAT, (physical_blocks - data_blocks_used - overhead_blocks_used) * block_size / 1024)); + g_hash_table_replace (stats, g_strdup ("usedPercent"), g_strdup_printf ("%.0f", 100.0 * (gfloat) (data_blocks_used + overhead_blocks_used) / (gfloat) physical_blocks + 0.5)); +- savings = (logical_blocks_used > 0) ? (gint64) (100.0 * (gfloat) (logical_blocks_used - data_blocks_used) / (gfloat) logical_blocks_used) : -1; ++ savings = (logical_blocks_used > 0) ? (gint64) (100.0 * (gfloat) (logical_blocks_used - data_blocks_used) / (gfloat) logical_blocks_used) : 100; + g_hash_table_replace (stats, g_strdup ("savings"), g_strdup_printf ("%"G_GINT64_FORMAT, savings)); + if (savings >= 0) + g_hash_table_replace (stats, g_strdup ("savingPercent"), g_strdup_printf ("%"G_GINT64_FORMAT, savings)); +-- +2.31.1 + diff --git a/SOURCES/0010-Add-support-for-creating-and-activating-integrity-de.patch b/SOURCES/0010-Add-support-for-creating-and-activating-integrity-de.patch new file mode 100644 index 0000000..77d6bc8 --- /dev/null +++ b/SOURCES/0010-Add-support-for-creating-and-activating-integrity-de.patch @@ -0,0 +1,966 @@ +From 37f1aff5f5f967d6a4440d176f3de877aab789ac Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Mon, 20 Sep 2021 16:38:16 +0200 +Subject: [PATCH 1/3] Add support for creating and activating integrity devices + +This adds support for create, open and close actions for standalone +integrity devices using cryptsetup. +--- + configure.ac | 4 +- + src/lib/plugin_apis/crypto.api | 157 +++++++++++++++++ + src/plugins/crypto.c | 261 +++++++++++++++++++++++++++- + src/plugins/crypto.h | 41 +++++ + src/python/gi/overrides/BlockDev.py | 24 +++ + tests/crypto_test.py | 97 ++++++++++- + 6 files changed, 576 insertions(+), 8 deletions(-) + +diff --git a/configure.ac b/configure.ac +index abe1412..13830ae 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -210,7 +210,9 @@ AS_IF([test "x$with_crypto" != "xno"], + AS_IF([$PKG_CONFIG --atleast-version=2.0.3 libcryptsetup], + [AC_DEFINE([LIBCRYPTSETUP_2])], []) + AS_IF([$PKG_CONFIG --atleast-version=2.3.0 libcryptsetup], +- [AC_DEFINE([LIBCRYPTSETUP_BITLK])], []) ++ [AC_DEFINE([LIBCRYPTSETUP_23])], []) ++ AS_IF([$PKG_CONFIG --atleast-version=2.4.0 libcryptsetup], ++ [AC_DEFINE([LIBCRYPTSETUP_24])], []) + AS_IF([test "x$with_escrow" != "xno"], + [LIBBLOCKDEV_PKG_CHECK_MODULES([NSS], [nss >= 3.18.0]) + LIBBLOCKDEV_CHECK_HEADER([volume_key/libvolume_key.h], [$GLIB_CFLAGS $NSS_CFLAGS], [libvolume_key.h not available])], +diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api +index ef0217f..40e32c8 100644 +--- a/src/lib/plugin_apis/crypto.api ++++ b/src/lib/plugin_apis/crypto.api +@@ -1,5 +1,6 @@ + #include + #include ++#include + + #define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB + +@@ -245,6 +246,115 @@ GType bd_crypto_luks_extra_get_type () { + return type; + } + ++#define BD_CRYPTO_TYPE_INTEGRITY_EXTRA (bd_crypto_integrity_extra_get_type ()) ++GType bd_crypto_integrity_extra_get_type(); ++ ++/** ++ * BDCryptoIntegrityExtra: ++ * @sector_size: integrity sector size ++ * @journal_size: size of journal in bytes ++ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit ++ * @journal_commit_time: journal commit time (or bitmap flush time) in ms ++ * @interleave_sectors: number of interleave sectors (power of two) ++ * @tag_size: tag size per-sector in bytes ++ * @buffer_sectors: number of sectors in one buffer ++ */ ++typedef struct BDCryptoIntegrityExtra { ++ guint32 sector_size; ++ guint64 journal_size; ++ guint journal_watermark; ++ guint journal_commit_time; ++ guint32 interleave_sectors; ++ guint32 tag_size; ++ guint32 buffer_sectors; ++} BDCryptoIntegrityExtra; ++ ++/** ++ * bd_crypto_integrity_extra_copy: (skip) ++ * @extra: (allow-none): %BDCryptoIntegrityExtra to copy ++ * ++ * Creates a new copy of @extra. ++ */ ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) { ++ if (extra == NULL) ++ return NULL; ++ ++ BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1); ++ ++ new_extra->sector_size = extra->sector_size; ++ new_extra->journal_size = extra->journal_size; ++ new_extra->journal_watermark = extra->journal_watermark; ++ new_extra->journal_commit_time = extra->journal_commit_time; ++ new_extra->interleave_sectors = extra->interleave_sectors; ++ new_extra->tag_size = extra->tag_size; ++ new_extra->buffer_sectors = extra->buffer_sectors; ++ ++ return new_extra; ++} ++ ++/** ++ * bd_crypto_integrity_extra_free: (skip) ++ * @extra: (allow-none): %BDCryptoIntegrityExtra to free ++ * ++ * Frees @extra. ++ */ ++void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) { ++ if (extra == NULL) ++ return; ++ ++ g_free (extra); ++} ++ ++/** ++ * bd_crypto_integrity_extra_new: (constructor) ++ * @sector_size: integrity sector size, 0 for default (512) ++ * @journal_size: size of journal in bytes ++ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit ++ * @journal_commit_time: journal commit time (or bitmap flush time) in ms ++ * @interleave_sectors: number of interleave sectors (power of two) ++ * @tag_size: tag size per-sector in bytes ++ * @buffer_sectors: number of sectors in one buffer ++ * ++ * Returns: (transfer full): a new Integrity extra argument ++ */ ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) { ++ BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1); ++ ret->sector_size = sector_size; ++ ret->journal_size = journal_size; ++ ret->journal_watermark = journal_watermark; ++ ret->journal_commit_time = journal_commit_time; ++ ret->interleave_sectors = interleave_sectors; ++ ret->tag_size = tag_size; ++ ret->buffer_sectors = buffer_sectors; ++ ++ return ret; ++} ++ ++GType bd_crypto_integrity_extra_get_type () { ++ static GType type = 0; ++ ++ if (G_UNLIKELY(type == 0)) { ++ type = g_boxed_type_register_static("BDCryptoIntegrityExtra", ++ (GBoxedCopyFunc) bd_crypto_integrity_extra_copy, ++ (GBoxedFreeFunc) bd_crypto_integrity_extra_free); ++ } ++ ++ return type; ++} ++ ++typedef enum { ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, ++ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, ++#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, ++#endif ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, ++#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, ++#endif ++ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, ++} BDCryptoIntegrityOpenFlags; ++ + #define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ()) + GType bd_crypto_luks_info_get_type(); + +@@ -857,6 +967,53 @@ BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error) + */ + BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error); + ++/** ++ * bd_crypto_integrity_format: ++ * @device: a device to format as integrity ++ * @algorithm: integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default ++ * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums ++ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed ++ * @key_size: size the integrity key and @key_data ++ * @extra: (allow-none): extra arguments for integrity format creation ++ * @error: (out): place to store error (if any) ++ * ++ * Formats the given @device as integrity according to the other parameters given. ++ * ++ * Returns: whether the given @device was successfully formatted as integrity or not ++ * (the @error) contains the error in such cases) ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE ++ */ ++gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error); ++ ++/** ++ * bd_crypto_integrity_open: ++ * @device: integrity device to open ++ * @name: name for the opened @device ++ * @algorithm: (allow-none): integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default ++ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed ++ * @key_size: size the integrity key and @key_data ++ * @flags: flags for the integrity device activation ++ * @extra: (allow-none): extra arguments for integrity open ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully opened or not ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE ++ */ ++gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error); ++ ++/** ++ * bd_crypto_integrity_close: ++ * @integrity_device: integrity device to close ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the given @integrity_device was successfully closed or not ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE ++ */ ++gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error); ++ + /** + * bd_crypto_device_seems_encrypted: + * @device: the queried device +diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c +index 4fad9a8..b1b0700 100644 +--- a/src/plugins/crypto.c ++++ b/src/plugins/crypto.c +@@ -50,6 +50,18 @@ + + #define SECTOR_SIZE 512 + ++#define DEFAULT_LUKS_KEYSIZE_BITS 256 ++#define DEFAULT_LUKS_CIPHER "aes-xts-plain64" ++ ++#ifdef LIBCRYPTSETUP_23 ++/* 0 for autodetect since 2.3.0 */ ++#define DEFAULT_INTEGRITY_TAG_SIZE 0 ++#else ++/* we need some sane default for older versions, users should specify tag size when using ++ other algorithms than the default crc32c */ ++#define DEFAULT_INTEGRITY_TAG_SIZE 4 ++#endif ++ + #define UNUSED __attribute__((unused)) + + /** +@@ -146,6 +158,43 @@ BDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar + return ret; + } + ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) { ++ BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1); ++ ret->sector_size = sector_size; ++ ret->journal_size = journal_size; ++ ret->journal_watermark = journal_watermark; ++ ret->journal_commit_time = journal_commit_time; ++ ret->interleave_sectors = interleave_sectors; ++ ret->tag_size = tag_size; ++ ret->buffer_sectors = buffer_sectors; ++ ++ return ret; ++} ++ ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) { ++ if (extra == NULL) ++ return NULL; ++ ++ BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1); ++ ++ new_extra->sector_size = extra->sector_size; ++ new_extra->journal_size = extra->journal_size; ++ new_extra->journal_watermark = extra->journal_watermark; ++ new_extra->journal_commit_time = extra->journal_commit_time; ++ new_extra->interleave_sectors = extra->interleave_sectors; ++ new_extra->tag_size = extra->tag_size; ++ new_extra->buffer_sectors = extra->buffer_sectors; ++ ++ return new_extra; ++} ++ ++void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) { ++ if (extra == NULL) ++ return; ++ ++ g_free (extra); ++} ++ + void bd_crypto_luks_info_free (BDCryptoLUKSInfo *info) { + if (info == NULL) + return; +@@ -346,15 +395,15 @@ gboolean bd_crypto_is_tech_avail (BDCryptoTech tech, guint64 mode, GError **erro + "Integrity technology requires libcryptsetup >= 2.0"); + return FALSE; + #endif +- ret = mode & (BD_CRYPTO_TECH_MODE_QUERY); ++ ret = mode & (BD_CRYPTO_TECH_MODE_CREATE|BD_CRYPTO_TECH_MODE_OPEN_CLOSE|BD_CRYPTO_TECH_MODE_QUERY); + if (ret != mode) { + g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, +- "Only 'query' supported for Integrity"); ++ "Only 'create', 'open' and 'query' supported for Integrity"); + return FALSE; + } else + return TRUE; + case BD_CRYPTO_TECH_BITLK: +-#ifndef LIBCRYPTSETUP_BITLK ++#ifndef LIBCRYPTSETUP_23 + g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, + "BITLK technology requires libcryptsetup >= 2.3.0"); + return FALSE; +@@ -2035,6 +2084,208 @@ BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **e + } + #endif + ++static int _wipe_progress (guint64 size, guint64 offset, void *usrptr) { ++ /* "convert" the progress from 0-100 to 50-100 because wipe starts at 50 in bd_crypto_integrity_format */ ++ gdouble progress = 50 + (((gdouble) offset / size) * 100) / 2; ++ bd_utils_report_progress (*(guint64 *) usrptr, progress, "Integrity device wipe in progress"); ++ ++ return 0; ++} ++ ++/** ++ * bd_crypto_integrity_format: ++ * @device: a device to format as integrity ++ * @algorithm: integrity algorithm specification (e.g. "crc32c" or "sha256") ++ * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums ++ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed ++ * @key_size: size the integrity key and @key_data ++ * @extra: (allow-none): extra arguments for integrity format creation ++ * @error: (out): place to store error (if any) ++ * ++ * Formats the given @device as integrity according to the other parameters given. ++ * ++ * Returns: whether the given @device was successfully formatted as integrity or not ++ * (the @error) contains the error in such cases) ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE ++ */ ++gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error) { ++ struct crypt_device *cd = NULL; ++ gint ret; ++ guint64 progress_id = 0; ++ gchar *msg = NULL; ++ struct crypt_params_integrity params = ZERO_INIT; ++ g_autofree gchar *tmp_name = NULL; ++ g_autofree gchar *tmp_path = NULL; ++ g_autofree gchar *dev_name = NULL; ++ ++ msg = g_strdup_printf ("Started formatting '%s' as integrity device", device); ++ progress_id = bd_utils_report_started (msg); ++ g_free (msg); ++ ++ ret = crypt_init (&cd, device); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to initialize device: %s", strerror_l (-ret, c_locale)); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ if (extra) { ++ params.sector_size = extra->sector_size; ++ params.journal_size = extra->journal_size; ++ params.journal_watermark = extra->journal_watermark; ++ params.journal_commit_time = extra->journal_commit_time; ++ params.interleave_sectors = extra->interleave_sectors; ++ params.tag_size = extra->tag_size; ++ params.buffer_sectors = extra->buffer_sectors; ++ } ++ ++ params.integrity_key_size = key_size; ++ params.integrity = algorithm; ++ params.tag_size = params.tag_size ? params.tag_size : DEFAULT_INTEGRITY_TAG_SIZE; ++ ++ ret = crypt_format (cd, CRYPT_INTEGRITY, NULL, NULL, NULL, NULL, 0, ¶ms); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED, ++ "Failed to format device: %s", strerror_l (-ret, c_locale)); ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ if (wipe) { ++ bd_utils_report_progress (progress_id, 50, "Format created"); ++ ++ dev_name = g_path_get_basename (device); ++ tmp_name = g_strdup_printf ("bd-temp-integrity-%s-%d", dev_name, g_random_int ()); ++ tmp_path = g_strdup_printf ("%s/%s", crypt_get_dir (), tmp_name); ++ ++ ret = crypt_activate_by_volume_key (cd, tmp_name, (const char *) key_data, key_size, ++ CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to activate the newly created integrity device for wiping: %s", ++ strerror_l (-ret, c_locale)); ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ bd_utils_report_progress (progress_id, 50, "Starting to wipe the newly created integrity device"); ++ ret = crypt_wipe (cd, tmp_path, CRYPT_WIPE_ZERO, 0, 0, 1048576, ++ 0, &_wipe_progress, &progress_id); ++ bd_utils_report_progress (progress_id, 100, "Wipe finished"); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to wipe the newly created integrity device: %s", ++ strerror_l (-ret, c_locale)); ++ ++ ret = crypt_deactivate (cd, tmp_name); ++ if (ret != 0) ++ g_warning ("Failed to deactivate temporary device %s", tmp_name); ++ ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ ret = crypt_deactivate (cd, tmp_name); ++ if (ret != 0) ++ g_warning ("Failed to deactivate temporary device %s", tmp_name); ++ ++ } else ++ bd_utils_report_finished (progress_id, "Completed"); ++ ++ crypt_free (cd); ++ ++ return TRUE; ++} ++ ++/** ++ * bd_crypto_integrity_open: ++ * @device: integrity device to open ++ * @name: name for the opened @device ++ * @algorithm: (allow-none): integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default ++ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed ++ * @key_size: size the integrity key and @key_data ++ * @flags: flags for the integrity device activation ++ * @extra: (allow-none): extra arguments for integrity open ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the @device was successfully opened or not ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE ++ */ ++gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error) { ++ struct crypt_device *cd = NULL; ++ gint ret = 0; ++ guint64 progress_id = 0; ++ gchar *msg = NULL; ++ struct crypt_params_integrity params = ZERO_INIT; ++ ++ params.integrity = algorithm; ++ params.integrity_key_size = key_size; ++ ++ if (extra) { ++ params.sector_size = extra->sector_size; ++ params.journal_size = extra->journal_size; ++ params.journal_watermark = extra->journal_watermark; ++ params.journal_commit_time = extra->journal_commit_time; ++ params.interleave_sectors = extra->interleave_sectors; ++ params.tag_size = extra->tag_size; ++ params.buffer_sectors = extra->buffer_sectors; ++ } ++ ++ msg = g_strdup_printf ("Started opening '%s' integrity device", device); ++ progress_id = bd_utils_report_started (msg); ++ g_free (msg); ++ ++ ret = crypt_init (&cd, device); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to initialize device: %s", strerror_l (-ret, c_locale)); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ ret = crypt_load (cd, CRYPT_INTEGRITY, ¶ms); ++ if (ret != 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to load device's parameters: %s", strerror_l (-ret, c_locale)); ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, flags); ++ if (ret < 0) { ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, ++ "Failed to activate device: %s", strerror_l (-ret, c_locale)); ++ ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++ } ++ ++ crypt_free (cd); ++ bd_utils_report_finished (progress_id, "Completed"); ++ return TRUE; ++} ++ ++/** ++ * bd_crypto_integrity_close: ++ * @integrity_device: integrity device to close ++ * @error: (out): place to store error (if any) ++ * ++ * Returns: whether the given @integrity_device was successfully closed or not ++ * ++ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE ++ */ ++gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error) { ++ return _crypto_close (integrity_device, "integrity", error); ++} ++ + /** + * bd_crypto_device_seems_encrypted: + * @device: the queried device +@@ -2472,7 +2723,7 @@ gboolean bd_crypto_escrow_device (const gchar *device, const gchar *passphrase, + * + * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE + */ +-#ifndef LIBCRYPTSETUP_BITLK ++#ifndef LIBCRYPTSETUP_23 + gboolean bd_crypto_bitlk_open (const gchar *device UNUSED, const gchar *name UNUSED, const guint8* pass_data UNUSED, gsize data_len UNUSED, gboolean read_only UNUSED, GError **error) { + /* this will return FALSE and set error, because BITLK technology is not available */ + return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_BITLK, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error); +@@ -2542,7 +2793,7 @@ gboolean bd_crypto_bitlk_open (const gchar *device, const gchar *name, const gui + * + * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE + */ +-#ifndef LIBCRYPTSETUP_BITLK ++#ifndef LIBCRYPTSETUP_23 + gboolean bd_crypto_bitlk_close (const gchar *bitlk_device UNUSED, GError **error) { + /* this will return FALSE and set error, because BITLK technology is not available */ + return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_BITLK, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error); +diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h +index a38724d..166e558 100644 +--- a/src/plugins/crypto.h ++++ b/src/plugins/crypto.h +@@ -116,6 +116,43 @@ void bd_crypto_luks_extra_free (BDCryptoLUKSExtra *extra); + BDCryptoLUKSExtra* bd_crypto_luks_extra_copy (BDCryptoLUKSExtra *extra); + BDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar *data_device, const gchar *integrity, guint64 sector_size, const gchar *label, const gchar *subsystem, BDCryptoLUKSPBKDF *pbkdf); + ++/** ++ * BDCryptoIntegrityExtra: ++ * @sector_size: integrity sector size ++ * @journal_size: size of journal in bytes ++ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit ++ * @journal_commit_time: journal commit time (or bitmap flush time) in ms ++ * @interleave_sectors: number of interleave sectors (power of two) ++ * @tag_size: tag size per-sector in bytes ++ * @buffer_sectors: number of sectors in one buffer ++ */ ++typedef struct BDCryptoIntegrityExtra { ++ guint32 sector_size; ++ guint64 journal_size; ++ guint journal_watermark; ++ guint journal_commit_time; ++ guint32 interleave_sectors; ++ guint32 tag_size; ++ guint32 buffer_sectors; ++} BDCryptoIntegrityExtra; ++ ++void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra); ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra); ++BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors); ++ ++typedef enum { ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, ++ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, ++#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, ++#endif ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, ++#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, ++#endif ++ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, ++} BDCryptoIntegrityOpenFlags; ++ + /** + * BDCryptoLUKSInfo: + * @version: LUKS version +@@ -209,6 +246,10 @@ gboolean bd_crypto_luks_header_restore (const gchar *device, const gchar *backup + BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error); + BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error); + ++gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error); ++gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error); ++gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error); ++ + gboolean bd_crypto_device_seems_encrypted (const gchar *device, GError **error); + gboolean bd_crypto_tc_open (const gchar *device, const gchar *name, const guint8* pass_data, gsize data_len, gboolean read_only, GError **error); + gboolean bd_crypto_tc_open_full (const gchar *device, const gchar *name, const guint8* pass_data, gsize data_len, const gchar **keyfiles, gboolean hidden, gboolean system, gboolean veracrypt, guint32 veracrypt_pim, gboolean read_only, GError **error); +diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py +index 715a262..71bcd31 100644 +--- a/src/python/gi/overrides/BlockDev.py ++++ b/src/python/gi/overrides/BlockDev.py +@@ -276,6 +276,30 @@ def crypto_bitlk_open(device, name, passphrase, read_only=False): + __all__.append("crypto_bitlk_open") + + ++class CryptoIntegrityExtra(BlockDev.CryptoIntegrityExtra): ++ def __new__(cls, sector_size=0, journal_size=0, journal_watermark=0, journal_commit_time=0, interleave_sectors=0, tag_size=0, buffer_sectors=0): ++ ret = BlockDev.CryptoIntegrityExtra.new(sector_size, journal_size, journal_watermark, journal_commit_time, interleave_sectors, tag_size, buffer_sectors) ++ ret.__class__ = cls ++ return ret ++ def __init__(self, *args, **kwargs): # pylint: disable=unused-argument ++ super(CryptoIntegrityExtra, self).__init__() #pylint: disable=bad-super-call ++CryptoIntegrityExtra = override(CryptoIntegrityExtra) ++__all__.append("CryptoIntegrityExtra") ++ ++ ++_crypto_integrity_format = BlockDev.crypto_integrity_format ++@override(BlockDev.crypto_integrity_format) ++def crypto_integrity_format(device, algorithm=None, wipe=True, key_data=None, extra=None): ++ return _crypto_integrity_format(device, algorithm, wipe, key_data, extra) ++__all__.append("crypto_integrity_format") ++ ++_crypto_integrity_open = BlockDev.crypto_integrity_open ++@override(BlockDev.crypto_integrity_open) ++def crypto_integrity_open(device, name, algorithm, key_data=None, flags=0, extra=None): ++ return _crypto_integrity_open(device, name, algorithm, key_data, flags, extra) ++__all__.append("crypto_integrity_open") ++ ++ + _dm_create_linear = BlockDev.dm_create_linear + @override(BlockDev.dm_create_linear) + def dm_create_linear(map_name, device, length, uuid=None): +diff --git a/tests/crypto_test.py b/tests/crypto_test.py +index 0aecc03..1c6832e 100644 +--- a/tests/crypto_test.py ++++ b/tests/crypto_test.py +@@ -2,6 +2,7 @@ import unittest + import os + import tempfile + import overrides_hack ++import secrets + import shutil + import subprocess + import six +@@ -42,6 +43,8 @@ class CryptoTestCase(unittest.TestCase): + + requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "loop")) + ++ _dm_name = "libblockdevTestLUKS" ++ + @classmethod + def setUpClass(cls): + unittest.TestCase.setUpClass() +@@ -72,7 +75,7 @@ class CryptoTestCase(unittest.TestCase): + + def _clean_up(self): + try: +- BlockDev.crypto_luks_close("libblockdevTestLUKS") ++ BlockDev.crypto_luks_close(self._dm_name) + except: + pass + +@@ -964,7 +967,8 @@ class CryptoTestInfo(CryptoTestCase): + succ = BlockDev.crypto_luks_close("libblockdevTestLUKS") + self.assertTrue(succ) + +-class CryptoTestIntegrity(CryptoTestCase): ++ ++class CryptoTestLUKS2Integrity(CryptoTestCase): + @tag_test(TestTags.SLOW) + @unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") + def test_luks2_integrity(self): +@@ -1151,3 +1155,92 @@ class CryptoTestBitlk(CryptoTestCase): + succ = BlockDev.crypto_bitlk_close("libblockdevTestBitlk") + self.assertTrue(succ) + self.assertFalse(os.path.exists("/dev/mapper/libblockdevTestBitlk")) ++ ++ ++class CryptoTestIntegrity(CryptoTestCase): ++ ++ _dm_name = "libblockdevTestIntegrity" ++ ++ @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") ++ def test_integrity(self): ++ # basic format+open+close test ++ succ = BlockDev.crypto_integrity_format(self.loop_dev, "sha256", False) ++ self.assertTrue(succ) ++ ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "sha256") ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ info = BlockDev.crypto_integrity_info(self._dm_name) ++ self.assertEqual(info.algorithm, "sha256") ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ # same now with a keyed algorithm ++ key = list(secrets.token_bytes(64)) ++ ++ succ = BlockDev.crypto_integrity_format(self.loop_dev, "hmac(sha256)", False, key) ++ self.assertTrue(succ) ++ ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "hmac(sha256)", key) ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ info = BlockDev.crypto_integrity_info(self._dm_name) ++ self.assertEqual(info.algorithm, "hmac(sha256)") ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ # same with some custom parameters ++ extra = BlockDev.CryptoIntegrityExtra(sector_size=4096, interleave_sectors=65536) ++ succ = BlockDev.crypto_integrity_format(self.loop_dev, "crc32c", wipe=False, extra=extra) ++ self.assertTrue(succ) ++ ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "crc32c") ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ info = BlockDev.crypto_integrity_info(self._dm_name) ++ self.assertEqual(info.algorithm, "crc32c") ++ self.assertEqual(info.sector_size, 4096) ++ self.assertEqual(info.interleave_sectors, 65536) ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ @tag_test(TestTags.SLOW) ++ @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") ++ def test_integrity_wipe(self): ++ # also check that wipe progress reporting works ++ progress_log = [] ++ ++ def _my_progress_func(_task, _status, completion, msg): ++ progress_log.append((completion, msg)) ++ ++ succ = BlockDev.utils_init_prog_reporting(_my_progress_func) ++ self.assertTrue(succ) ++ self.addCleanup(BlockDev.utils_init_prog_reporting, None) ++ ++ succ = BlockDev.crypto_integrity_format(self.loop_dev, "sha256", True) ++ self.assertTrue(succ) ++ ++ # at least one message "Integrity device wipe in progress" should be logged ++ self.assertTrue(any(prog[1] == "Integrity device wipe in progress" for prog in progress_log)) ++ ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "sha256") ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ # check the devices was wiped and the checksums recalculated ++ # (mkfs reads some blocks first so without checksums it would fail) ++ ret, _out, err = run_command("mkfs.ext2 /dev/mapper/%s " % self._dm_name) ++ self.assertEqual(ret, 0, msg="Failed to create ext2 filesystem on integrity: %s" % err) ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) +-- +2.31.1 + + +From 4dcb7a42a2cb33f7a63021d72889c9a9688adfd3 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Thu, 30 Sep 2021 16:01:40 +0200 +Subject: [PATCH 2/3] Create smaller test images for integrity tests + +We are going to overwrite the entire device in test_integrity_wipe +so we need to make sure the sparse actually fits to /tmp which +can be smaller than 1 GiB. +--- + tests/crypto_test.py | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/tests/crypto_test.py b/tests/crypto_test.py +index 1c6832e..b7ec251 100644 +--- a/tests/crypto_test.py ++++ b/tests/crypto_test.py +@@ -44,6 +44,7 @@ class CryptoTestCase(unittest.TestCase): + requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "loop")) + + _dm_name = "libblockdevTestLUKS" ++ _sparse_size = 1024**3 + + @classmethod + def setUpClass(cls): +@@ -57,8 +58,8 @@ class CryptoTestCase(unittest.TestCase): + + def setUp(self): + self.addCleanup(self._clean_up) +- self.dev_file = create_sparse_tempfile("crypto_test", 1024**3) +- self.dev_file2 = create_sparse_tempfile("crypto_test2", 1024**3) ++ self.dev_file = create_sparse_tempfile("crypto_test", self._sparse_size) ++ self.dev_file2 = create_sparse_tempfile("crypto_test2", self._sparse_size) + try: + self.loop_dev = create_lio_device(self.dev_file) + except RuntimeError as e: +@@ -1160,6 +1161,7 @@ class CryptoTestBitlk(CryptoTestCase): + class CryptoTestIntegrity(CryptoTestCase): + + _dm_name = "libblockdevTestIntegrity" ++ _sparse_size = 100 * 1024**2 + + @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") + def test_integrity(self): +-- +2.31.1 + + +From 3b82f9085c0df2e58b673716cdefd747495738e2 Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 20 Oct 2021 10:27:41 +0200 +Subject: [PATCH 3/3] crypto: Do not use libcryptsetup flags directly in + crypto.h + +We can "translate" our flags in the implementation instead to +avoid including libcryptsetup.h in our header and API files. +--- + src/lib/plugin_apis/crypto.api | 17 ++++++----------- + src/plugins/crypto.c | 34 +++++++++++++++++++++++++++++++++- + src/plugins/crypto.h | 16 ++++++---------- + tests/crypto_test.py | 14 ++++++++++++++ + 4 files changed, 59 insertions(+), 22 deletions(-) + +diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api +index 40e32c8..cf87979 100644 +--- a/src/lib/plugin_apis/crypto.api ++++ b/src/lib/plugin_apis/crypto.api +@@ -1,6 +1,5 @@ + #include + #include +-#include + + #define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB + +@@ -343,16 +342,12 @@ GType bd_crypto_integrity_extra_get_type () { + } + + typedef enum { +- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, +- BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, +-#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP +- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, +-#endif +- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, +-#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET +- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, +-#endif +- BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = 1 << 0, ++ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = 1 << 1, ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = 1 << 2, ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = 1 << 3, ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = 1 << 4, ++ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5, + } BDCryptoIntegrityOpenFlags; + + #define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ()) +diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c +index b1b0700..8a4d64a 100644 +--- a/src/plugins/crypto.c ++++ b/src/plugins/crypto.c +@@ -2223,6 +2223,7 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const + guint64 progress_id = 0; + gchar *msg = NULL; + struct crypt_params_integrity params = ZERO_INIT; ++ guint32 activate_flags = 0; + + params.integrity = algorithm; + params.integrity_key_size = key_size; +@@ -2237,6 +2238,37 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const + params.buffer_sectors = extra->buffer_sectors; + } + ++ ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL) ++ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL; ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECOVERY) ++ activate_flags |= CRYPT_ACTIVATE_RECOVERY; ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE) ++ activate_flags |= CRYPT_ACTIVATE_RECALCULATE; ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS) ++ activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP) { ++#ifndef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, ++ "Cannot activate %s with bitmap, installed version of cryptsetup doesn't support this option.", device); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++#else ++ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP; ++#endif ++ } ++ ++ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET) { ++#ifndef CRYPT_ACTIVATE_RECALCULATE_RESET ++ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, ++ "Cannot reset integrity recalculation while activating %s, installed version of cryptsetup doesn't support this option.", device); ++ bd_utils_report_finished (progress_id, (*error)->message); ++ return FALSE; ++#else ++ activate_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET; ++#endif ++ } ++ + msg = g_strdup_printf ("Started opening '%s' integrity device", device); + progress_id = bd_utils_report_started (msg); + g_free (msg); +@@ -2258,7 +2290,7 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const + return FALSE; + } + +- ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, flags); ++ ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, activate_flags); + if (ret < 0) { + g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, + "Failed to activate device: %s", strerror_l (-ret, c_locale)); +diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h +index 166e558..b5f133c 100644 +--- a/src/plugins/crypto.h ++++ b/src/plugins/crypto.h +@@ -141,16 +141,12 @@ BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra * + BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors); + + typedef enum { +- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, +- BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, +-#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP +- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, +-#endif +- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, +-#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET +- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, +-#endif +- BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = 1 << 0, ++ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = 1 << 1, ++ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = 1 << 2, ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = 1 << 3, ++ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = 1 << 4, ++ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5, + } BDCryptoIntegrityOpenFlags; + + /** +diff --git a/tests/crypto_test.py b/tests/crypto_test.py +index b7ec251..673d8b8 100644 +--- a/tests/crypto_test.py ++++ b/tests/crypto_test.py +@@ -1215,6 +1215,20 @@ class CryptoTestIntegrity(CryptoTestCase): + self.assertTrue(succ) + self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) + ++ # open with flags ++ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "crc32c", ++ flags=BlockDev.CryptoIntegrityOpenFlags.ALLOW_DISCARDS) ++ self.assertTrue(succ) ++ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ ++ # check that discard is enabled for the mapped device ++ _ret, out, _err = run_command("dmsetup table %s" % self._dm_name) ++ self.assertIn("allow_discards", out) ++ ++ succ = BlockDev.crypto_integrity_close(self._dm_name) ++ self.assertTrue(succ) ++ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) ++ + @tag_test(TestTags.SLOW) + @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") + def test_integrity_wipe(self): +-- +2.31.1 + diff --git a/SOURCES/0011-tests-Wait-for-raid-and-mirrored-LVs-to-be-synced-be.patch b/SOURCES/0011-tests-Wait-for-raid-and-mirrored-LVs-to-be-synced-be.patch new file mode 100644 index 0000000..938a8a4 --- /dev/null +++ b/SOURCES/0011-tests-Wait-for-raid-and-mirrored-LVs-to-be-synced-be.patch @@ -0,0 +1,278 @@ +From d0ba031e679d480855bea61060acea597d5ffbbd Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Wed, 15 Dec 2021 14:14:19 +0100 +Subject: [PATCH 1/2] tests: Wait for raid and mirrored LVs to be synced before + removing + +Resolves: rhbz#2030647 +--- + tests/lvm_dbus_tests.py | 31 +++++++++++++++++++++++++------ + tests/lvm_test.py | 31 +++++++++++++++++++++++++------ + 2 files changed, 50 insertions(+), 12 deletions(-) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 5516afe..5ce653e 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -7,6 +7,8 @@ import six + import re + import shutil + import subprocess ++import time ++from contextlib import contextmanager + from distutils.version import LooseVersion + from itertools import chain + +@@ -18,6 +20,21 @@ sb = dbus.SystemBus() + lvm_dbus_running = any("lvmdbus" in name for name in chain(sb.list_names(), sb.list_activatable_names())) + + ++@contextmanager ++def wait_for_sync(vg_name, lv_name): ++ try: ++ yield ++ finally: ++ time.sleep(2) ++ while True: ++ ret, out, _err = run_command("LC_ALL=C lvs -o copy_percent --noheadings %s/%s" % (vg_name, lv_name)) ++ if ret != 0: ++ break ++ if int(float(out)) == 100: ++ break ++ time.sleep(1) ++ ++ + class LVMTestCase(unittest.TestCase): + @classmethod + def setUpClass(cls): +@@ -801,9 +818,10 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + succ = BlockDev.lvm_lvremove("testVG", "testLV", True, None) + self.assertTrue(succ) + +- # try to create a mirrored LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) +- self.assertTrue(succ) ++ with wait_for_sync("testVG", "testLV"): ++ # try to create a mirrored LV ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) ++ self.assertTrue(succ) + + # verify that the LV has the requested segtype + info = BlockDev.lvm_lvinfo("testVG", "testLV") +@@ -812,9 +830,10 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + succ = BlockDev.lvm_lvremove("testVG", "testLV", True, None) + self.assertTrue(succ) + +- # try to create a raid1 LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) +- self.assertTrue(succ) ++ with wait_for_sync("testVG", "testLV"): ++ # try to create a raid1 LV ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) ++ self.assertTrue(succ) + + # verify that the LV has the requested segtype + info = BlockDev.lvm_lvinfo("testVG", "testLV") +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index e349817..12b78ca 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -7,12 +7,29 @@ import six + import re + import shutil + import subprocess ++import time ++from contextlib import contextmanager + from distutils.version import LooseVersion + + from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command, read_file + from gi.repository import BlockDev, GLib + + ++@contextmanager ++def wait_for_sync(vg_name, lv_name): ++ try: ++ yield ++ finally: ++ time.sleep(2) ++ while True: ++ info = BlockDev.lvm_lvinfo(vg_name, lv_name) ++ if not info: ++ break ++ if info.copy_percent == 100: ++ break ++ time.sleep(1) ++ ++ + class LVMTestCase(unittest.TestCase): + + @classmethod +@@ -737,9 +754,10 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + succ = BlockDev.lvm_lvremove("testVG", "testLV", True, None) + self.assertTrue(succ) + +- # try to create a mirrored LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) +- self.assertTrue(succ) ++ with wait_for_sync("testVG", "testLV"): ++ # try to create a mirrored LV ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) ++ self.assertTrue(succ) + + # verify that the LV has the requested segtype + info = BlockDev.lvm_lvinfo("testVG", "testLV") +@@ -748,9 +766,10 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + succ = BlockDev.lvm_lvremove("testVG", "testLV", True, None) + self.assertTrue(succ) + +- # try to create a raid1 LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) +- self.assertTrue(succ) ++ with wait_for_sync("testVG", "testLV"): ++ # try to create a raid1 LV ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) ++ self.assertTrue(succ) + + # verify that the LV has the requested segtype + info = BlockDev.lvm_lvinfo("testVG", "testLV") +-- +2.31.1 + + +From 36dbac970bc4a052dbd97f51eb47379036d15b6e Mon Sep 17 00:00:00 2001 +From: Vojtech Trefny +Date: Thu, 16 Dec 2021 12:27:33 +0100 +Subject: [PATCH 2/2] tests: Make smaller images for test_lvcreate_type + +We are now waiting for the initial resync for the RAID/mirror LVs +which means we are trying to overwrite the entire 1 GB image which +doesn't fit in /tmp on our CI machines. +--- + tests/lvm_dbus_tests.py | 16 +++++++++++----- + tests/lvm_test.py | 15 ++++++++++----- + 2 files changed, 21 insertions(+), 10 deletions(-) + +diff --git a/tests/lvm_dbus_tests.py b/tests/lvm_dbus_tests.py +index 5ce653e..723aabb 100644 +--- a/tests/lvm_dbus_tests.py ++++ b/tests/lvm_dbus_tests.py +@@ -313,14 +313,17 @@ class LvmNoDevTestCase(LVMTestCase): + + @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") + class LvmPVonlyTestCase(LVMTestCase): ++ ++ _sparse_size = 1024**3 ++ + # :TODO: + # * test pvmove (must create two PVs, a VG, a VG and some data in it + # first) + # * some complex test for pvs, vgs, lvs, pvinfo, vginfo and lvinfo + def setUp(self): + self.addCleanup(self._clean_up) +- self.dev_file = create_sparse_tempfile("lvm_test", 1024**3) +- self.dev_file2 = create_sparse_tempfile("lvm_test", 1024**3) ++ self.dev_file = create_sparse_tempfile("lvm_test", self._sparse_size) ++ self.dev_file2 = create_sparse_tempfile("lvm_test", self._sparse_size) + try: + self.loop_dev = create_lio_device(self.dev_file) + except RuntimeError as e: +@@ -795,6 +798,9 @@ class LvmTestLVcreateWithExtra(LvmPVVGLVTestCase): + + @unittest.skipUnless(lvm_dbus_running, "LVM DBus not running") + class LvmTestLVcreateType(LvmPVVGLVTestCase): ++ ++ _sparse_size = 200 * 1024**2 ++ + def test_lvcreate_type(self): + """Verify it's possible to create LVs with various types""" + +@@ -808,7 +814,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + self.assertTrue(succ) + + # try to create a striped LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "striped", [self.loop_dev, self.loop_dev2], None) ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "striped", [self.loop_dev, self.loop_dev2], None) + self.assertTrue(succ) + + # verify that the LV has the requested segtype +@@ -820,7 +826,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + + with wait_for_sync("testVG", "testLV"): + # try to create a mirrored LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) + self.assertTrue(succ) + + # verify that the LV has the requested segtype +@@ -832,7 +838,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + + with wait_for_sync("testVG", "testLV"): + # try to create a raid1 LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) + self.assertTrue(succ) + + # verify that the LV has the requested segtype +diff --git a/tests/lvm_test.py b/tests/lvm_test.py +index 12b78ca..97f6c69 100644 +--- a/tests/lvm_test.py ++++ b/tests/lvm_test.py +@@ -302,14 +302,17 @@ class LvmNoDevTestCase(LVMTestCase): + BlockDev.lvm_cache_get_mode_from_str("bla") + + class LvmPVonlyTestCase(LVMTestCase): ++ ++ _sparse_size = 1024**3 ++ + # :TODO: + # * test pvmove (must create two PVs, a VG, a VG and some data in it + # first) + # * some complex test for pvs, vgs, lvs, pvinfo, vginfo and lvinfo + def setUp(self): + self.addCleanup(self._clean_up) +- self.dev_file = create_sparse_tempfile("lvm_test", 1024**3) +- self.dev_file2 = create_sparse_tempfile("lvm_test", 1024**3) ++ self.dev_file = create_sparse_tempfile("lvm_test", self._sparse_size) ++ self.dev_file2 = create_sparse_tempfile("lvm_test", self._sparse_size) + try: + self.loop_dev = create_lio_device(self.dev_file) + except RuntimeError as e: +@@ -731,6 +734,8 @@ class LvmTestLVcreateWithExtra(LvmPVVGLVTestCase): + self.assertTrue(succ) + + class LvmTestLVcreateType(LvmPVVGLVTestCase): ++ _sparse_size = 200 * 1024**2 ++ + def test_lvcreate_type(self): + """Verify it's possible to create LVs with various types""" + +@@ -744,7 +749,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + self.assertTrue(succ) + + # try to create a striped LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "striped", [self.loop_dev, self.loop_dev2], None) ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "striped", [self.loop_dev, self.loop_dev2], None) + self.assertTrue(succ) + + # verify that the LV has the requested segtype +@@ -756,7 +761,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + + with wait_for_sync("testVG", "testLV"): + # try to create a mirrored LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "mirror", [self.loop_dev, self.loop_dev2], None) + self.assertTrue(succ) + + # verify that the LV has the requested segtype +@@ -768,7 +773,7 @@ class LvmTestLVcreateType(LvmPVVGLVTestCase): + + with wait_for_sync("testVG", "testLV"): + # try to create a raid1 LV +- succ = BlockDev.lvm_lvcreate("testVG", "testLV", 512 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) ++ succ = BlockDev.lvm_lvcreate("testVG", "testLV", 100 * 1024**2, "raid1", [self.loop_dev, self.loop_dev2], None) + self.assertTrue(succ) + + # verify that the LV has the requested segtype +-- +2.31.1 + diff --git a/SOURCES/libblockdev-gcc11.patch b/SOURCES/libblockdev-gcc11.patch new file mode 100644 index 0000000..6e5fe35 --- /dev/null +++ b/SOURCES/libblockdev-gcc11.patch @@ -0,0 +1,15 @@ +diff --git a/src/plugins/kbd.c b/src/plugins/kbd.c +index a2908ec..97abd3b 100644 +--- a/src/plugins/kbd.c ++++ b/src/plugins/kbd.c +@@ -732,6 +732,10 @@ static gboolean wait_for_file (const char *filename) { + * + * Tech category: %BD_KBD_TECH_BCACHE-%BD_KBD_TECH_MODE_CREATE + */ ++/* This triggers a known false positive warning in gcc-11. It's being ++ addressed upstream, but until the fix is available, this works around ++ the false positive. */ ++__attribute__ ((optimize ("-O1"))) + gboolean bd_kbd_bcache_create (const gchar *backing_device, const gchar *cache_device, const BDExtraArg **extra, const gchar **bcache_device, GError **error) { + const gchar *argv[6] = {"make-bcache", "-B", backing_device, "-C", cache_device, NULL}; + gboolean success = FALSE; diff --git a/SPECS/libblockdev.spec b/SPECS/libblockdev.spec new file mode 100644 index 0000000..9dd4ed4 --- /dev/null +++ b/SPECS/libblockdev.spec @@ -0,0 +1,2299 @@ +%define with_python2 1 +%define with_python3 1 +%define with_gtk_doc 1 +%define with_bcache 1 +%define with_btrfs 1 +%define with_crypto 1 +%define with_dm 1 +%define with_loop 1 +%define with_lvm 1 +%define with_lvm_dbus 1 +%define with_mdraid 1 +%define with_mpath 1 +%define with_swap 1 +%define with_kbd 1 +%define with_part 1 +%define with_fs 1 +%define with_nvdimm 1 +%define with_vdo 0 +%define with_gi 1 +%define with_escrow 1 +%define with_dmraid 1 +%define with_tools 1 + +# python2 is not available on RHEL > 7 and not needed on Fedora > 29 +%if 0%{?rhel} > 7 || 0%{?fedora} > 29 || %{with_python2} == 0 +%define with_python2 0 +%define python2_copts --without-python2 +%endif + +# python3 is not available on older RHEL +%if (! 0%{?fedora} && 0%{?rhel} <= 7) || %{with_python3} == 0 +%define with_python3 0 +%define python3_copts --without-python3 +%endif + +# bcache is not available on RHEL +%if (0%{?rhel}) || %{with_bcache} == 0 +%define with_bcache 0 +%define bcache_copts --without-bcache +%endif + +# lvm_dbus is not available on older RHEL +%if (! 0%{?fedora} && 0%{?rhel} <= 7) || %{with_lvm_dbus} == 0 +%define with_lvm_dbus 0 +%define lvm_dbus_copts --without-lvm-dbus +%endif + +# vdo is not available on non-x86_64 on older RHEL +%if (0%{?rhel} && 0%{?rhel} <= 7) +%ifnarch x86_64 +%define with_vdo 0 +%define vdo_copts --without-vdo +%endif +%endif + +# btrfs is not available on RHEL > 7 +%if 0%{?rhel} > 7 || %{with_btrfs} == 0 +%define with_btrfs 0 +%define btrfs_copts --without-btrfs +%endif + +# dmraid is not available on RHEL > 7 +%if 0%{?rhel} > 7 +%define with_dmraid 0 +%endif + +%if %{with_btrfs} != 1 +%define btrfs_copts --without-btrfs +%endif +%if %{with_crypto} != 1 +%define crypto_copts --without-crypto +%else +%if %{with_escrow} != 1 +%define crypto_copts --without-escrow +%endif +%endif +%if %{with_dm} != 1 +%define dm_copts --without-dm +%else +%if %{with_dmraid} != 1 +%define dm_copts --without-dmraid +%endif +%endif +%if %{with_loop} != 1 +%define loop_copts --without-loop +%endif +%if %{with_lvm} != 1 +%define lvm_copts --without-lvm +%endif +%if %{with_lvm_dbus} != 1 +%define lvm_dbus_copts --without-lvm_dbus +%endif +%if %{with_mdraid} != 1 +%define mdraid_copts --without-mdraid +%endif +%if %{with_mpath} != 1 +%define mpath_copts --without-mpath +%endif +%if %{with_swap} != 1 +%define swap_copts --without-swap +%endif +%if %{with_kbd} != 1 +%define kbd_copts --without-kbd +%endif +%if %{with_part} != 1 +%define part_copts --without-part +%endif +%if %{with_fs} != 1 +%define fs_copts --without-fs +%endif +%if %{with_nvdimm} != 1 +%define nvdimm_copts --without-nvdimm +%endif +%if %{with_vdo} != 1 +%define vdo_copts --without-vdo +%endif +%if %{with_tools} != 1 +%define tools_copts --without-tools +%endif +%if %{with_gi} != 1 +%define gi_copts --disable-introspection +%endif + +%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: 11%{?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 + +BuildRequires: make +BuildRequires: glib2-devel +%if %{with_gi} +BuildRequires: gobject-introspection-devel +%endif +%if %{with_python2} +BuildRequires: python2-devel +%else +# Obsolete the python2 subpackage to avoid errors on upgrade +Obsoletes: python2-blockdev < %{version}-%{release} +%endif +%if %{with_python3} +BuildRequires: python3-devel +%endif +%if %{with_gtk_doc} +BuildRequires: gtk-doc +%endif +BuildRequires: glib2-doc +BuildRequires: autoconf-archive + +# Needed for the escrow tests in tests/crypto_test.py, but not used to build +# BuildRequires: volume_key +# BuildRequires: nss-tools + +# Needed for python 2 vs. 3 compatibility in the tests, but not used to build +# BuildRequires: python2-six +# BuildRequires: python3-six + +%description +The libblockdev is a C library with GObject introspection support that can be +used for doing low-level operations with block devices like setting up LVM, +BTRFS, LUKS or MD RAID. The library uses plugins (LVM, BTRFS,...) and serves as +a thin wrapper around its plugins' functionality. All the plugins, however, can +be used as standalone libraries. One of the core principles of libblockdev is +that it is stateless from the storage configuration's perspective (e.g. it has +no information about VGs when creating an LV). + +%package devel +Summary: Development files for libblockdev +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: glib2-devel + +%description devel +This package contains header files and pkg-config files needed for development +with the libblockdev library. + +%if %{with_python2} +%package -n python2-blockdev +Summary: Python2 gobject-introspection bindings for libblockdev +Requires: %{name}%{?_isa} = %{version}-%{release} + +%if 0%{?fedora} <= 26 || 0%{?rhel} <= 7 +Requires: pygobject3-base +%else +Requires: python2-gobject-base +%endif +%{?python_provide:%python_provide python2-blockdev} + +%description -n python2-blockdev +This package contains enhancements to the gobject-introspection bindings for +libblockdev in Python2. +%endif + +%if %{with_python3} +%package -n python3-blockdev +Summary: Python3 gobject-introspection bindings for libblockdev +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: python3-gobject-base +%{?python_provide:%python_provide python3-blockdev} + +%description -n python3-blockdev +This package contains enhancements to the gobject-introspection bindings for +libblockdev in Python3. +%endif + +%package utils +BuildRequires: kmod-devel +Summary: A library with utility functions for the libblockdev library + +%description utils +The libblockdev-utils is a library providing utility functions used by the +libblockdev library and its plugins. + +%package utils-devel +Summary: Development files for libblockdev-utils +Requires: %{name}-utils%{?_isa} = %{version}-%{release} +Requires: glib2-devel + +%description utils-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-utils library. + + +%if %{with_btrfs} +%package btrfs +BuildRequires: libbytesize-devel +Summary: The BTRFS plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: btrfs-progs + +%description btrfs +The libblockdev library plugin (and in the same time a standalone library) +providing the BTRFS-related functionality. + +%package btrfs-devel +Summary: Development files for the libblockdev-btrfs plugin/library +Requires: %{name}-btrfs%{?_isa} = %{version}-%{release} +Requires: glib2-devel +Requires: %{name}-utils-devel%{?_isa} + +%description btrfs-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-btrfs plugin/library. +%endif + + +%if %{with_crypto} +%package crypto +BuildRequires: cryptsetup-devel +BuildRequires: libblkid-devel + +%if %{with_escrow} +BuildRequires: volume_key-devel >= 0.3.9-7 +BuildRequires: nss-devel +%endif + +Summary: The crypto plugin for the libblockdev library + +%description crypto +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description crypto-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-crypto plugin/library. +%endif + + +%if %{with_dm} +%package dm +BuildRequires: device-mapper-devel +%if %{with_dmraid} +BuildRequires: dmraid-devel +%endif +BuildRequires: systemd-devel +Summary: The Device Mapper plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: device-mapper +%if %{with_dmraid} +Requires: dmraid +%endif + +%description dm +The libblockdev library plugin (and in the same time a standalone library) +providing the functionality related to Device Mapper. + +%package dm-devel +Summary: Development files for the libblockdev-dm plugin/library +Requires: %{name}-dm%{?_isa} = %{version}-%{release} +Requires: glib2-devel +Requires: device-mapper-devel +Requires: systemd-devel +%if %{with_dmraid} +Requires: dmraid-devel +%endif +Requires: %{name}-utils-devel%{?_isa} + +%description dm-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-dm plugin/library. +%endif + + +%if %{with_fs} +%package fs +BuildRequires: parted-devel +BuildRequires: libblkid-devel +BuildRequires: libmount-devel +Summary: The FS plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 + +%description fs +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel +Requires: xfsprogs +Requires: dosfstools + +%description fs-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-fs plugin/library. +%endif + + +%if %{with_kbd} +%package kbd +BuildRequires: libbytesize-devel +Summary: The KBD plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 +%if %{with_bcache} +Requires: bcache-tools >= 1.0.8 +%endif + +%description kbd +The libblockdev library plugin (and in the same time a standalone library) +providing the functionality related to kernel block devices (namely zRAM and +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: glib2-devel + +%description kbd-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-kbd plugin/library. +%endif + + +%if %{with_loop} +%package loop +Summary: The loop plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 + +%description loop +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description loop-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-loop plugin/library. +%endif + + +%if %{with_lvm} +%package lvm +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) +providing the LVM-related functionality. + +%package lvm-devel +Summary: Development files for the libblockdev-lvm plugin/library +Requires: %{name}-lvm%{?_isa} = %{version}-%{release} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} +Requires: glib2-devel + +%description lvm-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-lvm plugin/library. +%endif + +%if %{with_lvm_dbus} +%package lvm-dbus +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) +providing the LVM-related functionality utilizing the LVM DBus API. + +%package lvm-dbus-devel +Summary: Development files for the libblockdev-lvm-dbus plugin/library +Requires: %{name}-lvm-dbus%{?_isa} = %{version}-%{release} +Requires: %{name}-utils-devel%{?_isa} = %{version}-%{release} +Requires: glib2-devel + +%description lvm-dbus-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-lvm-dbus plugin/library. +%endif + + +%if %{with_mdraid} +%package mdraid +BuildRequires: libbytesize-devel +Summary: The MD RAID plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: mdadm + +%description mdraid +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description mdraid-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-mdraid plugin/library. +%endif + + +%if %{with_mpath} +%package mpath +BuildRequires: device-mapper-devel +Summary: The multipath plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 +Recommends: device-mapper-multipath + +%description mpath +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description mpath-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-mpath plugin/library. +%endif + +%if %{with_nvdimm} +%package nvdimm +BuildRequires: ndctl-devel +BuildRequires: libuuid-devel +Summary: The NVDIMM plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: ndctl + +%description nvdimm +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description nvdimm-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-nvdimm plugin/library. +%endif + + +%if %{with_part} +%package part +BuildRequires: parted-devel +Summary: The partitioning plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: gdisk +Requires: util-linux + +%description part +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description part-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-part plugin/library. +%endif + + +%if %{with_swap} +%package swap +BuildRequires: libblkid-devel +Summary: The swap plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 +Requires: util-linux + +%description swap +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description swap-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-swap plugin/library. +%endif + + +%if %{with_vdo} +%package vdo +BuildRequires: libbytesize-devel +BuildRequires: libyaml-devel +Summary: The vdo plugin for the libblockdev library +Requires: %{name}-utils%{?_isa} >= 0.11 + +# weak dependencies doesn't work on older RHEL +%if (0%{?rhel} && 0%{?rhel} <= 7) +Requires: vdo +Requires: kmod-kvdo +%else +# we want to build the plugin everywhere but the dependencies might not be +# available so just use weak dependency +Recommends: vdo +Recommends: kmod-kvdo +%endif + +%description vdo +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description vdo-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-vdo plugin/library. +%endif + +%if %{with_tools} +%package tools +Summary: Various nice tools based on libblockdev +Requires: %{name} +Requires: %{name}-lvm +BuildRequires: libbytesize-devel +%if %{with_lvm_dbus} == 1 +Recommends: %{name}-lvm-dbus +%endif + +%description tools +Various nice storage-related tools based on libblockdev. + +%endif + +%ifarch s390 s390x +%package s390 +Summary: The s390 plugin for the libblockdev library +Requires: s390utils + +%description s390 +The libblockdev library plugin (and in the same time a standalone library) +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: glib2-devel + +%description s390-devel +This package contains header files and pkg-config files needed for development +with the libblockdev-s390 plugin/library. +%endif + +%package plugins-all +Summary: Meta-package that pulls all the libblockdev plugins as dependencies +Requires: %{name}%{?_isa} = %{version}-%{release} + +%if %{with_btrfs} +Requires: %{name}-btrfs%{?_isa} = %{version}-%{release} +%endif + +%if %{with_crypto} +Requires: %{name}-crypto%{?_isa} = %{version}-%{release} +%endif + +%if %{with_dm} +Requires: %{name}-dm%{?_isa} = %{version}-%{release} +%endif + +%if %{with_fs} +Requires: %{name}-fs%{?_isa} = %{version}-%{release} +%endif + +%if %{with_kbd} +Requires: %{name}-kbd%{?_isa} = %{version}-%{release} +%endif + +%if %{with_loop} +Requires: %{name}-loop%{?_isa} = %{version}-%{release} +%endif + +%if %{with_lvm} +Requires: %{name}-lvm%{?_isa} = %{version}-%{release} +%endif + +%if %{with_mdraid} +Requires: %{name}-mdraid%{?_isa} = %{version}-%{release} +%endif + +%if %{with_mpath} +Requires: %{name}-mpath%{?_isa} = %{version}-%{release} +%endif + +%if %{with_nvdimm} +Requires: %{name}-nvdimm%{?_isa} = %{version}-%{release} +%endif + +%if %{with_part} +Requires: %{name}-part%{?_isa} = %{version}-%{release} +%endif + +%if %{with_swap} +Requires: %{name}-swap%{?_isa} = %{version}-%{release} +%endif + +%if %{with_vdo} +Requires: %{name}-vdo%{?_isa} = %{version}-%{release} +%endif + +%ifarch s390 s390x +Requires: %{name}-s390%{?_isa} = %{version}-%{release} +%endif + +%description plugins-all +A meta-package that pulls all the libblockdev plugins as dependencies. + + +%prep +%setup -q -n %{name}-%{version} +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 + +%build +autoreconf -ivf +%configure %{?configure_opts} +%{__make} %{?_smp_mflags} + +%install +%{make_install} +find %{buildroot} -type f -name "*.la" | xargs %{__rm} + + +%ldconfig_scriptlets +%ldconfig_scriptlets utils + +%if %{with_btrfs} +%ldconfig_scriptlets btrfs +%endif + +%if %{with_crypto} +%ldconfig_scriptlets crypto +%endif + +%if %{with_dm} +%ldconfig_scriptlets dm +%endif + +%if %{with_fs} +%ldconfig_scriptlets fs +%endif + +%if %{with_loop} +%ldconfig_scriptlets loop +%endif + +%if %{with_lvm} +%ldconfig_scriptlets lvm +%endif + +%if %{with_lvm_dbus} +%ldconfig_scriptlets lvm-dbus +%endif + +%if %{with_mdraid} +%ldconfig_scriptlets mdraid +%endif + +%if %{with_mpath} +%ldconfig_scriptlets mpath +%endif + +%if %{with_nvdimm} +%ldconfig_scriptlets nvdimm +%endif + +%if %{with_part} +%ldconfig_scriptlets part +%endif + +%if %{with_swap} +%ldconfig_scriptlets swap +%endif + +%if %{with_vdo} +%ldconfig_scriptlets vdo +%endif + +%ifarch s390 s390x +%ldconfig_scriptlets s390 +%endif + +%if %{with_kbd} +%ldconfig_scriptlets kbd +%endif + + +%files +%{!?_licensedir:%global license %%doc} +%license LICENSE +%{_libdir}/libblockdev.so.* +%if %{with_gi} +%{_libdir}/girepository*/BlockDev*.typelib +%endif +%dir %{_sysconfdir}/libblockdev +%dir %{_sysconfdir}/libblockdev/conf.d +%config %{_sysconfdir}/libblockdev/conf.d/00-default.cfg + +%files devel +%doc features.rst specs.rst +%{_libdir}/libblockdev.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/blockdev.h +%{_includedir}/blockdev/plugins.h +%{_libdir}/pkgconfig/blockdev.pc +%if %{with_gtk_doc} +%{_datadir}/gtk-doc/html/libblockdev +%endif +%if %{with_gi} +%{_datadir}/gir*/BlockDev*.gir +%endif + +%if %{with_python2} +%files -n python2-blockdev +%{python2_sitearch}/gi/overrides/* +%endif + +%if %{with_python3} +%files -n python3-blockdev +%{python3_sitearch}/gi/overrides/BlockDev* +%{python3_sitearch}/gi/overrides/__pycache__/BlockDev* +%endif + +%files utils +%{_libdir}/libbd_utils.so.* +%{_libdir}/libbd_part_err.so.* + +%files utils-devel +%{_libdir}/libbd_utils.so +%{_libdir}/libbd_part_err.so +%{_libdir}/pkgconfig/blockdev-utils.pc +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/utils.h +%{_includedir}/blockdev/sizes.h +%{_includedir}/blockdev/exec.h +%{_includedir}/blockdev/extra_arg.h +%{_includedir}/blockdev/dev_utils.h +%{_includedir}/blockdev/module.h +%{_includedir}/blockdev/dbus.h + + +%if %{with_btrfs} +%files btrfs +%{_libdir}/libbd_btrfs.so.* + +%files btrfs-devel +%{_libdir}/libbd_btrfs.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/btrfs.h +%endif + + +%if %{with_crypto} +%files crypto +%{_libdir}/libbd_crypto.so.* + +%files crypto-devel +%{_libdir}/libbd_crypto.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/crypto.h +%endif + + +%if %{with_dm} +%files dm +%{_libdir}/libbd_dm.so.* + +%files dm-devel +%{_libdir}/libbd_dm.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/dm.h +%endif + + +%if %{with_fs} +%files fs +%{_libdir}/libbd_fs.so.* + +%files fs-devel +%{_libdir}/libbd_fs.so +%dir %{_includedir}/blockdev +%dir %{_includedir}/blockdev/fs +%{_includedir}/blockdev/fs.h +%{_includedir}/blockdev/fs/*.h +%endif + + +%if %{with_kbd} +%files kbd +%{_libdir}/libbd_kbd.so.* + +%files kbd-devel +%{_libdir}/libbd_kbd.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/kbd.h +%endif + + +%if %{with_loop} +%files loop +%{_libdir}/libbd_loop.so.* + +%files loop-devel +%{_libdir}/libbd_loop.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/loop.h +%endif + + +%if %{with_lvm} +%files lvm +%{_libdir}/libbd_lvm.so.* + +%files lvm-devel +%{_libdir}/libbd_lvm.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/lvm.h +%endif + + +%if %{with_lvm_dbus} +%files lvm-dbus +%{_libdir}/libbd_lvm-dbus.so.* +%config %{_sysconfdir}/libblockdev/conf.d/10-lvm-dbus.cfg + +%files lvm-dbus-devel +%{_libdir}/libbd_lvm-dbus.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/lvm.h +%endif + + +%if %{with_mdraid} +%files mdraid +%{_libdir}/libbd_mdraid.so.* + +%files mdraid-devel +%{_libdir}/libbd_mdraid.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/mdraid.h +%endif + + +%if %{with_mpath} +%files mpath +%{_libdir}/libbd_mpath.so.* + +%files mpath-devel +%{_libdir}/libbd_mpath.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/mpath.h +%endif + + +%if %{with_nvdimm} +%files nvdimm +%{_libdir}/libbd_nvdimm.so.* + +%files nvdimm-devel +%{_libdir}/libbd_nvdimm.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/nvdimm.h +%endif + + +%if %{with_part} +%files part +%{_libdir}/libbd_part.so.* + +%files part-devel +%{_libdir}/libbd_part.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/part.h +%endif + + +%if %{with_swap} +%files swap +%{_libdir}/libbd_swap.so.* + +%files swap-devel +%{_libdir}/libbd_swap.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/swap.h +%endif + + +%if %{with_vdo} +%files vdo +%{_libdir}/libbd_vdo.so.* + +%files vdo-devel +%{_libdir}/libbd_vdo.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/vdo.h +%endif + +%if %{with_tools} +%files tools +%{_bindir}/lvm-cache-stats +%endif + +%ifarch s390 s390x +%files s390 +%{_libdir}/libbd_s390.so.* + +%files s390-devel +%{_libdir}/libbd_s390.so +%dir %{_includedir}/blockdev +%{_includedir}/blockdev/s390.h +%endif + +%files plugins-all + +%changelog +* Mon Jan 10 2022 Vojtech Trefny - 2.25-11 +- tests: Wait for raid and mirrored LVs to be synced before removing + Resolves: rhbz#2030647 +- spec: Require the same version of utils for lvm-devel and lvm-dbus-devel + Resolves: rhbz#2028113 + +* Wed Dec 08 2021 Vojtech Trefny - 2.25-10 +- Fix reading statistics for VDO pools with VDO 8 + Resolves: rhbz#1994220 +- vdo_stats: Default to 100 % savings for invalid savings values + Resolves: rhbz#2025880 +- Add support for creating and unlocking standalone integrity devices + Resolves: rhbz#2011365 + +* Tue Nov 30 2021 Vojtech Trefny - 2.25-9 +- Fix patch for 'Add support LVM devices file management' + Resolves: rhbz#1983705 + +* Tue Nov 30 2021 Vojtech Trefny - 2.25-8 +- Add support LVM devices file management + Resolves: rhbz#1983705 + +* Mon Aug 09 2021 Mohan Boddu - 2.25-7 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Tue Jun 29 2021 Vojtech Trefny - 2.25-6 +- Add workarounds for some LVM test issues + Resolves: rhbz#1976174 +- Adapt tests to xfsprogs 5.12 changes + Resolves: rhbz#1976176 + +* Tue May 18 2021 Vojtech Trefny - 2.25-5 +- Adapt to dosfstools 4.2 changes + Resolves: rhbz#1960624 + +* Thu May 13 2021 Vojtech Trefny - 2.25-4 +- Memory leaks fixes backport + Resolves: rhbz#1938757 +- Fix default key size for non XTS ciphers + Resolves: rhbz#1954005 + +* Fri Apr 16 2021 Mohan Boddu - 2.25-3 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Tue Jan 26 2021 Fedora Release Engineering - 2.25-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Mon Jan 11 2021 Vojtech Trefny - 2.25-1 +- loop: Retry LOOP_SET_STATUS64 on EAGAIN (vtrefny) +- Fix max size limit for LVM thinpool metadata (vtrefny) +- lvm: Use the UNUSED macro instead of __attribute__((unused)) (vtrefny) +- lvm: Do not use thin_metadata_size to recommend thin metadata size (vtrefny) +- lvm: Set thin metadata limits to match limits LVM uses in lvcreate (vtrefny) +- Mark all GIR file constants as guint64 (vtrefny) +- lvm: Fix bd_lvm_vdopooldata_* symbols (tbzatek) +- fs: Fix compile error in ext_repair caused by cherry pick from master (vtrefny) +- README: Use CI status image for 2.x-branch on 2.x (vtrefny) +- fs: Do not report error when errors were fixed by e2fsck (vtrefny) +- tests: Add null-byte exec tests (tbzatek) +- tests: Add bufferbloat exec tests (tbzatek) +- exec: Clarify the BDUtilsProgExtract callback documentation (tbzatek) +- exec: Use non-blocking read and process the buffer manually (tbzatek) +- exec: Fix polling for stdout and stderr (tbzatek) +- exec: Fix setting locale for util calls (vtrefny) + +* Thu Oct 01 2020 Vojtech Trefny - 2.24-7 +- Do not build VDO plugin + +* Thu Sep 17 2020 Vojtech Trefny - 2.24-6 +- exec: Fix setting locale for util calls + +* Thu Aug 20 2020 Vojtech Trefny - 2.24-5 +- dm: Fix comparing DM RAID member devices UUID + +* Wed Aug 19 2020 Jeff Law - 2.24-4 +- Work around gcc-11 false positive warning + +* Mon Jul 27 2020 Hans de Goede - 2.24-3 +- Change -mpath subpackage Requires: device-mapper-multipath into Recommends +- Related: rhbz#1857393 + +* Sat May 23 2020 Miro Hrončok - 2.24-2 +- Rebuilt for Python 3.9 + +* Fri May 22 2020 Vojtech Trefny - 2.24-1 +- Mark VDO plugin as deprecated since 2.24 (vtrefny) +- Fix multiple uninitialized values discovered by coverity (vtrefny) +- fs: Fix potential NULL pointer dereference in mount.c (vtrefny) +- utils: Remove deadcode in exec.c (vtrefny) +- Do not check VDO saving percent value in LVM DBus tests (vtrefny) +- Use libblkid to get label and UUID for XFS filesystems (vtrefny) +- Do not open devices as read-write for read-only fs operations (vtrefny) +- Create a common function to get label and uuid of a filesystem (vtrefny) +- lvm: Fix getting cache stats for cache thinpools (vtrefny) +- Do not skip LVM VDO tests when the kvdo module is already loaded (vtrefny) +- tests: Skip LVM VDO tests if kvdo module cannot be loaded (vtrefny) +- lvm-dbus: Add LVM VDO pools to bd_lvm_lvs (vtrefny) +- lvm: Add a function to get VDO pool name for a VDO LV (vtrefny) +- lvm-dbus: Get data LV name for LVM VDO pools too (vtrefny) +- Add functions to get VDO stats for LVM VDO volumes (vtrefny) +- Move VDO statistics code to a separate file (vtrefny) +- Fix copy-paste bug in lvm.api (vtrefny) +- exec: Disable encoding when reading data from stdout/stderr (vtrefny) +- Add function to get LVM VDO write policy from a string (vtrefny) +- Add extra parameters for creating LVM VDO volumes (vtrefny) +- Allow calling LVM functions without locking global_config_lock (vtrefny) +- Fix getting VDO data in the LVM DBus plugin (vtrefny) +- Fix getting string representation of unknown VDO state index (vtrefny) +- Add write policy and index size to LVM VDO data (vtrefny) +- Fix converting to VDO pool without name for the VDO LV (vtrefny) +- Add some helper functions to get LVM VDO mode and state strings (vtrefny) +- Add support for creating and managing VDO LVs with LVM (vtrefny) +- Fix LVM plugin so names in tests (vtrefny) +- Do not hardcode pylint executable name in Makefile (vtrefny) +- Add a function to check if a tool supports given feature (vtrefny) +- configure.ac: Avoid more bashisms (gentoo) +- mount: Fix a memleak (tbzatek) +- exec: Fix a memleak (tbzatek) +- vdo: Fix a memleak (tbzatek) +- configure.ac: Avoid bashisms (polynomial-c) +- tests: Specify loader for yaml.load in VDO tests (vtrefny) +- lvm-dbus: Fix memory leak in bd_lvm_thlvpoolname (vtrefny) +- lvm-dbus: Do not activate LVs during pvscan --cache (vtrefny) +- vdo: Run "vdo create" with "--force" (vtrefny) +- Fix typo in (un)mount error messages (vtrefny) +- utils: Add functions to get and check current linux kernel version (tbzatek) +- ext: Return empty string instead of "" for empty UUID (vtrefny) +- Add support for BitLocker encrypted devices using cryptsetup (vtrefny) +- Add a helper function for closing an active crypto device (vtrefny) +- Manually remove symlinks not removed by udev in tests (vtrefny) +- Fix memory leak in LVM DBus plugin (vtrefny) +- Fix expected cache pool name with newest LVM (vtrefny) +- fs: Fix checking for UID/GID == 0 (vtrefny) +- Fixed a number of memory leaks in lvm-dbus plugin (mthompson) +- exec.c: Fix reading outputs with null bytes (vtrefny) +- Fix linking against utils on Debian (vtrefny) +- Add new function 'bd_fs_wipe_force' to control force wipe (vtrefny) +- Use 'explicit_bzero' to erase passphrases from key files (vtrefny) +- Sync spec with downstream (vtrefny) + +* Wed Jan 29 2020 Fedora Release Engineering - 2.23-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Mon Sep 09 2019 Vojtech Trefny - 2.23-1 +- Fix how we get process exit code from g_spawn_sync (vtrefny) +- Skip tests for old-style LVM snapshots on recent Fedora (vtrefny) +- Fix skipping NTFS read-only test case on systems without NTFS (vtrefny) +- Fix LVM_MAX_LV_SIZE in the GIR file (vtrefny) +- Print skipped test "results" to stderr instead of stdout (vtrefny) +- Move the NTFS read-only device test to a separate test case (vtrefny) +- Fix parsing distro version from CPE name (vtrefny) +- Use 'kmod_module_probe_insert_module' function for loading modules (vtrefny) +- Hide filesystem-specific is_tech_available functions (vtrefny) +- Mark LVM global config locks as static (vtrefny) +- Remove unused 'get_PLUGIN_num_functions' and 'get_PLUGIN_functions' functions (vtrefny) +- Mark 'private' plugin management functions as static (vtrefny) +- Ignore coverity deadcode warning in 'bd_fs_is_tech_avail' (vtrefny) +- Ignore coverity deadcode warnings in the generated code (vtrefny) +- Use the new config file for skipping tests (vtrefny) +- Skip bcache tests if make-bcache is not installed (vtrefny) +- Add ability to read tests to skip from a config file (vtrefny) +- Mark 'test_set_bitmap_location' as unstable (vtrefny) +- Force LVM cli plugin in lvm_test (vtrefny) +- Add a special test tag for library tests that recompile plugins (vtrefny) +- Allow running tests against installed libblockdev (vtrefny) +- Remove duplicate test case (vtrefny) +- Use the new test tags in tests (vtrefny) +- Use test tags for skipping tests (vtrefny) +- Add a decorator for "tagging" tests (vtrefny) +- Add function for (un)freezing filesystems (vtrefny) +- Add a function to check whether a path is a mounpoint or not (vtrefny) +- Skip bcache tests on all Debian versions (vtrefny) + +* Fri Aug 16 2019 Miro Hrončok - 2.22-3 +- Rebuilt for Python 3.8 + +* Thu Jul 25 2019 Fedora Release Engineering - 2.22-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Wed Jun 12 2019 Vojtech Trefny - 2.22-1 +- tests: Fix Debian testing "version" for skipping (vtrefny) +- module: Fix libkmod related leak (tbzatek) +- btrfs: Fix number of memory leaks (tbzatek) +- mdraid: Fix leaking BDMDExamineData.metadata (tbzatek) +- mdraid: Fix leaking error (tbzatek) +- part: Fix leaking string in args (tbzatek) +- ext: Fix leaking string (tbzatek) +- part: Fix leaking objects (tbzatek) +- kbd: Fix g_match_info_fetch() leaks (tbzatek) +- ext: Fix g_match_info_fetch() leaks (tbzatek) +- ext: Fix g_strsplit() leaks (tbzatek) +- s390: Fix g_strsplit() leaks (tbzatek) +- mdraid: Fix g_strsplit() leaks (tbzatek) +- exec: Fix some memory leaks (tbzatek) +- lvm: Fix leaking BDLVMPVdata.vg_uuid (tbzatek) +- lvm: Use g_ptr_array_free() for creating lists (tbzatek) +- lvm: Fix some obvious memory leaks (tbzatek) +- Remove device-mapper-multipath dependency from fs and part plugins (vtrefny) +- bd_fs_xfs_get_info: Allow passing error == NULL (tbzatek) +- tests: Fix removing targetcli lun (vtrefny) +- Use existing cryptsetup API for changing keyslot passphrase (vtrefny) +- New function to get supported sector sizes for NVDIMM namespaces (vtrefny) +- Allow skiping tests only based on architecture (vtrefny) +- Sync spec file with python2 obsoletion added downstream (awilliam) +- Sync spec with downstream (vtrefny) + +* Tue Apr 16 2019 Vojtech Trefny - 2.21-3 +- Remove device-mapper-multipath dependency from fs and part plugins + +* Thu Feb 28 2019 Adam Williamson - 2.21-2 +- Obsolete the python2 subpackage if we're not building it + +* Thu Feb 21 2019 Vojtech Trefny - 2.21-1 +- Fix checking swap status on lvm/md (vtrefny) +- tests: Stop skipping some tests on Debian testing (vtrefny) +- tests: Remove some old/irrelevant skips (vtrefny) +- Use 512bit keys in LUKS by default (vratislav.podzimek) +- Add 'autoconf-archive' to build requires (vtrefny) +- vagrant: remove F27 and add F29 (vtrefny) +- vagrant: install 'autoconf-archive' on Ubuntu (vtrefny) +- Enable cryptsetup debug messages when compiled using --enable-debug (vtrefny) +- lvm-dbus: Do not pass extra arguments enclosed in a tuple (vtrefny) +- crypto: Do not try to use keyring on systems without keyring support (vtrefny) +- Fix LUKS2 resize password test (vtrefny) +- Use cryptsetup to check LUKS2 label (vtrefny) +- Skip LUKS2+integrity test on systems without dm-integrity module (vtrefny) +- Add custom error message for wrong passphrase for open (vtrefny) +- Use major/minor macros from sys/sysmacros.h instead of linux/kdev_t.h (vtrefny) +- crypto_test.py: Use blkid instead of lsblk to check luks label (vtrefny) +- Skip VDO grow physical test (vtrefny) +- Add libblkid-devel as a build dependency for the swap plugin (vtrefny) +- Add error codes and Python exceptions for swapon fails (vtrefny) +- Use libblkid to check swap status before swapon (vtrefny) +- Add a new subpackage with the tool(s) (v.podzimek) +- Document what the 'tools' directory contains (v.podzimek) +- Make building tools optional (v.podzimek) +- Add a tool for getting cached LVM statistics (v.podzimek) +- Discard messages from libdevmapper in the LVM plugins (v.podzimek) + +* Fri Feb 01 2019 Fedora Release Engineering - 2.20-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Oct 08 2018 Vojtech Trefny - 2.20-2 +- Use libblkid to check swap status before swapon (vtrefny) +- Add error codes and Python exceptions for swapon fails (vtrefny) + +* Wed Sep 26 2018 Vojtech Trefny - 2.20-1 +- Use unsafe caching for storage for devel/testing VMs (v.podzimek) +- Require newer version of cryptsetup for LUKS2 tests (vtrefny) +- Skip nvdimm tests on systems without ndctl (vtrefny) +- Add Ubuntu 18.04 VM configuration to the vagrant template (vtrefny) +- Add some missing test dependencies to the vagrant template (vtrefny) +- Fix how/where the bcache tests are skipped (v.podzimek) +- Document what the 'misc' directory contains (v.podzimek) +- Add a Vagrantfile template (v.podzimek) +- Fix the error message when deleting partition fails (vpodzime) +- Fix build of plugins by changing linking order (devurandom) +- Fix how we check zram stats from /sys/block/zram0/stat (vtrefny) +- lvm-dbus: Fix parsing extra arguments for LVM methods calls (vtrefny) +- Skip MDTestAddRemove on Debian (vtrefny) +- Skip NTFS mount test on Debian testing (vtrefny) +- Skip bcache tests on Debian testing (vtrefny) +- tests: Try harder to get distribution version (vtrefny) +- Mark the function stubs as static (v.podzimek) +- Build the dm plugin without dmraid support on newer RHEL (vtrefny) +- Fix skipping zram tests on Fedora 27 (vtrefny) +- kbd: Check for zram module availability in 'bd_kbd_is_tech_avail' (vtrefny) +- Always build the VDO plugin (vtrefny) +- Do not require 'dmraid' package if built without dmraid support (vtrefny) +- Fix licence header in dbus.c (vtrefny) +- Fix spacing in NEWS.rst (vtrefny) + +* Fri Aug 10 2018 Vojtech Trefny - 2.19-1 +- Use python interpreter explicitly when running boilerplate_generator.py (vtrefny) +- vdo: Implement bd_vdo_get_stats() (tbzatek) +- Add test for is_tech_available with multiple dependencies (vtrefny) +- lvm-dbus.c: Check for 'lvmdbus' dependency in 'bd_lvm_is_tech_avail' (vtrefny) +- lvm.c: Check for 'lvm' dependency in 'bd_lvm_is_tech_avail' (vtrefny) +- Fix licence headers in sources (vtrefny) +- Fix three memory leaks in lvm-dbus.c (vtrefny) +- Ignore "bad-super-call" pylint warning in BlockDev.py (vtrefny) +- Fix running pylint in tests (vtrefny) +- Fix vdo configuration options definition in spec file (vtrefny) +- Fix calling BlockDev.reinit in swap tests (vtrefny) +- Fix how we check zram stats from /sys/block/zram0/mm_stat (vtrefny) +- Skip VDO tests also when the 'kvdo' module is not available (vtrefny) +- Add version to tests that should be skipped on CentOS/RHEL 7 (vtrefny) +- Skip btrfs tests if btrfs module is not available (vtrefny) +- Do not build KBD plugin with bcache support on RHEL (vtrefny) +- Do not build btrfs plugin on newer RHEL (vtrefny) +- fs: Properly close both ends of the pipe (tbzatek) +- Make sure library_test works after fixing -Wstrict-prototypes (vtrefny) +- Make sure library tests properly clean after themselves (vtrefny) +- pkg-config: add -L${libdir} and -I${includedir} (max.kellermann) +- plugins/kbd: make wait_for_file() static (max.kellermann) +- plugins/lvm{,-dbus}: get_lv_type_from_flags() returns const string (max.kellermann) +- plugins/dm: add explicit cast to work around -Wdiscarded-qualifiers (max.kellermann) +- plugins/crypto: work around -Wdiscarded-qualifiers (max.kellermann) +- plugins/check_deps: make all strings and `UtilDep` instances `const` (max.kellermann) +- exec: make `msg` parameters const (max.kellermann) +- fix -Wstrict-prototypes (max.kellermann) +- module.c: Accept kernel modules if they are built-in (marco.guerri.dev) +- BlockDev.py Convert dictionary keys to set before using them (vtrefny) +- Skip 'test_cache_pool_create_remove' on CentOS 7 (vtrefny) +- Re-order libbd_crypto_la_LIBADD to fix libtool issue (tom) +- acinclude.m4: Use AS_EXIT to fail in LIBBLOCKDEV_FAILURES (vtrefny) +- configure.ac: Fix missing parenthesis in blkid version check (vtrefny) +- Allow specifying extra options for PBKDF when creating LUKS2 (vtrefny) +- Reintroduce python2 support for Fedora 29 (vtrefny) +- Use versioned command for Python 2 (vtrefny) +- Fix few wrong names in doc strings (vtrefny) +- Make sure all our free and copy functions work with NULL (vtrefny) +- Use libblkid in bd_crypto_is_luks (vtrefny) +- vdo: Properly destroy the yaml parser (tbzatek) +- Add a simple test case for bd_crypto_tc_open (vtrefny) +- Add Python override for bd_crypto_tc_open_full (vtrefny) +- Show simple summary after configure (vtrefny) +- Do not build VDO plugin on non-x86_64 architectures (vtrefny) +- Sync spec with downstream (vtrefny) + +* Fri Jul 13 2018 Fedora Release Engineering - 2.18-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Mon Jul 09 2018 Vojtech Trefny - 2.18-3 +- Reitroduce python2 support for Fedora 29 + +* Mon Jul 02 2018 Miro Hrončok - 2.18-2 +- Rebuilt for Python 3.7 + +* Wed Jun 20 2018 Vojtech Trefny - 2.18-1 +- Add VDO to features.rst (vtrefny) +- Remove roadmap.rst (vtrefny) +- vdo: Add tests for bd_vdo_grow_physical() (tbzatek) +- Do not try to build VDO plugin on Fedora (vtrefny) +- Introduce reporting function per thread (kailueke) +- vdo: Implement bd_vdo_grow_physical() (tbzatek) +- Correct arguments for ext4 repair with progress (kailueke) +- Clarify that checking an RW-mounted XFS file system is impossible (v.podzimek) +- vdo: Resolve real device file path (tbzatek) +- Adjust to new NVDIMM namespace modes (vtrefny) +- Use xfs_repair instead of xfs_db in bd_fs_xfs_check() (v.podzimek) +- Allow compiling libblockdev without libdmraid (vtrefny) +- Only require plugins we really need in LVM dbus tests (vtrefny) +- Add tests for VDO plugin (vtrefny) +- Add decimal units definition to utils/sizes.h (vtrefny) +- Add basic VDO plugin functionality (vtrefny) +- Add the VDO plugin (vtrefny) +- Always check for error when (un)mounting (vtrefny) +- Fix off-by-one error when counting TCRYPT keyfiles (segfault) +- Add 'bd_dm_is_tech_avail' to header file (vtrefny) +- Fix release number in NEWS.rst (vtrefny) +- Update specs.rst and features.rst (vtrefny) + +* Fri Jun 15 2018 Miro Hrončok - 2.17-2 +- Rebuilt for Python 3.7 + +* Tue Apr 24 2018 Vojtech Trefny - 2.17-1 +- Redirect cryptsetup log to libblockdev log (vtrefny) +- Add a generic logging function for libblockdev (vtrefny) +- Add functions to resize LUKS 2 (vtrefny) +- Add function to get information about LUKS 2 integrity devices (vtrefny) +- Add function to get information about a LUKS device (vtrefny) +- Add a basic test for creating LUKS 2 format (vtrefny) +- Use libblockdev function to create LUKS 2 in tests (vtrefny) +- Add support for creating LUKS 2 format (vtrefny) +- Skip bcache tests on Rawhide (vtrefny) +- Allow building libblockdev without Python 2 support (vtrefny) +- Allow compiling libblockdev crypto plugin without escrow support (vtrefny) +- Require at least libndctl 58.4 (vtrefny) +- New function for luks metadata size (japokorn) +- Add functions to backup and restore LUKS header (vtrefny) +- Add function for killing keyslot on a LUKS device (vtrefny) +- Add functions to suspend and resume a LUKS device (vtrefny) +- Use '=' instead of '==' to compare using 'test' (v.podzimek) +- lvm-dbus: Check returned job object for error (vtrefny) +- Get sector size for non-block NVDIMM namespaces too (vtrefny) +- Fix memory leaks discovered by clang (vtrefny) +- Add new functions to docs/libblockdev-sections.txt (segfault) +- Make a link point to the relevant section (segfault) +- Don't use VeraCrypt PIM if compiled against libcryptsetup < 2.0 (segfault) +- Make keyfiles parameter to bd_crypto_tc_open_full zero terminated (segfault) +- Add function bd_crypto_device_seems_encrypted (segfault) +- Support VeraCrypt PIM (segfault) +- Support TCRYPT system volumes (segfault) +- Support TCRYPT hidden containers (segfault) +- Support TCRYPT keyfiles (segfault) +- Support unlocking VeraCrypt volumes (segfault) +- Enforce ZERO_INIT gcc backwards compatibility (bjornpagen) +- Add function for getting NVDIMM namespace name from devname or path (vtrefny) +- Add --without-xyz to DISTCHECK_CONFIGURE_FLAGS for disabled plugins (vtrefny) +- Add tests for the NVDIMM plugin (vtrefny) +- Add the NVDIMM plugin (vtrefny) +- Fix build with clang (bjornpagen) +- s390: don't hardcode paths, search PATH (flokli) +- Fix build against musl libc (bjornpagen) +- Fix python2-gobject-base dependency on Fedora 26 and older (vtrefny) +- Sync the spec file with downstream (vtrefny) + +* Wed Apr 11 2018 Vojtech Trefny - 2.16-3 +- Add the NVDIMM plugin (vtrefny) +- Add tests for the NVDIMM plugin (vtrefny) +- Add --without-xyz to DISTCHECK_CONFIGURE_FLAGS for disabled plugins (vtrefny) +- Add function for getting NVDIMM namespace name from devname or path (vtrefny) + +* Fri Feb 09 2018 Igor Gnatenko - 2.16-2 +- Escape macros in %%changelog + +* Thu Feb 08 2018 Vojtech Trefny - 2.16-1 +- Add tests for progress report (jtulak) +- Add e2fsck progress (jtulak) +- Add progress reporting infrastructure for Ext fsck (jtulak) +- Add a function to test if prog. reporting was initialized (jtulak) +- Add support for LUKS 2 opening and key management (vtrefny) +- Fix few more links for project and documentation website (vtrefny) +- Sync the spec file with downstream (vpodzime) +- Check if 'journalctl' is available before trying to use it in tests (vtrefny) +- Update 'Testing libblockdev' section in documentation (vtrefny) +- Fix link to online documentation (vtrefny) +- Fix how the new kernel module functions are added to docs (vpodzime) + +* Wed Feb 07 2018 Fedora Release Engineering - 2.15-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Wed Feb 07 2018 Iryna Shcherbina - 2.15-3 +- Update Python 2 dependency declarations to new packaging standards + (See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3) + +* Sat Feb 03 2018 Igor Gnatenko - 2.15-2 +- Switch to %%ldconfig_scriptlets + +* Fri Dec 01 2017 Vratislav Podzimek - 2.15-1 +- Do not use the 'btrfs' plugin in overrides tests (vpodzime) +- Do not use the btrfs plugin in library tests (vpodzime) +- Check for btrfs module availability in btrfs module (vtrefny) +- Move kernel modules (un)loading and checking into utils (vtrefny) +- Free locale struct in kbd plugin (vtrefny) +- Add test for setting partition flags on GPT (vtrefny) +- Use only sgdisk to set flags on GPT (vtrefny) +- Move the fs.h file to its original place (vpodzime) +- Add a HACKING.rst file (vpodzime) +- Mark bcache tests as unstable (vpodzime) +- Fix memory leaks in bd_fs_vfat_get_info() (vpodzime) +- Revert the behaviour of bd_fs_check_deps() (vpodzime) +- Split the bd_fs_is_tech_avail() implementation (vpodzime) +- Split the FS plugin source into multiple files (vpodzime) +- Fix bd_s390_dasd_format (vponcova) +- Mark unstable tests as such (vpodzime) +- bd_s390_dasd_is_ldl should be true only for LDL DADSs (vponcova) +- Do not lie about tag creation (vpodzime) + +* Wed Nov 08 2017 Zbigniew Jędrzejewski-Szmek - 2.14-2 +- Rebuild for cryptsetup-2.0.0 + +* Tue Oct 31 2017 Vratislav Podzimek - 2.14-1 +- Support the legacy boot GPT flag (intrigeri) +- Respect the version in the blockdev.pc file (vpodzime) +- Add pkgconfig definitions for the utils library (vpodzime) +- fs.c: Fix potential NULL pointer dereference (vtrefny) +- dm.c: Fix uninitialized values in various dm plugin functions (vtrefny) +- dm.c: Check return values of dm_task_set_name/run/get_info functions (vtrefny) +- fs.c: Fix multiple "forward NULL" warnings in 'bd_fs_ntfs_get_info' (vtrefny) +- lvm-dbus.c: Fix multiple "use after free" coverity warnings (vtrefny) +- Fix duplicate 'const' in generated functions (vtrefny) +- Add some test cases for NTFS (kailueke) +- Add function wrappers for NTFS tools (kailueke) +- exec.c: Fix error message in 'bd_utils_exec_and_report_progress' (vtrefny) +- crypto.c: Fix waiting for enough entropy (vtrefny) +- Ignore some coverity false positive errors (vtrefny) +- exec.c: Ignore errors from 'g_io_channel_shutdown' (vtrefny) +- part.c: Check if we've found a place to put new logical partitions (vtrefny) +- kbd.c: Fix potential string overflow in 'bd_kbd_bcache_create' (vtrefny) +- exec.c: Fix resource leaks in 'bd_utils_exec_and_report_progress' (vtrefny) +- fs.c: Fix "forward null" in 'do_mount' and 'bd_fs_xfs_get_info' (vtrefny) +- part.c: Fix possible NULL pointer dereference (vtrefny) +- crypto.c: Use right key buffer in 'bd_crypto_luks_add_key' (vtrefny) +- exec.c: Fix "use after free" in 'bd_utils_check_util_version' (vtrefny) +- kbd.c: Fix double free in 'bd_kbd_zram_get_stats' (vtrefny) +- part.c: Check if file discriptor is >= 0 before closing it (vtrefny) +- mdraid.c: Fix resource leaks (vtrefny) +- lvm.c: Fix "use after free" in 'bd_lvm_get_thpool_meta_size' (vtrefny) +- fs.c: Fix for loop condition in 'bd_fs_get_fstype' (vtrefny) +- fs.c: Check sscanf return value in 'bd_fs_vfat_get_info' (vtrefny) +- fs.c: Fix resource leaks in 'bd_fs_get_fstype' (vtrefny) +- blockdev.c.in: Fix unused variables (vtrefny) +- Use libbytesize to parse bcache block size (vtrefny) +- Use system values in KbdTestBcacheStatusTest (vtrefny) +- Fix BSSize memory leaks in btrfs and mdraid plugins (vtrefny) +- Skip btrfs subvolume tests with btrfs-progs 4.13.2 (vtrefny) +- Added function to get DM device subsystem (japokorn) +- Sync spec with downstream (vpodzime) + +* Fri Sep 29 2017 Vratislav Podzimek - 2.13-1 +- Fix the rpmlog and shortlog targets (vpodzime) +- Add a function for enabling/disabling plugins' init checks (vpodzime) +- Assign functions to tech-mode categories (vpodzime) +- Add missing items to particular sections in the documentation (vpodzime) +- Add a basic test for the runtime dependency checking (vpodzime) +- Simplify what WITH_BD_BCACHE changes in the KBD plugin (vpodzime) +- Add functions for querying available technologies (vpodzime) +- Dynamically check for the required utilities (vpodzime) +- Use shorter prefix for tempfiles (vtrefny) +- Try harder when waiting for lio device to show up (vtrefny) +- Better handle old and new zram sysfs api in tests (vtrefny) +- Skip btrfs tests on CentOS 7 aarch64 (vtrefny) +- Add new function for setting swap label (vtrefny) +- Use only one git tag for new releases (vtrefny) +- Fix source URL in spec file (vtrefny) +- Add NEWS.rst file (vtrefny) +- Do not include s390utils/vtoc.h in s390 plugin (vtrefny) +- Use "AC_CANONICAL_BUILD" to check architecture instead of "uname" (vtrefny) +- Bypass error proxy in s390 test (vtrefny) +- Fix zFCP LUN max length (vtrefny) +- Do not run g_clear_error after setting it (vtrefny) +- Allow compiling libblockdev without s390 plugin (vtrefny) +- Add a function for getting plugin name (vpodzime) + +* Thu Sep 28 2017 Troy Dawson - 2.12-3 +- Cleanup spec file conditionals correctly + +* Wed Sep 27 2017 Troy Dawson - 2.12-2 +- Cleanup spec file conditionals + +* Wed Aug 30 2017 Vratislav Podzimek - 2.12-1 +- Own directories /etc/libblockdev and /etc/libblockdev/conf.d (vtrefny) +- Wait for resized partition (kailueke) +- Make sure the device is opened for libparted (vpodzime) +- Fix label check in swap_test (vtrefny) +- Use "run_tests" script for running tests from Makefile (vtrefny) +- Add a script for running tests (vtrefny) +- Tests: Move library initialization to setUpClass method (vtrefny) +- Stop skipping FAT resize tests on rawhide (vtrefny) +- Close filesystem before closing the partition during FAT resize (vtrefny) +- Use mountpoint for "xfs_info" calls (vtrefny) +- Use libmount cache when parsing /proc/mounts (vtrefny) +- Add some space for the CI status (vpodzime) +- Confirm the force when creating PVs in FS tests (vpodzime) +- Skip vgremove tests on 32bit Debian (vtrefny) +- Fix names of backing files in tests (vtrefny) +- Fix checking for available locales (vtrefny) +- Skip dependency checking in mpath tests on Debian (vtrefny) +- Skip zRAM tests on Debian (vtrefny) +- Skip the test for device escrow on Debian too (vtrefny) +- Skip free region tests on Debian too (vtrefny) +- Fix redirecting command output to /dev/null in tests (vtrefny) +- Try harder to unmount devices in test cleanup (vtrefny) +- Require only plugins that are needed for given test (vtrefny) +- Try to get distribution info from "PrettyName" if "CPEName" isn't available (vtrefny) +- Use -ff when creating PVs in FS tests (vpodzime) +- Sync spec with downstream (vpodzime) + +* Mon Jul 31 2017 Vratislav Podzimek - 2.11-1 +- Make the KbdZRAMDevicesTestCase inherit from KbdZRAMTestCase (vpodzime) +- Allow non-source directory builds (kailueke) +- Add a way to disable runtime dependency checks (vpodzime) +- Link to GObject even if no plugin is activated (kailueke) +- Skip zram tests on Rawhide (vpodzime) +- Keep most utilities available for tests (vpodzime) +- Use new libmount function to get (un)mount error message (vtrefny) +- Update the documentation URL (vpodzime) + +* Wed Jul 26 2017 Fedora Release Engineering - 2.10-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Jul 05 2017 Vratislav Podzimek - 2.10-1 +- Only enable partition size tolerance with alignment (vpodzime) +- Limit the requested partition size to maximum possible (vpodzime) +- Do not verify vfat FS' size after generic resize (vpodzime) +- Specify tolerance for partition size (kailueke) +- Only use the exact constraint if not using any other (vpodzime) +- Check resulting FS size in tests for generic FS resize (vpodzime) +- Query setting FS label support and generic relabeling (kailueke) +- Do not strictly require all FS utilities (vpodzime) +- Compile everything with the C99 standard (vpodzime) +- Add partition resize function (kailueke) +- Generic Check and Repair Functions (kailueke) +- Query functions for FS resize and repair support (kailueke) +- Update the project/source URL in the spec file (vpodzime) +- Add functions for opening/closing TrueCrypt/VeraCrypt volumes (vpodzime) +- Adapt to a change in behaviour in new libmount (vpodzime) +- Try RO mount also if we get EACCES (vpodzime) +- Size in bytes for xfs_resize_device (kailueke) +- src/plugins/Makefile.am: Remove hard coded include path in /usr prefix (tristan.vanberkom) +- Fixed include for libvolume_key.h (tristan.vanberkom) +- Ignore parted warnings if possible (squimrel) +- bcache tests: Remove FEELINGLUCKY checks (tasleson) +- kbd.c: Code review corrections (tasleson) +- kbd.c: Make bd_kbd_bcache_create work without abort (tasleson) + +* Tue Jun 13 2017 Vratislav Podzimek - 2.9-1 +- Fix hardcoded reference to gcc (timo.gurr) +- Catch and ignore partial failures in LVM tests' cleanups (vpodzime) +- Fix hardcoded reference to pkg-config (timo.gurr) +- Make GObject introspection optional (vpodzime) +- Do not link libraries required by plugins to the GI files (vpodzime) +- Make sure the whole build status image is shown (vpodzime) +- Show CI status in README (at the GH repo's front page) (vpodzime) +- Always require the libudev pkg (tgurr) +- Make sure we give kernel time to fully setup zram device(s) (vpodzime) +- fs_test.py: Close FDs when calling utilities (tasleson) +- crypto.c: Correct segmentation fault (tasleson) + +* Tue Jun 06 2017 Vratislav Podzimek - 2.8-1 +- Temporarily skip vfat generic resize test on rawhide (vtrefny) +- Use "safeprobe" in "bd_fs_wipe" (vtrefny) +- Add a generic filesystem resize function (vtrefny) +- Add a function to get mountpoint for a device (vtrefny) +- Add a function to get filesystem type for a device (vtrefny) +- Only include the LVM DBus config when shipping LVM DBus (vpodzime) +- Skip the LVM DBus vgreduce tests on Rawhide (vpodzime) +- Do not build the lvm-dbus plugin on RHEL/CentOS (vpodzime) +- Give zRAM more time to settle before trying to remove a device (vpodzime) +- Put zram tests adding/removing devices into a separate class (vpodzime) +- Skip LVM cache and RAID tests on Rawhide (vpodzime) +- Fix the skip_on decorator factory for tests (vpodzime) +- Use 'blkid -p' instead of lsblk to get device's FS type (vpodzime) +- Improve the lvm_set_global_config test (vpodzime) +- Pass '-y' to pvresize (vpodzime) +- Create a copy of os.environ for a child process (vpodzime) +- Revert "Use the "C.UTF-8" locale instead of just "C"" (vpodzime) +- Fix how we create vfat FS in tests (vpodzime) +- Skip the test if requiring unavailable locales (vpodzime) +- Use the "C.UTF-8" locale instead of just "C" (vpodzime) +- Add functions for working with ext2 and ext3 filesystems (vtrefny) +- Link to gobject when lvm or btrfs is enabled (andreas) +- Link to libm where needed (andreas) +- Add a function for cleaning a device (vtrefny) +- Add few code exaples to documentation (vtrefny) +- Use a special exception for no fs signature when doing wipe (vpodzime) +- One more incompatible os.symlink() call (vpodzime) +- Do not use pass-by-name in the os.symlink() call (vpodzime) +- Ignore previous errors when falling back to using ioctl() (vpodzime) +- Use ioctl() call to teardown loop devices (vpodzime) +- Resolve the device to remove for mdadm (vpodzime) +- Add a function for getting device symlinks (vpodzime) +- Use the new resolve_device() function where appropriate (vpodzime) +- Add the resolve_device() function to the utils library (vpodzime) +- First try to read the 'autoclear' flag from /sys/ (vpodzime) + +* Wed Apr 26 2017 Vratislav Podzimek - 2.7-1 +- Skip btrfs min size tests on Fedora 25 (vtrefny) +- Make sure the loop device doesn't disappear during tests (vpodzime) +- Close the loop device when autoclear is (un)set (vpodzime) +- Do not enforce Python 3 for running tests in CI (vpodzime) +- Revert "Use different BTRFS_MIN_MEMBER_SIZE on aarch64" (vtrefny) +- Use both 'old' and 'new' sysfs files to read zRAM stats (vtrefny) +- Check if libparted-fs-resize pkgconfig is available (vpodzime) +- Do not try to get name for inactive partitions (vtrefny) +- Skip tests for getting free regions on CentOS/RHEL (vpodzime) +- Free the container holding the specs of free regions (vpodzime) +- Open loop devices as O_RDONLY when getting flags (vpodzime) +- Resolve maximum partition size when we know its start (vpodzime) +- Use --id instead of --part-type when setting partition id (vpodzime) +- Fix mdadm command for removing failed device from an array (vtrefny) +- Skip bcache tests on CentOS/RHEL 7 (vpodzime) +- Use six.assertRaisesRegex in the FS tests (vpodzime) +- Use mkdtemp() instead of TemporaryDirectory() (vpodzime) +- Fix installation without specifying --exec-prefix (vpodzime) +- Add options to force mkfs.ext4/vfat to create a FS on the whole device (vpodzime) +- Skip the test for device escrow on CentOS/RHEL (vpodzime) +- Define DEVNULL on our own if not in subprocess (vpodzime) +- Remove the patches from the spec file (vpodzime) +- Sync the spec file with downstream (vpodzime) +- Stop skipping zRAM stats tests (vtrefny) +- Add more tests for zRAM stats (vtrefny) +- Fix reading zRAM properties from sysfs (vtrefny) + +* Wed Apr 12 2017 Vratislav Podzimek - 2.6-3 +- Do not try to parse 'raid_spec' for 'bd_md_activate' (vtrefny) + Resolves: rhbz#1439111 + +* Tue Apr 11 2017 Vratislav Podzimek - 2.6-2 +- Make sure the returned thpool MD size is valid (vpodzime) + +* Wed Mar 15 2017 Vratislav Podzimek - 2.6-1 +- Move the part_err library before part and fs (vtrefny) +- Fix BuildRequires for crypto and dm packages (vtrefny) +- Fix mounting read-only devices (vtrefny) +- Fix the bd_s390_dasd_is_ldl function. (vponcova) +- Add the bd_s390_dasd_is_fba function to check if DASD is FBA (vponcova) +- Disable MD RAID tests on 32bit systems (vpodzime) +- Fix error message when mounting with a wrong fs type (vtrefny) +- Only create RPMs for requested/configured plugins (vpodzime) +- Only check dependencies of plugins to be built (vpodzime) +- Only build and distribute plugins if configured so (vpodzime) +- Fix format-security and unused-result compiler warnings (vtrefny) +- Add an AC macro for modular builds (vpodzime) +- Add functions for mounting and unmounting filesystems (vtrefny) + +* Mon Mar 06 2017 Vratislav Podzimek - 2.5-1 +- Do not try to get GVariant after not adding anything to its builder (vpodzime) +- Replace NULL with "" when building ExtraArg (vpodzime) +- Replace NULL with "" when adding it as a 's' GVariant (vpodzime) +- Make sure we don't try to add NULL as GVariant to DBus params (vpodzime) +- Add function for getting recommended thpool metadata size (vpodzime) +- Make udev settle after we create a LIO device (vpodzime) +- Always use '--yes' for lvremove (vpodzime) + +* Tue Feb 21 2017 Vratislav Podzimek - 2.4-1 +- Update specs.rst to use present-tense and current API (agrover) +- Add functions using BLOBs as LUKS passphrases (vpodzime) +- Make sure the _error_quark() functions are in the library (vtrefny) +- Return a special error when trying to wipe empty device (vtrefny) +- Adapt tests to use LIO devices instead of loop devices (vpodzime) +- Add functions for creating and deleting LIO devices (vpodzime) +- MDRAID: Allow path as input for functions that work with sysfs (vtrefny) + +* Wed Feb 15 2017 Vratislav Podzimek - 2.3-3 +- Rebuild with changelog fixed up + +* Tue Feb 14 2017 Vratislav Podzimek - 2.3-1 +- Allow specifying raid 'name' in multiple way when calling md functions (vtrefny) +- Allow using both path and raid name in bd_md_set_bitmap_location (vtrefny) +- Fix potential memory issues in s390 sanitizate functions (vpodzime) +- Try multiple times when probing device for wiping (vpodzime) +- Check for libvolume_key.h and dmraid.h in configure.ac (vpodzime) +- Define our own macro for testing required header files (vpodzime) +- Include blockdev/utils.h in mdraid.h (vtrefny) +- Fix misspelling (agrover) +- Skip the bcache tests even on x86_64 (vpodzime) +- Take a break between bcache creation tests (vpodzime) +- Make sure ./configure fails if there are some soft failures (vpodzime) +- Improve the error message on missing GI support (vpodzime) +- Only require bcache-tools if supporting bcache (vpodzime) +- Skip bcache tests on non-x86_64 architectures (vpodzime) +- Try harder to register a new bcache device (vpodzime) +- Reimplement swapon/swapoff functions by using syscalls (vpodzime) +- Make sure bcache functions are correctly provided or not (vpodzime) +- Changelog fixup (vpodzime) + +* Fri Feb 10 2017 Fedora Release Engineering - 2.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Wed Jan 11 2017 Vratislav Podzimek - 2.2-2 +- Rebuild with changelog fixed up + +* Wed Jan 11 2017 Vratislav Podzimek - 2.2-1 +- Use the .in file as source when bumping version (vpodzime) +- Run pylint based on the python version and make it optional (vpodzime) +- Disable python3 and bcache on RHEL (vpodzime) +- Make bcache support optional (vpodzime) +- Teach boileplate_generator.py to skip things based on patterns (vpodzime) +- Require lower versions of some utilities (vpodzime) +- Do not require python3 for the boilerplate generation script (vpodzime) +- Use a proper initialization value for 'GPollFD fds[2]' (vpodzime) +- Deal with older parted and libblkid (vpodzime) +- Make python3 and gtk-doc optional (vpodzime) +- Bump the version of the utils library (vpodzime) +- Fix docstring for 'bd_md_node_from_name' (vtrefny) +- Add tests for added mdraid methods (vtrefny) +- Skip 'MDTestNominateDenominateActive' unless feeling lucky (vtrefny) +- MDRaid tests: change 'wait_for_resync' to wait for given action (vtrefny) +- Add functionality need by storaged to mdraid plugin (vtrefny) +- Move 'echo_str_to_file' method to utils (vtrefny) +- Add a function to setup a loop device from a file descriptor (vpodzime) +- Add functions to get/set the autoclear flag on a loop device (vpodzime) +- Fix checking /proc/mdstat for resync action (vtrefny) +- Adapt the test config files to version 2.x (vpodzime) + +* Mon Dec 12 2016 Charalampos Stratakis - 2.1-3 +- Rebuild for Python 3.6 + +* Tue Nov 15 2016 Vratislav Podzimek - 2.1-2 +- Rebuild for a chain-build with storaged (vpodzime) + +* Thu Nov 10 2016 Vratislav Podzimek - 2.1-1 +- Do not require an exclusive lock on the device to commit part stuff (vpodzime) +- Prevent failure if there are no btrfs subvolumes (vpodzime) +- Fix the test for getting version of a failing utility (vpodzime) +- Also run the utils tests (vpodzime) +- Bump the version of the pkgconfig module (vpodzime) +- Include utils.h in plugins that need it (vpodzime) +- Fix dependency check in fs plugin (vtrefny) +- Add support for setting part id (part type) on msdos part tables (vtrefny) +- Trim the extra info for MD RAID's name (vpodzime) +- Add xfsprogs and dosfstools as dependencies of the fs plugin (vpodzime) +- Fix md_name_from_node to work with the "/dev/" prefix (vpodzime) +- New major upstream release + +* Wed Nov 9 2016 Vratislav Podzimek - 1.9-8 +- Revert "Prevent issues between libparted and udev" (vpodzime) +- Revert "Open the device file as RDWR when committing parts" (vpodzime) + +* Thu Oct 27 2016 Vratislav Podzimek - 1.9-7 +- Open the device file as RDWR when committing parts (vpodzime) +- Handle mdadm --examine output during migration (adamw) + Resolves: rhbz#1381996 + +* Mon Oct 24 2016 Vratislav Podzimek - 1.9-6 +- Prevent issues between libparted and udev (vpodzime) + +* Mon Oct 10 2016 Vratislav Podzimek - 1.9-5 +- Make sure all object paths are passed and extracted as such (vpodzime) + Resolves: rhbz#1374973 + +* Tue Oct 4 2016 Vratislav Podzimek - 1.9-4 +- Do not report volume name for FW RAID container device (vpodzime) + Related: rhbz#1379865 +- Search for just "UUID" in mdadm --examine output (vpodzime) + Related: rhbz#1379865 +- Use 'mdadm --examine --export' to get MD RAID level (vpodzime) + Related: rhbz#1379865 + +* Mon Oct 3 2016 Vratislav Podzimek - 1.9-3 +- Try to search for "RAID Level" in mdadm's output (vpodzime) + Resolves: rhbz#1379865 +- Fix the number passed to LVM DBus as a job-creation timeout (vpodzime) + Resolves: rhbz#1378970 + +* Mon Aug 29 2016 Vratislav Podzimek - 1.9-2 +- Explicitly cast number constants for GVariants (vpodzime) + +* Wed Jul 27 2016 Vratislav Podzimek - 1.9-1 +- Add functions for creating thin/cache pools from existing LVs (vpodzime) +- Add the new mpath_get_members() function to the docs (vpodzime) + +* Tue Jul 19 2016 Fedora Release Engineering - 1.8-2 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Wed Jun 29 2016 Vratislav Podzimek - 1.8-1 +- Add a function to get all mpath member devices (vpodzime) +- Fix backport issues in the zfcp-related functionality (#1348442) (vpodzime) +- Revert "Fix a few const params in the s390 plugin." (vpodzime) +- Fix creation of the version-only tags (vpodzime) + +* Wed Jun 15 2016 Vratislav Podzimek - 1.7-1 +- Include the LV roles in the LVdata (vpodzime) +- Add a few missing items to the documentation (vpodzime) +- Document fields of the structures (vpodzime) +- Report (meta)data LV name properly for cache pools in lvm-dbus (vpodzime) +- Add information about related LVs to LVMLVdata (vpodzime) +- Remove unused code for getting supported functions (vpodzime) +- Add zFCP functionality to s390 plugin (sbueno+anaconda) +- Fix a few const params in the s390 plugin. (sbueno+anaconda) + +* Wed Jun 01 2016 Vratislav Podzimek - 1.6-1 +- Ignore merge commits when creating changelog (vpodzime) +- Only take the number of the first %%changelog line found (vpodzime) +- Add some more detailed description to the part plugin (vpodzime) +- Fix a few extra issues with the const types (vpodzime) +- Add function for getting best free region (vpodzime) +- Add function for getting free regions (vpodzime) +- Fix the error message when setting part flag fails (vpodzime) +- Add function for setting disk flags (vpodzime) +- Add function for getting information about disk(s) (vpodzime) +- Do not set nonsense partition paths (vpodzime) +- Add function for getting partition by position (vpodzime) +- Indicate if there was error from parted or not in set_parted_error() (vpodzime) +- Minor fixes for the bd_part_get_part_spec() function (vpodzime) +- Add support for extra GPT flags (vpodzime) +- Add functionality for partition types (GUIDs) (vpodzime) +- Add functionality for partition names (vpodzime) +- Do not destroy disk objects we didn't get (vpodzime) +- Add a function for setting multiple partition flags at once (vpodzime) +- Remove the unused definition USE_PYTHON3 from configure.ac (vpodzime) +- Use different BTRFS_MIN_MEMBER_SIZE on aarch64 (vpodzime) +- Better release memory from parted objects on failures (vpodzime) +- Rework how we do optimal alignment (vpodzime) +- Do not try to destroy object we didn't get (vpodzime) +- Don't pass sizes in bytes to LVM (#1317373) (vpodzime) +- Add the libbytesize-devel build requires (vpodzime) +- Search for the LVM DBus service in both active and activatable names (vpodzime) +- Adapt to another stupid change in btrfs-progs (vpodzime) +- Add the XFS-related functions to the documentation (vpodzime) +- Add tests for the XFS-related functions (vpodzime) +- Add support for the XFS file system to the FS plugin (vpodzime) +- Add chunk_size to BDMDExamineData (vtrefny) +- Add the subpackage for the FS plugin (vpodzime) +- Add the FS plugin to the docs (vpodzime) +- Add tests for the ext4 functionality in the fs plugin (vpodzime) +- Add the FS plugin and the ext4 support (vpodzime) +- Add a function for running utility reporting error and exit code (vpodzime) +- Add the subpackage for the part plugin (vpodzime) +- Add a missing BuildRequires for parted-devel (vpodzime) +- Tag as both libblockdev-$version and just $version (vpodzime) +- Add the 'part' plugin to documentation (vpodzime) +- Add tests for the newly added part plugin (vpodzime) +- Add the part plugin with storaged-required functionality (vpodzime) + +* Mon Mar 21 2016 Vratislav Podzimek - 1.5-1 +- Merge pull request #72 from vpodzime/master-faster_tests (vpodzime) +- Ignore all .bak files (vpodzime) +- Use python3-pylint and skip Python 2 tests (vpodzime) +- Try a bit harder when deactivating MD arrays in tests (vpodzime) +- Recompile only the LVM plugin in tests (vpodzime) +- Merge pull request #65 from vpodzime/master-loc_indep_error (vpodzime) +- Merge pull request #70 from vojtechtrefny/master-chunk_size (vpodzime) +- Add bd_md_create_with_chunk_size() function (vtrefny) +- Merge pull request #68 from vpodzime/master-no_intro_data (vpodzime) +- Merge pull request #71 from vpodzime/master-ipython3 (vpodzime) +- Run coverage with the right config directories (vpodzime) +- Merge pull request #67 from phatina/master (vpodzime) +- Merge pull request #69 from vpodzime/master-lvm_dbus_autostart (vpodzime) +- Use ipython3 for debugging and testing sessions (vpodzime) +- Don't expect to always get introspection data from DBus (vpodzime) +- Make invocation of tests configurable (phatina) +- Make error messages locale agnostic (vpodzime) + +* Tue Mar 15 2016 Vratislav Podzimek - 1.4-5 +- Search for the LVM DBus service in activatable names (vpodzime) +- Better check for the LVM DBus API (vpodzime) + +* Wed Mar 9 2016 Vratislav Podzimek - 1.4-4 +- Do not try to get object path of NULL in vgreduce (vpodzime) + +* Tue Mar 1 2016 Peter Robinson 1.4-3 +- Depend on python3-gobject-base not python3-gobject so as to not pull in X components + +* Thu Feb 25 2016 Vratislav Podzimek - 1.4-2 +- Add/fix the requirement for the LVM DBus daemon + +* Thu Feb 25 2016 Vratislav Podzimek - 1.4-1 +- Merge pull request #62 from vpodzime/master-clean_up (vpodzime) +- Use addCleanup() instead of tearDown() in tests (vpodzime) +- Merge pull request #58 from vpodzime/master-lvm_dbus_pr (vpodzime) +- Add the VG renaming functionality (vpodzime) +- Packaging of the lvm-dbus plugin (vpodzime) +- The LVM DBus plugin (vpodzime) +- Add more generic functions for logging (vpodzime) +- Use MAX(a, b) instead of CLAMP(b, a, b) (vpodzime) +- Merge pull request #59 from vpodzime/master-vgrename (vpodzime) +- Add a function for renaming VGs (vpodzime) +- Merge pull request #57 from clumens/master (vpodzime) +- Fix error reporting when running "make test". (clumens) +- Merge pull request #54 from vojtechtrefny/master-pvsize (vpodzime) +- Do not try to create a PV with 4KiB metadata space (vpodzime) +- Add pv_info to BDLVMPVdata (vtrefny) +- btrfs now requires at least 128MiB device(s) (vpodzime) +- Merge pull request #52 from vpodzime/master (vpodzime) +- Round size in thpoolcreate() to KiB (vpodzime) +- Sync the %%changelog in spec with downstream (vpodzime) + +* Wed Nov 25 2015 Vratislav Podzimek - 1.3-4 +- Create the cache pool before the to-be-cached LV (vpodzime) + +* Thu Nov 05 2015 Robert Kuska - 1.3-3 +- Rebuilt for Python3.5 rebuild + +* Wed Nov 04 2015 Vratislav Podzimek - 1.3-2 +- Fix the annotation of bd_try_init in blockdev.c (vpodzime) + +* Mon Oct 26 2015 Vratislav Podzimek - 1.3-1 +- Add missing python GI requires (vpodzime) +- Merge pull request #49 from dashea/libblockdev-python (vpodzime) +- Merge pull request #50 from vpodzime/master-fix_striped_lv (vpodzime) +- Merge pull request #46 from vpodzime/master-bcache_destroy (vpodzime) +- Merge pull request #39 from vpodzime/master-lvm_physical_space (vpodzime) +- Add a missing ldconfig that rpmlint found. (dshea) +- Move python files to separate packages (#1256758) (dshea) +- Fix lvcreate calls for striped LVs (vpodzime) +- Merge pull request #48 from vojtechtrefny/master_pvfree (vpodzime) +- Add pv_free to BDLVMPVdata (vtrefny) +- Merge pull request #47 from atodorov/add_coverage_report (vpodzime) +- Produce coverage report in CI (atodorov) +- Check bcache device's state before trying to detach the cache in destroy() (vpodzime) +- Fix URLs in the spec (vpodzime) +- Fix the int-float less-than comparison (vpodzime) +- Fix the calculation of physical space taken by an LV (vpodzime) + +* Wed Sep 23 2015 Vratislav Podzimek - 1.2-1 +- Merge pull request #40 from vpodzime/master-config_support (vpodzime) +- Add tests for configuration support (vpodzime) +- Add a function for getting the loaded soname for a plugin (vpodzime) +- Add the default configuration (vpodzime) +- Load and respect configuration files when loading plugins (vpodzime) +- Add functions for finding and processing configuration files (vpodzime) +- Merge pull request #38 from vpodzime/master-md_superblock_size (vpodzime) +- Better document how MD RAID superblock size should be calculated (vpodzime) +- Merge pull request #36 from phatina/master (vpodzime) +- BTRFS: allow an arbitrary label to be set for a btrfs volume (phatina) +- Merge pull request #32 from phatina/master (vpodzime) +- BTRFS: fix parsing empty partition label (phatina) +- Merge pull request #35 from vpodzime/master (vpodzime) +- Define env variables for sudo via the env utility (vpodzime) +- Merge pull request #34 from dashea/python3-tests (vpodzime) +- Use unittest.addCleanup to simplify crypto_test. (dshea) +- Run tests with both python2 and python3 in the ci target. (dshea) +- Fix python3 issues in the unittests. (dshea) +- Do not run all tests in the 'ci' target (vpodzime) +- Merge pull request #33 from clumens/master (vpodzime) +- Add a new makefile target that does everything needed for jenkins. (clumens) +- Synchronize the .spec file with downstream (vpodzime) + +* Fri Jul 24 2015 Vratislav Podzimek - 1.1-2 +- Explicitly specify the type of the cert_data parameter (#1246096) (vpodzime) + +* Fri Jun 19 2015 Vratislav Podzimek - 1.1-1 +- Clean generated boilerplate code on 'make clean' (vpodzime) +- Merge pull request #31 from atodorov/use_lang_c (vpodzime) +- tests: use LANG=C in test_backup_passphrase() (atodorov) +- Merge pull request #30 from atodorov/makefile_updates (vpodzime) +- Makefile.am: - add separate check target - add coverage targets - make it possible to test with Python3 (atodorov) +- Merge pull request #29 from atodorov/fix_issue_28 (vpodzime) +- Merge pull request #27 from atodorov/fix_docs_url (vpodzime) +- Merge pull request #26 from atodorov/test_docs (vpodzime) +- Change the modified sources back in tearDown() method as well. Closes #28. (atodorov) +- update URL to on-line documentation (atodorov) +- add test documentation (atodorov) +- Merge pull request #22 from dashea/escrow-tests (vpodzime) +- Merge pull request #25 from dashea/python-dep (vpodzime) +- Filter the python files from automatic rpm requires (dshea) +- Added tests for escrow packets and backup passphrases (dshea) +- Free leaked contexts from crypto_init (dshea) +- Cooperate with volume_key's memory management (dshea) +- Fix inheritance in the LVM tests to prevent multiple runs of some tests (vpodzime) +- Make the regexp for testing crypto_generate_backup_passphrase() stricter (vpodzime) +- Leave room in the backup passphrase for a trailing 0 (dshea) +- Add functions to get names of data/metadata internal LVs (vpodzime) +- Allow getting info for an internal LV (vpodzime) +- Gather information about all LVs (vpodzime) +- Round requested size to KBs in lvresize() (#1221247) (vpodzime) +- Add overrides for the ensure_init() function (vpodzime) +- Change the default value of the 'reload' parameter of try_reinit() (vpodzime) +- Merge pull request #21 from vpodzime/master-thpool_size_discard (vpodzime) +- Add overrides for the lvm_is_valid_thpool_chunk_size() function (vpodzime) + +* Wed Jun 17 2015 Fedora Release Engineering - 1.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Thu May 21 2015 Vratislav Podzimek - 1.0-1 +- Adapt the release helper targets to autotools (vpodzime) +- Fixes of paths in Makefile.am's inspired by build failures on s390 (vpodzime) +- Add an s390-specific BuildRequires (vpodzime) +- Distribute also the boilerplate_generator.py script (vpodzime) +- Fix path to the generated blockdev.pc file (vpodzime) +- Adapt tests that compile stuff to autotools (vpodzime) +- Merge pull request #18 from vpodzime/master-autotools (vpodzime) +- Merge pull request #20 from dashea/gtkdoc-sections (vpodzime) +- Use the autotools building system instead of scons (vpodzime) +- Add the two new functions to the 'blockdev' docs section (vpodzime) +- Fix the line defining the docs file for the s390 section (vpodzime) +- Add a missing #include to the kbd.api file (vpodzime) +- Prevent s390-specific stuff from being used on other architectures (vpodzime) +- Update the documentation of the is_initialized() function (vpodzime) +- Merge pull request #19 from vpodzime/master-ensure_init (vpodzime) +- Remove private macros from the gtkdoc sections file. (dshea) +- Terminate ifdef statements for arch check. (sbueno+anaconda) +- Return early from the init functions if setting up logging fails (vpodzime) +- Add tests for the new and modified init functions (vpodzime) +- Add new try_init() and try_reinit() functions (vpodzime) +- Fix for adding number of loaded plugins (vpodzime) +- Fix for ensure_init() (vpodzime) +- Rename the try_init() function to ensure_init() and improve it (vpodzime) +- Check number of loaded plugins and library initialization state (vpodzime) +- Make 'reload' default to True instead of False in overrides (vpodzime) +- Add the s390 plugin test file. (sbueno+anaconda) +- Add the s390 plugin functions. (sbueno+anaconda) +- Add the s390 plugin. (sbueno+anaconda) +- Fix a typo in the spec file. (sbueno+anaconda) +- Require the kmod-devel package for the build process (vpodzime) +- Merge pull request #16 from dashea/escrow-encoding (vpodzime) +- Merge pull request #13 from vpodzime/master-lvm_cache (vpodzime) +- Merge pull request #12 from vpodzime/master-kbd_plugin (vpodzime) +- Merge pull request #14 from vpodzime/master-better_is_multipath (vpodzime) +- Use g_strdup() instead of g_strdup_printf() to just dup a string (vpodzime) +- Fix the spelling of "escrow" (dshea) +- Make the crypto plugin string parameters const (dshea) +- Set encoding to NULL before writing the escrow packet. (dshea) +- Get cache stats directly from the device mapper (vpodzime) +- Reimplement the is_mpath_member() function using device mapper (vpodzime) +- Add the LVM cache related symbols to the LVM section in the documentation (vpodzime) +- Update the list of LVM cache related functions in features.rst (vpodzime) +- Add tests for functions related to the LVM cache technology (vpodzime) +- Implement the lvm_cache_stats() function (vpodzime) +- Implement the lvm_cache_pool_name function (vpodzime) +- Implement the lvm_cache_create_cached_lv() function (vpodzime) +- Implement lvm_cache_attach/detach() functions (vpodzime) +- Implement the lvm_cache_create_pool() function plus two support functions (vpodzime) +- Implement the lvm_cache_get_default_md_size() function (vpodzime) +- Add the 'type' parameter to the lvm_lvcreate function (vpodzime) +- Teach boilerplate_generator to work with enum return types (vpodzime) +- Teach boilerplate_generator to work with 'const' return types (vpodzime) +- Add subpackages for the KBD plugin and its devel files (vpodzime) +- Add provided symbols to the documentation section of the KBD plugin (vpodzime) +- Implement the bcache_get_backing/cache_device functions (vpodzime) +- Exclude bcache tests from the normal 'test' target (vpodzime) +- Add some more and prolong some of the waits in KBD tests (vpodzime) +- Zero all newly allocated structures (vpodzime) +- Implement the bcache_status function and all it wants (vpodzime) +- Fix for the zram stats (vpodzime) +- Add bcache_get_mode and bcache_set_mode functions (vpodzime) +- Teach boilerplate_generator to work with enum return types (vpodzime) +- Teach boilerplate_generator to work with 'const' return types (vpodzime) +- Add the zram_get_stats function (vpodzime) +- Add the check() function for the KBD plugin (vpodzime) +- Add ErrorProxy instance for the KBD plugin (vpodzime) +- Add tests for bcache_create/attach/detach/destroy functions (vpodzime) +- Add the 'rebuild' Makefile target (vpodzime) +- Add bcache_create, bcache_attach, bcache_detach and bcache_destroy functions (vpodzime) +- Implement a helper function to echo string into a file (vpodzime) +- Add tests for zram_create_devices and zram_destroy_devices functions (vpodzime) +- Add the zram_destroy_devices function to the KBD plugin (vpodzime) +- Add first function to the KBD plugin: zram_create_devices (vpodzime) +- Add the KernelBlockDevices plugin (vpodzime) + +* Wed May 13 2015 Vratislav Podzimek - 0.13-1 +- Prevent a leaky test from running in Jenkins (vpodzime) +- Try harder when cleaning up after MD RAID tests (vpodzime) +- Improve the MD RAID activate/deactivate test (vpodzime) +- One more @contextmanager that needs try-finally (vpodzime) +- Do not require metadata version to be reported by 'mdadm --examine' (#1217900) (vpodzime) +- Make sure we always set things back in context managers (vpodzime) +- Make the release date for version 1.0 more realistic (vpodzime) +- Merge pull request #11 from vpodzime/master (vpodzime) +- Run utilities with LC_ALL=C (vpodzime) (#1219033) +- Free GMatchInfo instance even in case of no match (vpodzime) +- Resolve /dev/md/ symlinks when checking swap status. (dlehman) + +* Fri Apr 24 2015 Vratislav Podzimek - 0.12-1 +- Require minimum version of libblockdev-utils in some plugins (vpodzime) +- Report both stdout and stderr if exit code != 0 (vpodzime) + +* Fri Apr 17 2015 Vratislav Podzimek - 0.11-1 +- Fix issues with using overriden functions over ErrorProxy (vpodzime) +- Update the roadmap.rst and features.rst with new stuff (vpodzime) +- Fix two minor issues with docs generation (vpodzime) + +* Thu Apr 16 2015 Vratislav Podzimek - 0.10-1 +- Fix return type of the unload_plugins() function (vpodzime) +- Close the DL handle when check() or init() fail (vpodzime) +- Add one more check to the reload test (vpodzime) +- Drop reference to check() and init() functions (vpodzime) +- Add more cats to tests (vpodzime) +- Make regexp for getting btrfs version more generic (vpodzime) +- Merge pull request #8 from vpodzime/master-check_functions (vpodzime) +- Fix parameters passed to unoverridden swapon function (vpodzime) +- Implement and test swap plugin's check function (vpodzime) +- Implement and test MD RAID plugin's check function (vpodzime) +- Implement and test mpath plugin's check function (vpodzime) +- Try harder to get util's version (vpodzime) +- Implement and test loop plugin's check function (vpodzime) +- Implement and test DM plugin's check function (vpodzime) +- Implement and test BTRFS plugin's check function (vpodzime) +- Implement and test LVM plugin's check function (vpodzime) +- Init logging before loading plugins (vpodzime) +- Add function for utility availability checking (vpodzime) +- Fix default value for the fake_utils' path argument (vpodzime) +- Add ErrorProxy instance for the utils functions (vpodzime) +- Add function for version comparison (vpodzime) +- Merge pull request #9 from clumens/master (vpodzime) +- Disable pylint checking on the new exception proxy. (clumens) +- Fix XRules application and add a test for it (vpodzime) +- Raise NotImplementedError when an unavailable function is called (vpodzime) +- Merge pull request #4 from vpodzime/master-error_proxy (vpodzime) +- Merge branch 'master' into master-error_proxy (vpodzime) +- Merge pull request #5 from vpodzime/master-not_implemented_error (vpodzime) +- Add a simple test for unloaded/unavailable functions (vpodzime) +- Unload the plugins properly when reinit() is called (vpodzime) +- Raise error/exception when an unimplemented function is called (#1201475) (vpodzime) +- Do an ugly but necessary hack to make local GI overrides work (vpodzime) +- Add the __dir__ method to ErrorProxy (vpodzime) +- Add a rationale for the ErrorProxy to the overrides' docstring (vpodzime) +- Add some basic info about GI overrides to the documentation (vpodzime) +- Use pylint to check for errors in python overrides (vpodzime) +- Add the first small test for the ErrorProxy (vpodzime) +- Put the GI overrides in a special dir so that they are preferred (vpodzime) +- Add a cache for attributes already resolved by ErrorProxy (vpodzime) +- Implement the ErrorProxy python class and use it (vpodzime) + +* Tue Apr 07 2015 Vratislav Podzimek - 0.9-1 +- Merge pull request #7 from vpodzime/master-fw_raid_fixes (vpodzime) +- Try a bit harder when trying to determine MD RAID name (#1207317) (vpodzime) +- Don't be naïve about mdadm --detail telling us what we want (#1207317) (vpodzime) +- Ignore libblockdev tarballs (vpodzime) +- Implement a test of btrfs_list_subvolumes on data from bug report (vpodzime) +- Implement a context manager for running tests with fake utils (vpodzime) +- Do not try to cannonicalize MD UUIDs if we didn't get them (#1207317) (vpodzime) +- Fix the table in roadmap.rst (vpodzime) +- Enrich the roadmap.rst file and add info about new plans (vpodzime) +- Sync spec file with downstream (vpodzime) + +* Fri Mar 27 2015 Vratislav Podzimek - 0.8-1 +- Merge pull request #6 from vpodzime/master-sort_btrfs_subvolumes (vpodzime) +- Don't be naïve about mdadm providing us data we would like (#1206394) (vpodzime) +- Sort BTRFS subvolumes in a way that child never appears before parent (#1201120) (vpodzime) +- Let libcryptsetup handle LUKSname->/dev/mapper/LUKSname for us (vpodzime) +- Fix the crypto_luks_resize and create a test for it (vpodzime) +- Add targets to create the SRPM and RPM files easily (vpodzime) +- Don't round up to multiple of PE size bigger than max value of the rtype (vpodzime) +- Mark majority of MD RAID tests as slow (vpodzime) +- Merge pull request #1 from dashea/file-paths (vpodzime) +- Don't report error for no loop device associated with given file (vpodzime) +- Skip the detail_data.clean check when running tests in Jenkins (vpodzime) +- Make package file paths more specific (dshea) +- Implement and use MD RAID-specific wait for tests (vpodzime) +- Try to give MD RAID time to sync things before querying them (vpodzime) +- Fix the default value of the BDMDDetailData.clean field (vpodzime) +- Do cleanup after every single MD RAID tests (vpodzime) +- Do cleanup after every single LVM test (vpodzime) +- Do cleanup after every single BTRFS test (vpodzime) +- Make sure the LUKS device is closed and removed after tests (vpodzime) +- Make sure DM maps from tests are removed after tests (vpodzime) +- Make sure that loop devices are deactivated after tests (vpodzime) +- Make the tearDown method of the mpath test case better visible (vpodzime) +- Make sure that the swap is deactivated after tests (vpodzime) +- Fix docstrings in tests' utils helper functions (vpodzime) +- Improve the logging tests in utils_test.py (vpodzime) +- Update the features.rst file (vpodzime) +- Update the roadmap (vpodzime) +- Don't check if we get a mountpoint for BTRFS operations (vpodzime) + +* Sun Mar 22 2015 Peter Robinson 0.7-2 +- Ship license as per packaging guidelines +- plugins-all should depend on base library too +- Add dev docs + +* Fri Feb 27 2015 Vratislav Podzimek - 0.7-1 +- Be ready for mdadm --examine to not provide some of the values we want (vpodzime) +- Add exit code information to exec logging (vpodzime) +- Improve and add tests (vpodzime) +- Mark the test_force_plugin and test_reload as slow (vpodzime) +- Make sure we get some devices when creating btrfs volume (vpodzime) +- Add override for the lvremove function (vpodzime) +- Do not create LUKS format with no passphrase and no key file (vpodzime) +- Make sure we use the /dev/mapper/... path for luks_status (vpodzime) + +* Thu Feb 19 2015 Vratislav Podzimek - 0.6-1 +- Don't report error when non-existing swap's status is queried (vpodzime) +- Make libblockdev-plugins-all pull the same version of plugins (vpodzime) +- Don't report error when asked for a backing file of an uknown loop (vpodzime) +- Fix accidental change in the spec's changelog (vpodzime) + +* Mon Feb 16 2015 Vratislav Podzimek - 0.5-1 +- Add tests for what we can easily test from the mpath plugin (vpodzime) +- Add link to sources to the documentation (vpodzime) +- Add missing symbols into the libblockdev-sections.txt file (vpodzime) +- Do not build docs for testing (vpodzime) +- Add the bd_try_init function (vpodzime) +- Log stdout and stderr output when running processes (vpodzime) +- Allow a subset of plugins to be load instead of all (vpodzime) +- Make sure devmapper doesn't spam stdout with tons of messages (vpodzime) +- Let debug messages go to stderr when running ipython (vpodzime) +- Give plugins a way to initialize themselves (vpodzime) +- Give plugins a way how to check if they could run properly (vpodzime) +- Allow a subset of plugins to be load instead of all [TEST NEEDED] (vpodzime) +- Make sure we use the whole /dev/mapper path for cryptsetup (vpodzime) +- Fix vg_pv_count parsing when getting info about PV (vpodzime) +- Set default values to data structures if real values are not available (vpodzime) +- Fix the parameter name specifying pool metadata size (vpodzime) +- Activate LUKS as ReadWrite in luks_open (vpodzime) +- Make sure we pass key_size to cryptsetup in bytes (vpodzime) +- Add the min_entropy parameter to luks_format Python overrides (vpodzime) +- Pass size in KiB instead of B to lvcreate (vpodzime) +- Add underscore into dataalignment and metadatasize parameter names (vpodzime) +- Don't report error if non-mpath device is tested for being mpath member (vpodzime) +- Fix name of the invoked utility in mpath_set_friendly_names (vpodzime) + +* Sat Jan 31 2015 Vratislav Podzimek - 0.4-1 +- Improve the test for lvm_set_global_config (vpodzime) +- Fix some minor issues in the spec file (vpodzime) +- Fix issues with the LVM global config str (vpodzime) +- Add couple more Python overrides (vpodzime) +- Fix the name of the lvm_thlvpoolname() function in the header file (vpodzime) +- Use assertEqual instead of assertTrue(a == b) (vpodzime) +- Add the min_entropy parameter to luks_format (vpodzime) +- Move internal dmraid-related macros into the source file (vpodzime) +- Add an override for the md_add function (vpodzime) +- Fix parameters in luks_open python overrides (vpodzime) +- Prevent init() from being done multiple times and provide a test function (vpodzime) +- Add the roadmap.rst document (vpodzime) +- Remove an extra parenthesis in one of the docstrings (vpodzime) +- Move the mddetail function next to the mdexamine function (vpodzime) +- Add some more constants required by blivet (vpodzime) + +* Wed Jan 21 2015 Vratislav Podzimek - 0.3-1 +- Require volume_key-devel in a version that fixes build issues (vpodzime) +- Fix Python 2 devel package name in BuildRequires (vpodzime) +- Generate docs for the library and all plugins (vpodzime) +- Make doc comments better for documentation generation (vpodzime) +- Fix parameter names in function prototypes (vpodzime) +- Add the metadatasize parameter to pvcreate (vpodzime) +- Add the dataalignment parameter to lvm_pvcreate (vpodzime) +- Export non-internal constants via introspection (vpodzime) +- Expand size constants in the GI-scanned files (vpodzime) +- Fix usage printing in the boilerplate_generator (vpodzime) +- Add the build directory to .gitignore (vpodzime) +- Add the md_run function (vpodzime) +- Fix some issues in Python overrides (vpodzime) +- Add the escrow_device function to the crypto plugin (vpodzime) +- Fix version of GI files in the Makefile (vpodzime) +- Make the order of release target's dependencies more explicit (vpodzime) + +* Mon Jan 12 2015 Vratislav Podzimek - 0.2-1 +- Fix dependencies of the release target (vpodzime) +- Python overrides for the GI-generated bindings (vpodzime) +- Pass version info to the code and use it to load plugins (vpodzime) + +* Wed Dec 10 2014 Vratislav Podzimek - 0.1-1 +- Initial release