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