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