summaryrefslogtreecommitdiffstats
path: root/debian/patches/udevadm-settle.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/udevadm-settle.patch')
-rw-r--r--debian/patches/udevadm-settle.patch105
1 files changed, 105 insertions, 0 deletions
diff --git a/debian/patches/udevadm-settle.patch b/debian/patches/udevadm-settle.patch
new file mode 100644
index 0000000..96cdbcf
--- /dev/null
+++ b/debian/patches/udevadm-settle.patch
@@ -0,0 +1,105 @@
+From 3947abeeb92069705229bff681b28d8ac78aedaa Mon Sep 17 00:00:00 2001
+From: Colin Watson <cjwatson@ubuntu.com>
+Date: Fri, 28 Mar 2014 17:10:16 +0000
+Subject: udev handling
+
+Run udevadm settle around partition table rereads, to avoid races.
+
+This should be replaced by a proper completion-notification mechanism
+between the kernel and udev.
+
+Forwarded: no
+Last-Update: 2019-10-11
+
+Patch-Name: udevadm-settle.patch
+---
+ libparted/arch/linux.c | 56 ++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 54 insertions(+), 2 deletions(-)
+
+diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
+index ccbba865..f6f72360 100644
+--- a/libparted/arch/linux.c
++++ b/libparted/arch/linux.c
+@@ -26,6 +26,7 @@
+ #include <parted/fdasd.h>
+ #endif
+
++#include <stdlib.h>
+ #include <ctype.h>
+ #include <errno.h>
+ #include <fcntl.h>
+@@ -3250,10 +3251,52 @@ _have_blkpg ()
+ return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0;
+ }
+
++static int
++_chrooted ()
++{
++ static int cached = -1;
++ struct stat root, init_root;
++
++ if (cached != -1)
++ return cached;
++
++ if (stat ("/", &root) || stat ("/proc/1/root", &init_root))
++ /* We can't tell, but are unlikely to be able to tell in the
++ * future either.
++ */
++ cached = 0;
++ else if (root.st_dev == init_root.st_dev &&
++ root.st_ino == init_root.st_ino)
++ /* / has the same dev/ino as /sbin/init's root, so we're not
++ * in a chroot.
++ */
++ cached = 0;
++ else
++ /* We must be in a chroot. */
++ cached = 1;
++
++ return cached;
++}
++
+ /* Return nonzero upon success, 0 if something fails. */
+ static int
+ linux_disk_commit (PedDisk* disk)
+ {
++ int ret = 1;
++
++ /* Modern versions of udev may notice the write activity on
++ * partition devices caused by _flush_cache, and may decide to
++ * synthesise some change events as a result. These may in turn run
++ * programs that open partition devices, which will race with us
++ * trying to remove those devices. To avoid this, we need to wait
++ * until udevd has finished processing its event queue.
++ * TODO: for upstream submission, this should check whether udevadm
++ * exists on $PATH.
++ */
++ if (!_chrooted () && system ("udevadm settle") != 0) {
++ /* ignore failures */
++ }
++
+ if (disk->dev->type != PED_DEVICE_FILE) {
+
+ /* We now require BLKPG support. If this assertion fails,
+@@ -3263,10 +3306,19 @@ linux_disk_commit (PedDisk* disk)
+ assert (_have_blkpg ());
+
+ if (!_disk_sync_part_table (disk))
+- return 0;
++ ret = 0;
+ }
+
+- return 1;
++ /* Now we wait for udevd to finish creating device nodes based on
++ * the above activity, so that callers can reliably use them.
++ * TODO: for upstream submission, this should check whether udevadm
++ * exists on $PATH.
++ */
++ if (!_chrooted () && system ("udevadm settle") != 0) {
++ /* ignore failures */
++ }
++
++ return ret;
+ }
+
+ #if USE_BLKID