1ff636
From e55efa99fd829a4699aae6505e02fae7b50a40bc Mon Sep 17 00:00:00 2001
1ff636
From: Daniel Drake <drake@endlessm.com>
1ff636
Date: Mon, 6 Apr 2015 16:03:43 -0600
1ff636
Subject: [PATCH] udevd: fix synchronization with settle when handling inotify
1ff636
 events
1ff636
1ff636
udev uses inotify to implement a scheme where when the user closes
1ff636
a writable device node, a change uevent is forcefully generated.
1ff636
In the case of block devices, it actually requests a partition rescan.
1ff636
1ff636
This currently can't be synchronized with "udevadm settle", i.e. this
1ff636
is not reliable in a script:
1ff636
1ff636
 sfdisk --change-id /dev/sda 1 81
1ff636
 udevadm settle
1ff636
 mount /dev/sda1 /foo
1ff636
1ff636
The settle call doesn't synchronize there, so at the same time we try
1ff636
to mount the device, udevd is busy removing the partition device nodes and
1ff636
readding them again. The mount call often happens in that moment where the
1ff636
partition node has been removed but not readded yet.
1ff636
1ff636
This exact issue was fixed long ago:
1ff636
http://git.kernel.org/cgit/linux/hotplug/udev.git/commit/?id=bb38678e3ccc02bcd970ccde3d8166a40edf92d3
1ff636
1ff636
but that fix is no longer valid now that sequence numbers are no longer
1ff636
used.
1ff636
1ff636
Fix this by forcing another mainloop iteration after handling inotify events
1ff636
before unblocking settle. If the inotify event caused us to generate a
1ff636
"change" event, we'll pick that up in the following loop iteration, before
1ff636
we reach the end of the loop where we respond to settle's control message,
1ff636
unblocking it.
1ff636
1ff636
(cherry picked from commit 07ba8037bf2a2d6a683fa107ee6f2b9545fca23e)
1ff636
1ff636
Cherry-picked from: 7a2e024
1ff636
Resolves: #1222517
1ff636
---
1ff636
 src/udev/udevd.c | 15 ++++++++++++++-
1ff636
 1 file changed, 14 insertions(+), 1 deletion(-)
1ff636
1ff636
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
181b3f
index e98c1fd6d..87a3f69e9 100644
1ff636
--- a/src/udev/udevd.c
1ff636
+++ b/src/udev/udevd.c
1ff636
@@ -1502,9 +1502,22 @@ int main(int argc, char *argv[]) {
1ff636
                         continue;
1ff636
 
1ff636
                 /* device node watch */
1ff636
-                if (is_inotify)
1ff636
+                if (is_inotify) {
1ff636
                         handle_inotify(udev);
1ff636
 
1ff636
+                        /*
1ff636
+                         * settle might be waiting on us to determine the queue
1ff636
+                         * state. If we just handled an inotify event, we might have
1ff636
+                         * generated a "change" event, but we won't have queued up
1ff636
+                         * the resultant uevent yet.
1ff636
+                         *
1ff636
+                         * Before we go ahead and potentially tell settle that the
1ff636
+                         * queue is empty, lets loop one more time to update the
1ff636
+                         * queue state again before deciding.
1ff636
+                         */
1ff636
+                        continue;
1ff636
+                }
1ff636
+
1ff636
                 /* tell settle that we are busy or idle, this needs to be before the
1ff636
                  * PING handling
1ff636
                  */