udev: make sure to install an inotify watch whenever we find a block device locked
authorLennart Poettering <lennart@poettering.net>
Thu, 3 Sep 2020 16:27:53 +0000 (18:27 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 9 Oct 2020 11:22:29 +0000 (13:22 +0200)
commitb8380cc67a738cb7ec68ac03bb128b90d542d53a
treef9d89158ce2fc7120a1b592a62eee6290c8aa0de
parente13d96ca2c956d4b8660a3b30d716316265de7b7
udev: make sure to install an inotify watch whenever we find a block device locked

This fixes a race where a block device that pops up and immediately is
locked (such as a loopback device in preparation) might result in
udev never run any rules for it, and thus never turn on inotify watching
for it (as inotify watching is controlled via an option set via udev
rules), thus not noticing when the device is unlocked/closed again
(which is noticed via IN_CLOSE_WRITE inotify events).

This changes two things:

1. Whenever we encounter a locked block device we'll now inotify watch
   it, so that it is guaranteed we'll notice when the BSD lock fd is
   closed again, and will reprobe.

2. We'll now turn off inotify watching again once we realise the
   udev rules don't actually want that. Previously, once watching a
   device was enabled via a udev rule, it would be watched forever until
   the device disappeared, even if the option was dropped by the rules
   for later events.

Together this will make sure that we'll watch the device via inotify
in both of the following cases:

a) The block device has been BSD locked when udev wanted to look at it

b) The udev rules run for the last seen event for the device say so

In all other cases inotify is off for block devices.

This new behaviour both fixes the race, but also makes the most sense,
as the rules (when they are run) actually really control the watch state
now. And if someone BSD locks a block device then it should be OK to
inotify watch it briefly until the lock is released again as the user
this way more or less opts into the locking protocol.
src/udev/udevd.c