diff --git a/.gitignore b/.gitignore
index c794bb6..bbb221c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/udisks-2.9.2.tar.bz2
+SOURCES/udisks-2.9.4.tar.bz2
diff --git a/.udisks2.metadata b/.udisks2.metadata
index cfa44e3..c779a78 100644
--- a/.udisks2.metadata
+++ b/.udisks2.metadata
@@ -1 +1 @@
-15aaadab7f6ce2ddc4c6ca114019241cd1152f04 SOURCES/udisks-2.9.2.tar.bz2
+e6f21e90456360723d80265c4d3372eb88ef7a6e SOURCES/udisks-2.9.4.tar.bz2
diff --git a/SOURCES/udisks-2.10.0-Ignore-Extended-Boot-Loader-GPT-partition.patch b/SOURCES/udisks-2.10.0-Ignore-Extended-Boot-Loader-GPT-partition.patch
deleted file mode 100644
index 1f98913..0000000
--- a/SOURCES/udisks-2.10.0-Ignore-Extended-Boot-Loader-GPT-partition.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 79eed9aa35fbf1c5131b44b50b407742f68e2f61 Mon Sep 17 00:00:00 2001
-From: Florian Ziegler <florian.ziegler@posteo.de>
-Date: Sat, 17 Apr 2021 13:31:31 +0200
-Subject: [PATCH 8/8] Ignore "Extended Boot Loader" GPT partition
-
----
- data/80-udisks2.rules | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/data/80-udisks2.rules b/data/80-udisks2.rules
-index fb50f48a..39bfa28b 100644
---- a/data/80-udisks2.rules
-+++ b/data/80-udisks2.rules
-@@ -135,6 +135,12 @@ ENV{ID_PART_ENTRY_SCHEME}=="gpt", \
-   ENV{ID_PART_ENTRY_TYPE}=="c12a7328-f81f-11d2-ba4b-00a0c93ec93b|21686148-6449-6e6f-744e-656564454649|a19d880f-05fc-4d3b-a006-743f0f84911e|e6d6d379-f507-44c2-a23c-238f2a3df928|e3c9e316-0b5c-4db8-817d-f92df00215ae|de94bba4-06d1-4d40-a16a-bfd50179d6ac", \
-   ENV{UDISKS_IGNORE}="1"
- 
-+# special Extended Boot Loader partition (XBOOTLDR)
-+# see https://systemd.io/BOOT_LOADER_SPECIFICATION/
-+ENV{ID_PART_ENTRY_SCHEME}=="gpt", \
-+  ENV{ID_PART_ENTRY_TYPE}=="bc13c2ff-59e6-4262-a352-b275fd6f7172", \
-+  ENV{UDISKS_IGNORE}="1"
-+
- # ZFS member partitions
- ENV{ID_PART_ENTRY_SCHEME}=="gpt", \
-   ENV{ID_FS_TYPE}=="zfs_member", ENV{ID_PART_ENTRY_TYPE}=="6a898cc3-1dd2-11b2-99a6-080020736631", \
--- 
-2.30.2
-
diff --git a/SOURCES/udisks-2.10.0-ata_conf_apply_GTask.patch b/SOURCES/udisks-2.10.0-ata_conf_apply_GTask.patch
deleted file mode 100644
index 077fada..0000000
--- a/SOURCES/udisks-2.10.0-ata_conf_apply_GTask.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-commit 6ff556afabd490feb6c4b29f9e91e81d64e2c0ed
-Author: Tomas Bzatek <tbzatek@redhat.com>
-Date:   Tue Mar 23 12:56:40 2021 +0100
-
-    udiskslinuxdriveata: Use GTask to apply configuration in a thread
-    
-    Should fix a leaking GThread without a need to join or track it anyhow.
-
-diff --git a/src/udiskslinuxdriveata.c b/src/udiskslinuxdriveata.c
-index 5ebdcd76..2de138cd 100644
---- a/src/udiskslinuxdriveata.c
-+++ b/src/udiskslinuxdriveata.c
-@@ -1625,10 +1625,13 @@ apply_conf_data_free (ApplyConfData *data)
-   g_free (data);
- }
- 
--static gpointer
--apply_configuration_thread_func (gpointer user_data)
-+static void
-+apply_configuration_thread_func (GTask        *task,
-+                                 gpointer      source_object,
-+                                 gpointer      task_data,
-+                                 GCancellable *cancellable)
- {
--  ApplyConfData *data = user_data;
-+  ApplyConfData *data = task_data;
-   UDisksDaemon *daemon;
-   const gchar *device_file = NULL;
-   gint fd = -1;
-@@ -1799,8 +1802,6 @@ apply_configuration_thread_func (gpointer user_data)
-  out:
-   if (fd != -1)
-     close (fd);
--  apply_conf_data_free (data);
--  return NULL;
- }
- 
- /**
-@@ -1819,6 +1820,7 @@ udisks_linux_drive_ata_apply_configuration (UDisksLinuxDriveAta *drive,
- {
-   gboolean has_conf = FALSE;
-   ApplyConfData *data = NULL;
-+  GTask *task;
- 
-   data = g_new0 (ApplyConfData, 1);
-   data->ata_pm_standby = -1;
-@@ -1862,9 +1864,10 @@ udisks_linux_drive_ata_apply_configuration (UDisksLinuxDriveAta *drive,
-   /* this can easily take a long time and thus block (the drive may be in standby mode
-    * and needs to spin up) - so run it in a thread
-    */
--  g_thread_new ("apply-conf-thread",
--                apply_configuration_thread_func,
--                data);
-+  task = g_task_new (data->object, NULL, NULL, NULL);
-+  g_task_set_task_data (task, data, (GDestroyNotify) apply_conf_data_free);
-+  g_task_run_in_thread (task, apply_configuration_thread_func);
-+  g_object_unref (task);
- 
-   data = NULL; /* don't free data below */
- 
diff --git a/SOURCES/udisks-2.10.0-dosfstools_4.2-reread_part.patch b/SOURCES/udisks-2.10.0-dosfstools_4.2-reread_part.patch
deleted file mode 100644
index 414c830..0000000
--- a/SOURCES/udisks-2.10.0-dosfstools_4.2-reread_part.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-commit d58ebcc32b583371dd73ab7f4c7be5191674ca62
-Author: Tomas Bzatek <tbzatek@redhat.com>
-Date:   Wed Mar 17 18:52:22 2021 +0100
-
-    udiskslinuxblock: Re-read partition table after creating FAT filesystem
-    
-    Might not be needed after reverting mkfs.vfat behaviour back
-    to the legacy way, added just as a precautionary measure.
-
-diff --git a/src/udiskslinuxblock.c b/src/udiskslinuxblock.c
-index 901426ad..69161b61 100644
---- a/src/udiskslinuxblock.c
-+++ b/src/udiskslinuxblock.c
-@@ -2913,7 +2913,9 @@ static inline gboolean
- need_partprobe_after_mkfs (const gchar *fs_type)
- {
-   /* udftools makes fake MBR since the 2.0 release */
--  return (g_strcmp0 (fs_type, "udf") == 0);
-+  /* dosfstools makes fake MBR since the 4.2 release */
-+  return (g_strcmp0 (fs_type, "udf") == 0 ||
-+          g_strcmp0 (fs_type, "vfat") == 0);
- }
- 
- void
diff --git a/SOURCES/udisks-2.10.0-dosfstools_4.2.patch b/SOURCES/udisks-2.10.0-dosfstools_4.2.patch
deleted file mode 100644
index 2764315..0000000
--- a/SOURCES/udisks-2.10.0-dosfstools_4.2.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-commit ef1979d8cbfb8ad976de0af21a70f8c0f98fbbe9
-Author: Tomas Bzatek <tbzatek@redhat.com>
-Date:   Wed Mar 17 18:50:19 2021 +0100
-
-    udiskslinuxfsinfo: Add dosfstools >= 4.2 quirks
-    
-    Reverting back the legacy behaviour with no protective (fake) MBR
-    created while making new FAT filesystem on an unpartitioned block device.
-    
-    Added a label clear functionality as well.
-
-diff --git a/src/udiskslinuxfsinfo.c b/src/udiskslinuxfsinfo.c
-index 15af26c8..f18b9b80 100644
---- a/src/udiskslinuxfsinfo.c
-+++ b/src/udiskslinuxfsinfo.c
-@@ -21,6 +21,8 @@
- #include <string.h>
- #include <glib.h>
- 
-+#include <blockdev/exec.h>
-+
- #include "config.h"
- #include "udiskslinuxfsinfo.h"
- #include "udisksconfigmanager.h"
-@@ -236,6 +238,19 @@ const FSInfo _fs_info[] =
-     },
-   };
- 
-+/* workaround for dosfstools >= 4.2 */
-+static const FSInfo vfat_dosfstools_42 =
-+    {
-+      FS_VFAT,
-+      "fatlabel $DEVICE $LABEL",
-+      "fatlabel --reset $DEVICE",
-+      FALSE, /* supports_online_label_rename */
-+      FALSE, /* supports_owners */
-+      "mkfs.vfat -I -n $LABEL --mbr=n $DEVICE",
-+      NULL,
-+      NULL, /* option_no_discard */
-+    };
-+
- /**
-  * get_fs_info:
-  *
-@@ -248,6 +263,7 @@ const FSInfo _fs_info[] =
- const FSInfo *
- get_fs_info (const gchar *fstype)
- {
-+  const FSInfo *info = NULL;
-   guint n;
- 
-   g_return_val_if_fail (fstype != NULL, NULL);
-@@ -255,10 +271,20 @@ get_fs_info (const gchar *fstype)
-   for (n = 0; n < sizeof(_fs_info)/sizeof(FSInfo); n++)
-     {
-       if (strcmp (_fs_info[n].fstype, fstype) == 0)
--        return &_fs_info[n];
-+        {
-+          info = &_fs_info[n];
-+          break;
-+        }
-+    }
-+
-+  /* dosfstools >= 4.2 workaround */
-+  if (g_str_equal (fstype, FS_VFAT) &&
-+      bd_utils_check_util_version ("mkfs.vfat", "4.2", "--help", "mkfs.fat\\s+([\\d\\.]+).+", NULL))
-+    {
-+      info = &vfat_dosfstools_42;
-     }
- 
--  return NULL;
-+  return info;
- }
- 
- /**
diff --git a/SOURCES/udisks-2.10.0-g_mkdtemp-leak.patch b/SOURCES/udisks-2.10.0-g_mkdtemp-leak.patch
deleted file mode 100644
index 58d58cd..0000000
--- a/SOURCES/udisks-2.10.0-g_mkdtemp-leak.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From fcdec5d58ba2bbe6d7ecf7168ab1a11282763041 Mon Sep 17 00:00:00 2001
-From: Tomas Bzatek <tbzatek@redhat.com>
-Date: Fri, 16 Apr 2021 18:15:03 +0200
-Subject: [PATCH 5/8] udiskslinuxfilesystemhelpers: Fix leaking string in case
- g_mkdtemp() fails
-
----
- src/udiskslinuxfilesystemhelpers.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/src/udiskslinuxfilesystemhelpers.c b/src/udiskslinuxfilesystemhelpers.c
-index 74d83152..7c5fc037 100644
---- a/src/udiskslinuxfilesystemhelpers.c
-+++ b/src/udiskslinuxfilesystemhelpers.c
-@@ -142,11 +142,11 @@ take_filesystem_ownership (const gchar  *device,
-       else
-         {
-           /* device is not mounted, we need to mount it */
--          mountpoint = g_mkdtemp (g_strdup ("/run/udisks2/temp-mount-XXXXXX"));
--          if (mountpoint == NULL)
-+          mountpoint = g_strdup ("/run/udisks2/temp-mount-XXXXXX");
-+          if (g_mkdtemp (mountpoint) == NULL)
-             {
-               g_set_error (error, UDISKS_ERROR, UDISKS_ERROR_FAILED,
--                           "Cannot create temporary mountpoint.");
-+                           "Cannot create temporary mountpoint: %m.");
-               success = FALSE;
-               goto out;
-             }
--- 
-2.30.2
-
diff --git a/SOURCES/udisks-2.10.0-lvm2_teardown_tests.patch b/SOURCES/udisks-2.10.0-lvm2_teardown_tests.patch
new file mode 100644
index 0000000..016b9eb
--- /dev/null
+++ b/SOURCES/udisks-2.10.0-lvm2_teardown_tests.patch
@@ -0,0 +1,182 @@
+From dd6ef8393a8f27fefad66cce136e52f13350f0df Mon Sep 17 00:00:00 2001
+From: Tomas Bzatek <tbzatek@redhat.com>
+Date: Fri, 1 Oct 2021 18:23:10 +0200
+Subject: [PATCH] tests: Add LVM2 teardown object existence checks
+
+This adds a check for the created stack objects presence after the teardown.
+
+Due to the nature of the global lvm2 module update some objects may still
+hang around after the org.freedesktop.UDisks2.VolumeGroup.Delete(options='tear-down')
+method call has returned. Until this is properly fixed an explicit timeout
+had to be added.
+---
+ src/tests/dbus-tests/test_20_LVM.py | 80 +++++++++++++++++------------
+ 1 file changed, 46 insertions(+), 34 deletions(-)
+
+diff --git a/src/tests/dbus-tests/test_20_LVM.py b/src/tests/dbus-tests/test_20_LVM.py
+index 56915e580..7fbff0434 100644
+--- a/src/tests/dbus-tests/test_20_LVM.py
++++ b/src/tests/dbus-tests/test_20_LVM.py
+@@ -3,6 +3,7 @@
+ import re
+ import time
+ import unittest
++import six
+ 
+ from distutils.version import LooseVersion
+ 
+@@ -637,7 +638,8 @@ def _remove_luks(self, device, name, close=True):
+                 device.Lock(self.no_options, dbus_interface=self.iface_prefix + '.Encrypted')
+             except dbus.exceptions.DBusException as e:
+                 # ignore when luks is actually already locked
+-                if not str(e).endswith('is not unlocked') and not 'No such interface' in str(e):
++                if not str(e).endswith('is not unlocked') and not 'No such interface' in str(e) and \
++                   not 'Object does not exist at path' in str(e):
+                     raise e
+ 
+         try:
+@@ -645,7 +647,7 @@ def _remove_luks(self, device, name, close=True):
+             d['erase'] = True
+             device.Format('empty', d, dbus_interface=self.iface_prefix + '.Block')
+         except dbus.exceptions.DBusException as e:
+-            if not 'No such interface' in str(e):
++            if not 'No such interface' in str(e) and not 'Object does not exist at path' in str(e):
+                 raise e
+ 
+     def _init_stack(self, name):
+@@ -663,18 +665,19 @@ def _init_stack(self, name):
+         self.assertIsNotNone(self.pv)
+ 
+         self.vg = self._create_vg(vgname, dbus.Array([self.pv]))
++        self.vg_path = self.vg.object_path
+         self.addCleanup(self._remove_vg, self.vg, tear_down=True, ignore_removed=True)
+ 
+         # create an LV on it
+-        lv_path = self.vg.CreatePlainVolume(lvname, dbus.UInt64(200 * 1024**2), self.no_options,
+-                                            dbus_interface=self.iface_prefix + '.VolumeGroup')
+-        self.lv = self.bus.get_object(self.iface_prefix, lv_path)
++        self.lv_path = self.vg.CreatePlainVolume(lvname, dbus.UInt64(200 * 1024**2), self.no_options,
++                                                 dbus_interface=self.iface_prefix + '.VolumeGroup')
++        self.lv = self.bus.get_object(self.iface_prefix, self.lv_path)
+         self.assertIsNotNone(self.lv)
+ 
+-        lv_block_path = self.lv.Activate(self.no_options, dbus_interface=self.iface_prefix + '.LogicalVolume')
+-        self.assertIsNotNone(lv_block_path)
++        self.lv_block_path = self.lv.Activate(self.no_options, dbus_interface=self.iface_prefix + '.LogicalVolume')
++        self.assertIsNotNone(self.lv_block_path)
+ 
+-        self.lv_block = self.get_object(lv_block_path)
++        self.lv_block = self.get_object(self.lv_block_path)
+         self.assertIsNotNone(self.lv_block)
+ 
+         # create LUKS on the LV
+@@ -702,10 +705,10 @@ def _init_stack(self, name):
+         self.addCleanup(self._remove_luks, self.lv_block, vgname)
+         self.luks_uuid = self.get_property_raw(self.lv_block, '.Block', 'IdUUID')
+ 
+-        luks_block_path = self.get_property(self.lv_block, '.Encrypted', 'CleartextDevice')
+-        self.luks_block = self.get_object(luks_block_path.value)
+-        self.assertIsNotNone(self.luks_block)
+-        self.fs_uuid = self.get_property_raw(self.luks_block, '.Block', 'IdUUID')
++        self.luks_block_path = self.get_property_raw(self.lv_block, '.Encrypted', 'CleartextDevice')
++        luks_block = self.get_object(self.luks_block_path)
++        self.assertIsNotNone(luks_block)
++        self.fs_uuid = self.get_property_raw(luks_block, '.Block', 'IdUUID')
+ 
+         # check for present crypttab configuration item
+         conf = self.get_property(self.lv_block, '.Block', 'Configuration')
+@@ -713,7 +716,7 @@ def _init_stack(self, name):
+         self.assertEqual(conf.value[0][0], 'crypttab')
+ 
+         # check for present fstab configuration item on a cleartext block device
+-        conf = self.get_property(self.luks_block, '.Block', 'Configuration')
++        conf = self.get_property(luks_block, '.Block', 'Configuration')
+         conf.assertTrue()
+         self.assertEqual(conf.value[0][0], 'fstab')
+ 
+@@ -730,6 +733,32 @@ def _init_stack(self, name):
+         self.assertIn(vgname, fstab)
+         self.assertIn(self.fs_uuid, fstab)
+ 
++    def _check_torn_down_stack(self, name):
++        # check that all created objects don't exist anymore
++        msg = r'Object does not exist at path|No such interface'
++        with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
++            luks_block = self.get_object(self.luks_block_path)
++            self.get_property_raw(luks_block, '.Block', 'DeviceNumber')
++        with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
++            lv_block = self.get_object(self.lv_block_path)
++            self.get_property_raw(lv_block, '.Block', 'DeviceNumber')
++        with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
++            # the lvm2 udisks module is not fully synchronous, see https://github.com/storaged-project/udisks/pull/814
++            time.sleep(2)
++            lv = self.get_object(self.lv_path)
++            self.get_property_raw(lv, '.LogicalVolume', 'Name')
++        with six.assertRaisesRegex(self, dbus.exceptions.DBusException, msg):
++            vg = self.get_object(self.vg_path)
++            self.get_property_raw(vg, '.VolumeGroup', 'Name')
++
++        # check that fstab and crypttab records have been removed
++        crypttab = self.read_file('/etc/crypttab')
++        self.assertNotIn(name, crypttab)
++        self.assertNotIn(self.luks_uuid, crypttab)
++        fstab = self.read_file('/etc/fstab')
++        self.assertNotIn(name, fstab)
++        self.assertNotIn(self.fs_uuid, fstab)
++
+ 
+     @udiskstestcase.tag_test(udiskstestcase.TestTags.UNSAFE)
+     def test_teardown_active_vg_unlocked(self):
+@@ -741,13 +770,7 @@ def test_teardown_active_vg_unlocked(self):
+ 
+         self._remove_vg(self.vg, tear_down=True, ignore_removed=False)
+ 
+-        # check that fstab and crypttab records have been removed
+-        crypttab = self.read_file('/etc/crypttab')
+-        self.assertNotIn(name, crypttab)
+-        self.assertNotIn(self.luks_uuid, crypttab)
+-        fstab = self.read_file('/etc/fstab')
+-        self.assertNotIn(name, fstab)
+-        self.assertNotIn(self.fs_uuid, fstab)
++        self._check_torn_down_stack(name)
+ 
+     @udiskstestcase.tag_test(udiskstestcase.TestTags.UNSAFE)
+     def test_teardown_active_vg_locked(self):
+@@ -760,13 +783,7 @@ def test_teardown_active_vg_locked(self):
+         self.lv_block.Lock(self.no_options, dbus_interface=self.iface_prefix + '.Encrypted')
+         self._remove_vg(self.vg, tear_down=True, ignore_removed=False)
+ 
+-        # check that fstab and crypttab records have been removed
+-        crypttab = self.read_file('/etc/crypttab')
+-        self.assertNotIn(name, crypttab)
+-        self.assertNotIn(self.luks_uuid, crypttab)
+-        fstab = self.read_file('/etc/fstab')
+-        self.assertNotIn(name, fstab)
+-        self.assertNotIn(self.fs_uuid, fstab)
++        self._check_torn_down_stack(name)
+ 
+     @udiskstestcase.tag_test(udiskstestcase.TestTags.UNSAFE)
+     def test_teardown_inactive_vg_locked(self):
+@@ -780,13 +797,7 @@ def test_teardown_inactive_vg_locked(self):
+         self.lv.Deactivate(self.no_options, dbus_interface=self.iface_prefix + '.LogicalVolume')
+         self._remove_vg(self.vg, tear_down=True, ignore_removed=False)
+ 
+-        # check that fstab and crypttab records have been removed
+-        crypttab = self.read_file('/etc/crypttab')
+-        self.assertNotIn(name, crypttab)
+-        self.assertNotIn(self.luks_uuid, crypttab)
+-        fstab = self.read_file('/etc/fstab')
+-        self.assertNotIn(name, fstab)
+-        self.assertNotIn(self.fs_uuid, fstab)
++        self._check_torn_down_stack(name)
+ 
+     @udiskstestcase.tag_test(udiskstestcase.TestTags.UNSAFE)
+     def test_reformat_inactive_vg_locked(self):
+@@ -812,6 +823,7 @@ def test_reformat_inactive_vg_locked(self):
+ 
+         # check that fstab and crypttab records have been removed
+         # TODO: these checks are the opposite - record shouldn't be present, once this is fixed
++        # self._check_torn_down_stack(name)
+         crypttab = self.read_file('/etc/crypttab')
+         self.assertIn(name, crypttab)
+         self.assertIn(self.luks_uuid, crypttab)
diff --git a/SOURCES/udisks-2.10.0-mdraid-g_source_attach.patch b/SOURCES/udisks-2.10.0-mdraid-g_source_attach.patch
deleted file mode 100644
index 9fb9911..0000000
--- a/SOURCES/udisks-2.10.0-mdraid-g_source_attach.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From cd458666a93fe9d07f3718e88f3169f01a11a63e Mon Sep 17 00:00:00 2001
-From: Tomas Bzatek <tbzatek@redhat.com>
-Date: Fri, 16 Apr 2021 18:36:16 +0200
-Subject: [PATCH 7/8] udiskslinuxmdraidobject: Handle source attach failure
- gracefully
-
-Only negligible theoretical chance to hit this, reported by Coverity.
----
- src/udiskslinuxmdraidobject.c | 10 ++++++++--
- 1 file changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/src/udiskslinuxmdraidobject.c b/src/udiskslinuxmdraidobject.c
-index 20ca89c5..828c7058 100644
---- a/src/udiskslinuxmdraidobject.c
-+++ b/src/udiskslinuxmdraidobject.c
-@@ -468,7 +468,8 @@ watch_attr (UDisksLinuxDevice *device,
-   GError *error = NULL;
-   gchar *path = NULL;
-   GIOChannel *channel = NULL;
--  GSource *ret = NULL;;
-+  GSource *ret = NULL;
-+  guint source_id;
- 
-   g_return_val_if_fail (UDISKS_IS_LINUX_DEVICE (device), NULL);
- 
-@@ -478,9 +479,14 @@ watch_attr (UDisksLinuxDevice *device,
-     {
-       ret = g_io_create_watch (channel, G_IO_ERR);
-       g_source_set_callback (ret, callback, user_data, NULL);
--      g_source_attach (ret, g_main_context_get_thread_default ());
-+      source_id = g_source_attach (ret, g_main_context_get_thread_default ());
-       g_source_unref (ret);
-       g_io_channel_unref (channel); /* the keeps a reference to this object */
-+      if (source_id == 0)
-+        {
-+          /* something bad happened while attaching the source */
-+          ret = NULL;
-+        }
-     }
-   else
-     {
--- 
-2.30.2
-
diff --git a/SOURCES/udisks-2.10.0-mdraid-iochannel-data.patch b/SOURCES/udisks-2.10.0-mdraid-iochannel-data.patch
deleted file mode 100644
index 51daf79..0000000
--- a/SOURCES/udisks-2.10.0-mdraid-iochannel-data.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 0353b5f2f9c586d872750423259b6ef6cc375625 Mon Sep 17 00:00:00 2001
-From: Tomas Bzatek <tbzatek@redhat.com>
-Date: Fri, 16 Apr 2021 18:22:46 +0200
-Subject: [PATCH 6/8] udiskslinuxmdraidobject: Optimize unused data out from
- the g_io_channel_read_to_end() call
-
-Looking into glib sources the g_io_channel_read_to_end() function
-can handle NULL output pointers just fine and since the data is thrown
-right away it's pointless to have them assigned.
----
- src/udiskslinuxmdraidobject.c | 6 +-----
- 1 file changed, 1 insertion(+), 5 deletions(-)
-
-diff --git a/src/udiskslinuxmdraidobject.c b/src/udiskslinuxmdraidobject.c
-index 759ff5f4..20ca89c5 100644
---- a/src/udiskslinuxmdraidobject.c
-+++ b/src/udiskslinuxmdraidobject.c
-@@ -503,8 +503,6 @@ attr_changed (GIOChannel   *channel,
-   UDisksLinuxMDRaidObject *object = UDISKS_LINUX_MDRAID_OBJECT (user_data);
-   gboolean bail = FALSE;
-   GError *error = NULL;
--  gchar *str = NULL;
--  gsize len = 0;
- 
-   if (cond & ~G_IO_ERR)
-     goto out;
-@@ -518,7 +516,7 @@ attr_changed (GIOChannel   *channel,
-       goto out;
-     }
- 
--  if (g_io_channel_read_to_end (channel, &str, &len, &error) != G_IO_STATUS_NORMAL)
-+  if (g_io_channel_read_to_end (channel, NULL, NULL, &error) != G_IO_STATUS_NORMAL)
-     {
-       udisks_debug ("Error reading (uuid %s): %s (%s, %d)",
-                     object->uuid, error->message, g_quark_to_string (error->domain), error->code);
-@@ -527,8 +525,6 @@ attr_changed (GIOChannel   *channel,
-       goto out;
-     }
- 
--  g_free (str);
--
-   /* synthesize uevent */
-   if (object->raid_device != NULL)
-     udisks_linux_mdraid_object_uevent (object, "change", object->raid_device, FALSE);
--- 
-2.30.2
-
diff --git a/SOURCES/udisks-2.10.0-module-names.patch b/SOURCES/udisks-2.10.0-module-names.patch
deleted file mode 100644
index a1a6619..0000000
--- a/SOURCES/udisks-2.10.0-module-names.patch
+++ /dev/null
@@ -1,136 +0,0 @@
-commit e062c17e3829f3c04c25b5f6fc17ccc4491befa8
-Author: Tomas Bzatek <tbzatek@redhat.com>
-Date:   Tue Mar 23 16:48:08 2021 +0100
-
-    modules: Limit module name to alphanumeric characters and -_ separators
-    
-    A hardening feature as long as the module name is directly involved
-    in filename creation.
-
-diff --git a/doc/udisks2-sections.txt.daemon.sections.in b/doc/udisks2-sections.txt.daemon.sections.in
-index 16eaf74e..204ca897 100644
---- a/doc/udisks2-sections.txt.daemon.sections.in
-+++ b/doc/udisks2-sections.txt.daemon.sections.in
-@@ -312,6 +312,7 @@ udisks_daemon_util_get_free_mdraid_device
- udisks_ata_identify_get_word
- udisks_daemon_util_trigger_uevent
- udisks_daemon_util_trigger_uevent_sync
-+udisks_module_validate_name
- </SECTION>
- 
- <SECTION>
-diff --git a/src/udisksconfigmanager.c b/src/udisksconfigmanager.c
-index 9558e276..5868e864 100644
---- a/src/udisksconfigmanager.c
-+++ b/src/udisksconfigmanager.c
-@@ -26,6 +26,7 @@
- #include "udiskslogging.h"
- #include "udisksdaemontypes.h"
- #include "udisksconfigmanager.h"
-+#include "udisksdaemonutil.h"
- 
- struct _UDisksConfigManager {
-   GObject parent_instance;
-@@ -60,6 +61,8 @@ enum
- #define DEFAULTS_GROUP_NAME "defaults"
- #define DEFAULTS_ENCRYPTION_KEY "encryption"
- 
-+#define MODULES_ALL_ARG "*"
-+
- static void
- udisks_config_manager_get_property (GObject    *object,
-                                     guint       property_id,
-@@ -170,7 +173,16 @@ parse_config_file (UDisksConfigManager         *manager,
-             {
-               modules_tmp = modules;
-               for (module_i = *modules_tmp; module_i; module_i = *++modules_tmp)
--                *out_modules = g_list_append (*out_modules, g_strdup (g_strstrip (module_i)));
-+                {
-+                  g_strstrip (module_i);
-+                  if (! udisks_module_validate_name (module_i) && !g_str_equal (module_i, MODULES_ALL_ARG))
-+                    {
-+                      g_warning ("Invalid module name '%s' specified in the %s config file.",
-+                                 module_i, conf_filename);
-+                      continue;
-+                    }
-+                  *out_modules = g_list_append (*out_modules, g_strdup (module_i));
-+                }
-               g_strfreev (modules);
-             }
-         }
-@@ -397,7 +409,7 @@ udisks_config_manager_get_modules_all (UDisksConfigManager *manager)
- 
-   parse_config_file (manager, NULL, NULL, &modules);
- 
--  ret = !modules || (g_strcmp0 (modules->data, "*") == 0 && g_list_length (modules) == 1);
-+  ret = !modules || (g_strcmp0 (modules->data, MODULES_ALL_ARG) == 0 && g_list_length (modules) == 1);
- 
-   g_list_free_full (modules, (GDestroyNotify) g_free);
- 
-diff --git a/src/udisksdaemonutil.c b/src/udisksdaemonutil.c
-index 60134765..1695b524 100644
---- a/src/udisksdaemonutil.c
-+++ b/src/udisksdaemonutil.c
-@@ -1880,3 +1880,29 @@ udisks_daemon_util_trigger_uevent_sync (UDisksDaemon *daemon,
- }
- 
- /* ---------------------------------------------------------------------------------------------------- */
-+
-+/**
-+ * udisks_module_validate_name:
-+ * @module_name: A udisks2 module name.
-+ *
-+ * Checks the string for a valid udisks2 module name. Only alphanumeric characters
-+ * along with the '-' and '_' separators are permitted.
-+ *
-+ * Returns: %TRUE if the string is a valid udisks2 module name, %FALSE otherwise.
-+ */
-+gboolean
-+udisks_module_validate_name (const gchar *module_name)
-+{
-+  int i;
-+
-+  for (i = 0; module_name[i] != '\0'; i++)
-+    /* going ASCII, will disqualify any UTF-* string */
-+    if (! g_ascii_isalnum (module_name[i]) &&
-+        module_name[i] != '-' &&
-+        module_name[i] != '_')
-+      return FALSE;
-+
-+  return TRUE;
-+}
-+
-+/* ---------------------------------------------------------------------------------------------------- */
-diff --git a/src/udisksdaemonutil.h b/src/udisksdaemonutil.h
-index 2d7ac981..df584de4 100644
---- a/src/udisksdaemonutil.h
-+++ b/src/udisksdaemonutil.h
-@@ -129,6 +129,8 @@ gchar *udisks_daemon_util_get_free_mdraid_device (void);
- 
- guint16 udisks_ata_identify_get_word (const guchar *identify_data, guint word_number);
- 
-+gboolean udisks_module_validate_name (const gchar *module_name);
-+
- /* Utility macro for policy verification. */
- #define UDISKS_DAEMON_CHECK_AUTHORIZATION(daemon,                   \
-                                           object,                   \
-diff --git a/src/udiskslinuxmanager.c b/src/udiskslinuxmanager.c
-index 8af65d97..26d8a5d7 100644
---- a/src/udiskslinuxmanager.c
-+++ b/src/udiskslinuxmanager.c
-@@ -956,6 +956,15 @@ handle_enable_module (UDisksManager         *object,
-   UDisksLinuxManager *manager = UDISKS_LINUX_MANAGER (object);
-   EnableModulesData *data;
- 
-+  if (! udisks_module_validate_name (arg_name))
-+    {
-+      g_dbus_method_invocation_return_error (invocation,
-+                                             G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
-+                                             "Requested module name '%s' is not a valid udisks2 module name.",
-+                                             arg_name);
-+      return TRUE;
-+    }
-+
-   if (! arg_enable)
-     {
-       /* TODO: implement proper module unloading */
diff --git a/SOURCES/udisks-2.10.0-static_daemon_resources_free.patch b/SOURCES/udisks-2.10.0-static_daemon_resources_free.patch
new file mode 100644
index 0000000..1f35552
--- /dev/null
+++ b/SOURCES/udisks-2.10.0-static_daemon_resources_free.patch
@@ -0,0 +1,74 @@
+From d205057296957d6064825252a3d3377e809d6fed Mon Sep 17 00:00:00 2001
+From: Tomas Bzatek <tbzatek@redhat.com>
+Date: Wed, 6 Oct 2021 17:12:13 +0200
+Subject: [PATCH] udiskslinuxmountoptions: Do not free static daemon resources
+
+The GResource instance returned from udisks_daemon_resources_get_resource()
+that calls g_static_resource_get_resource() internally is marked as
+'(transfer none)' and should not be freed. In fact that causes double
+free inside the g_static_resource_fini() atexit handler leading
+to memory corruption causing random failures of further atexit
+handlers such as cryptsetup and openssl destructors.
+
+ Invalid read of size 4
+    at 0x4BB03A4: g_resource_unref (gresource.c:527)
+    by 0x4BB2150: g_static_resource_fini (gresource.c:1449)
+    by 0x4010ADB: _dl_fini (dl-fini.c:139)
+    by 0x4EF0DF4: __run_exit_handlers (exit.c:113)
+    by 0x4EF0F6F: exit (exit.c:143)
+    by 0x4ED9566: __libc_start_call_main (libc_start_call_main.h:74)
+    by 0x4ED960B: __libc_start_main@@GLIBC_2.34 (libc-start.c:409)
+    by 0x128774: (below main) (in udisks/src/.libs/udisksd)
+  Address 0x5cc5fc0 is 0 bytes inside a block of size 16 free'd
+    at 0x48430E4: free (vg_replace_malloc.c:755)
+    by 0x4DB10BC: g_free (gmem.c:199)
+    by 0x4BB2148: g_static_resource_fini (gresource.c:1448)
+    by 0x4010ADB: _dl_fini (dl-fini.c:139)
+    by 0x4EF0DF4: __run_exit_handlers (exit.c:113)
+    by 0x4EF0F6F: exit (exit.c:143)
+    by 0x4ED9566: __libc_start_call_main (libc_start_call_main.h:74)
+    by 0x4ED960B: __libc_start_main@@GLIBC_2.34 (libc-start.c:409)
+    by 0x128774: (below main) (in udisks/src/.libs/udisksd)
+  Block was alloc'd at
+    at 0x484086F: malloc (vg_replace_malloc.c:380)
+    by 0x4DB47A8: g_malloc (gmem.c:106)
+    by 0x4BB19C7: UnknownInlinedFun (gresource.c:545)
+    by 0x4BB19C7: g_resource_new_from_data (gresource.c:613)
+    by 0x4BB1A88: register_lazy_static_resources_unlocked (gresource.c:1374)
+    by 0x4BB218C: UnknownInlinedFun (gresource.c:1393)
+    by 0x4BB218C: UnknownInlinedFun (gresource.c:1387)
+    by 0x4BB218C: g_static_resource_get_resource (gresource.c:1472)
+    by 0x14F6A3: UnknownInlinedFun (udisks-daemon-resources.c:284)
+    by 0x14F6A3: udisks_linux_mount_options_get_builtin (udiskslinuxmountoptions.c:612)
+    by 0x12CC6E: udisks_daemon_constructed (udisksdaemon.c:441)
+    by 0x4D1ED96: g_object_new_internal (gobject.c:1985)
+    by 0x4D20227: g_object_new_valist (gobject.c:2288)
+    by 0x4D2075C: g_object_new (gobject.c:1788)
+    by 0x129A5F: udisks_daemon_new (udisksdaemon.c:619)
+    by 0x129AD5: on_bus_acquired (main.c:63)
+    by 0x4C35C95: connection_get_cb.lto_priv.0 (gdbusnameowning.c:504)
+    by 0x4BD3F99: g_task_return_now (gtask.c:1219)
+    by 0x4BD419A: UnknownInlinedFun (gtask.c:1289)
+    by 0x4BD419A: g_task_return (gtask.c:1245)
+    by 0x4C31D51: bus_get_async_initable_cb (gdbusconnection.c:7433)
+    by 0x4BD3F99: g_task_return_now (gtask.c:1219)
+    by 0x4BD3FDC: complete_in_idle_cb (gtask.c:1233)
+    by 0x4DA852A: g_idle_dispatch (gmain.c:5897)
+    by 0x4DAC33E: UnknownInlinedFun (gmain.c:3381)
+    by 0x4DAC33E: g_main_context_dispatch (gmain.c:4099)
+---
+ src/udiskslinuxmountoptions.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/src/udiskslinuxmountoptions.c b/src/udiskslinuxmountoptions.c
+index 7729d4015..819c9ba96 100644
+--- a/src/udiskslinuxmountoptions.c
++++ b/src/udiskslinuxmountoptions.c
+@@ -614,7 +614,6 @@ udisks_linux_mount_options_get_builtin (void)
+                                                "/org/freedesktop/UDisks2/data/builtin_mount_options.conf",
+                                                G_RESOURCE_LOOKUP_FLAGS_NONE,
+                                                &error);
+-  g_resource_unref (daemon_resource);
+ 
+   if (builtin_opts_bytes == NULL)
+     {
diff --git a/SOURCES/udisks-2.10.0-tests-drive_ata-apm.patch b/SOURCES/udisks-2.10.0-tests-drive_ata-apm.patch
deleted file mode 100644
index 32c11ad..0000000
--- a/SOURCES/udisks-2.10.0-tests-drive_ata-apm.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-From c21ad308b1313a35cafa1664e5eb4772925bc005 Mon Sep 17 00:00:00 2001
-From: Tomas Bzatek <tbzatek@redhat.com>
-Date: Thu, 22 Apr 2021 18:05:29 +0200
-Subject: [PATCH 1/2] tests: Mark Drive.ATA tests as unstable
-
-Some of the tests operate on physical ATA drives, comparing values between
-smartctl output and udisks. Different libraries used, different approach
-to retrieve some ATA features and values. Turned out this is not working
-correctly on some SATA disks with each approach giving slightly different
-results, presumably for the quirks in place.
----
- src/tests/dbus-tests/test_drive_ata.py | 8 +++++---
- 1 file changed, 5 insertions(+), 3 deletions(-)
-
-diff --git a/src/tests/dbus-tests/test_drive_ata.py b/src/tests/dbus-tests/test_drive_ata.py
-index 3187367e..e91bd02f 100644
---- a/src/tests/dbus-tests/test_drive_ata.py
-+++ b/src/tests/dbus-tests/test_drive_ata.py
-@@ -4,7 +4,7 @@ import re
- import unittest
- import time
- 
--from udiskstestcase import UdisksTestCase
-+import udiskstestcase
- 
- SMART_CMDLINE_FAIL      = 1 << 0
- SMART_OPEN_READ_FAIL    = 1 << 1
-@@ -32,7 +32,7 @@ def _get_sata_disks():
- 
- 
- for disk in _get_sata_disks():
--    ret, out = UdisksTestCase.run_command("smartctl -a /dev/%s" % disk)
-+    ret, out = udiskstestcase.UdisksTestCase.run_command("smartctl -a /dev/%s" % disk)
- 
-     # Only the following bits in the exit status mean the device failed to
-     # provide valid SMART data, others may be set for different reasons (see
-@@ -46,7 +46,7 @@ for disk in _get_sata_disks():
-     else:
-         smart_unsupported.add(disk)
- 
--class UdisksDriveAtaTest(UdisksTestCase):
-+class UdisksDriveAtaTest(udiskstestcase.UdisksTestCase):
-     '''Noninvasive tests for the Drive.Ata interface'''
- 
-     def get_smart_setting(self, disk, attr, out_prefix):
-@@ -102,6 +102,7 @@ class UdisksDriveAtaTest(UdisksTestCase):
-             intro_data = drive_intro.Introspect()
-             self.assertNotIn('interface name="org.freedesktop.UDisks2.Drive.Ata"', intro_data)
- 
-+    @udiskstestcase.tag_test(udiskstestcase.TestTags.UNSTABLE)
-     @unittest.skipUnless(smart_supported, "No disks supporting S.M.A.R.T. available")
-     def test_properties(self):
-         for disk in smart_supported:
-@@ -148,6 +149,7 @@ class UdisksDriveAtaTest(UdisksTestCase):
-                 # ninth field is the raw value
-                 self.assertEqual(int(pwon_s.value / 3600), int(pwon_attr[8]))
- 
-+    @udiskstestcase.tag_test(udiskstestcase.TestTags.UNSTABLE)
-     @unittest.skipUnless(smart_supported, "No disks supporting S.M.A.R.T. available")
-     def test_smart_get_attributes(self):
-         for disk in smart_supported:
--- 
-2.30.2
-
diff --git a/SOURCES/udisks-2.10.0-tests-no-dev_disk-by-path.patch b/SOURCES/udisks-2.10.0-tests-no-dev_disk-by-path.patch
deleted file mode 100644
index 044a8aa..0000000
--- a/SOURCES/udisks-2.10.0-tests-no-dev_disk-by-path.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 1358d1e5208d71d5a70f17a242eda00f079a9d0b Mon Sep 17 00:00:00 2001
-From: Tomas Bzatek <tbzatek@redhat.com>
-Date: Thu, 22 Apr 2021 18:20:48 +0200
-Subject: [PATCH 2/2] tests: Handle missing /dev/disk/by-path gracefully
-
-Limited testing environments may not have this path always available.
----
- src/tests/dbus-tests/test_drive_ata.py | 19 +++++++++++--------
- 1 file changed, 11 insertions(+), 8 deletions(-)
-
-diff --git a/src/tests/dbus-tests/test_drive_ata.py b/src/tests/dbus-tests/test_drive_ata.py
-index e91bd02f..37740c60 100644
---- a/src/tests/dbus-tests/test_drive_ata.py
-+++ b/src/tests/dbus-tests/test_drive_ata.py
-@@ -20,14 +20,17 @@ DISK_PATH = "/dev/disk/by-path/"
- 
- def _get_sata_disks():
-     sata_disks = []
--    by_path = os.listdir(DISK_PATH)
--    for dev in by_path:
--        if "ata" in dev and "part" not in dev:
--            path = os.path.realpath(os.path.join(DISK_PATH, dev))
--            name = os.path.basename(path)
--            if name.startswith("sd"):
--                # ignore devices like CD drives etc.
--                sata_disks.append(name)
-+    try:
-+        by_path = os.listdir(DISK_PATH)
-+        for dev in by_path:
-+            if "ata" in dev and "part" not in dev:
-+                path = os.path.realpath(os.path.join(DISK_PATH, dev))
-+                name = os.path.basename(path)
-+                if name.startswith("sd"):
-+                    # ignore devices like CD drives etc.
-+                    sata_disks.append(name)
-+    except:
-+        pass
-     return sata_disks
- 
- 
--- 
-2.30.2
-
diff --git a/SPECS/udisks2.spec b/SPECS/udisks2.spec
index 3780351..0257784 100644
--- a/SPECS/udisks2.spec
+++ b/SPECS/udisks2.spec
@@ -47,23 +47,16 @@
 
 Name:    udisks2
 Summary: Disk Manager
-Version: 2.9.2
-Release: 6%{?dist}
+Version: 2.9.4
+Release: 2%{?dist}
 License: GPLv2+
 URL:     https://github.com/storaged-project/udisks
 Source0: https://github.com/storaged-project/udisks/releases/download/udisks-%{version}/udisks-%{version}.tar.bz2
-Patch0:  udisks-2.10.0-dosfstools_4.2.patch
-Patch1:  udisks-2.10.0-dosfstools_4.2-reread_part.patch
-Patch2:  udisks-2.10.0-module-names.patch
-Patch3:  udisks-2.10.0-ata_conf_apply_GTask.patch
 # https://github.com/storaged-project/udisks/pull/847
-Patch4:  ignore-apple-boot-part.patch
-Patch5:  udisks-2.10.0-g_mkdtemp-leak.patch
-Patch6:  udisks-2.10.0-mdraid-iochannel-data.patch
-Patch7:  udisks-2.10.0-mdraid-g_source_attach.patch
-Patch8:  udisks-2.10.0-Ignore-Extended-Boot-Loader-GPT-partition.patch
-Patch9:  udisks-2.10.0-tests-drive_ata-apm.patch
-Patch10: udisks-2.10.0-tests-no-dev_disk-by-path.patch
+Patch0:  ignore-apple-boot-part.patch
+# https://bugzilla.redhat.com/show_bug.cgi?id=2001549
+Patch1:  udisks-2.10.0-static_daemon_resources_free.patch
+Patch2:  udisks-2.10.0-lvm2_teardown_tests.patch
 
 BuildRequires: make
 BuildRequires: glib2-devel >= %{glib2_version}
@@ -439,6 +432,14 @@ fi
 %endif
 
 %changelog
+* Tue Oct 26 2021 Tomas Bzatek <tbzatek@redhat.com> - 2.9.4-2
+- Gating test fix
+
+* Tue Oct 26 2021 Tomas Bzatek <tbzatek@redhat.com> - 2.9.4-1
+- Version 2.9.4 (#2010363)
+- CVE-2021-3802: Harden the default mount options for ext filesystems (#2004423)
+- Fix double free on daemon exit (unaligned fastbin chunk) (#2001549)
+
 * Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 2.9.2-6
 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
   Related: rhbz#1991688