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