summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-11-13 02:05:06 +0100
committerKay Sievers <kay@vrfy.org>2012-11-13 02:14:17 +0100
commitbf9d233f781f27841be6638ee745e9c80bda5f4d (patch)
tree9417acb7e0cff3eba0d5af01a20df0994b4ae946
parentcf2292f5ac87087f57dbd632a25a332c9d194ebf (diff)
udev: properly handle symlink removal by 'change' event
If a 'change' event is supposed to remove created symlinks, we create a new device structure from the sysfs device and fill it with the list of links, to compute the delta of the old and new list of links to apply. If the device is already 'remove'd by the kernel though, udev fails to create the device structure, so the links are not removed properly. > From: Neil Brown <nfbrown@suse.com> > Date: Thu, 8 Nov 2012 10:39:06 +0100 > Subject: [PATCH] If a 'change' event does not get handled by udev until > after the device has subsequently disappeared, udev mis-handles > it. This can happen with 'md' devices which emit a change > event and then a remove event when they are stopped. It is > normally only noticed if udev is very busy (lots of arrays > being stopped at once) or the machine is otherwise loaded > and reponding slowly. > > There are two problems. > > 1/ udev_device_new_from_syspath() will refuse to create the device > structure if the device does not exist in /sys, and particularly if > the uevent file does not exist. > If a 'db' file does exist, that is sufficient evidence that the device > is genuine and should be created. Equally if we have just received an > event from the kernel about the device, it must be real. > > This patch just disabled the test for the 'uevent' file, it doesn't > try imposing any other tests - it isn't clear that they are really > needed. > > 2/ udev_event_execute_rules() calls udev_device_read_db() on a 'device' > structure that is largely uninitialised and in particular does not > have the 'subsystem' set. udev_device_read_db() needs the subsystem > so it tries to read the 'subsystem' symlink out of sysfs. If the > device is already deleted, this naturally fails. > udev_event_execute_rules() knows the subsystem (as it was in the > event message) so this patch simply sets the subsystem for the device > structure to be loaded to match the subsystem of the device structure > that is handling the event. > > With these two changes, deleted handling of change events will still > correctly remove any symlinks that are not needed any more. Use udev_device_new() instead of allowing udev_device_new_from_syspath() to proceed without a sysfs device.
-rw-r--r--src/udev/udev-event.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 2f4db3cc0..33ed47763 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -797,8 +797,10 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules,
if (major(udev_device_get_devnum(dev)) != 0)
udev_node_remove(dev);
} else {
- event->dev_db = udev_device_new_from_syspath(event->udev, udev_device_get_syspath(dev));
+ event->dev_db = udev_device_new(event->udev);
if (event->dev_db != NULL) {
+ udev_device_set_syspath(event->dev_db, udev_device_get_syspath(dev));
+ udev_device_set_subsystem(event->dev_db, udev_device_get_subsystem(dev));
udev_device_read_db(event->dev_db, NULL);
udev_device_set_info_loaded(event->dev_db);