[systemd-devel] [PATCH] udevd: fix synchronization with settle when handling inotify events
David Herrmann
dh.herrmann at gmail.com
Sat Apr 11 04:13:30 PDT 2015
Hi
On Tue, Apr 7, 2015 at 12:03 AM, Daniel Drake <drake at endlessm.com> wrote:
> 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.
> ---
> 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 830aedd..dfecef8 100644
> --- a/src/udev/udevd.c
> +++ b/src/udev/udevd.c
> @@ -1504,9 +1504,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;
> + }
> +
Nice catch!
There's indeed a small race between handling inotify and queuing up
the change-event. We need to re-loop there. One day we should switch
to sd-event to avoid such bugs... I mean the symptom is inherent to
queuing up events while handling them. Meh!
Applied!
Thanks
David
> /* tell settle that we are busy or idle, this needs to be before the
> * PING handling
> */
> --
> 2.1.0
>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
More information about the systemd-devel
mailing list