chiark / gitweb /
udevd: do not wrongly delay events for devices with swapped names
authorKay Sievers <kay.sievers@vrfy.org>
Wed, 13 Oct 2010 11:03:27 +0000 (13:03 +0200)
committerKay Sievers <kay.sievers@vrfy.org>
Wed, 13 Oct 2010 11:08:29 +0000 (13:08 +0200)
Renaming network devices might delay events for the other device, which has
the same devpath in the meantime as the original event. Causing a delay until
the timout of the event is reached.

Look at the ifindex/devnum of the devices to check if they are really
the same devices.

Makefile.am
libudev/libudev-device.c
libudev/libudev-private.h
udev/udevd.c

index 093a10e058f565d1a3a12e62ccdfe3f759ea1042..fd13005f353bf9b3bed0549bc6a64666f0eacc3f 100644 (file)
@@ -35,7 +35,7 @@ DISTCHECK_HOOKS =
 # libudev
 # ------------------------------------------------------------------------------
 LIBUDEV_CURRENT=9
-LIBUDEV_REVISION=1
+LIBUDEV_REVISION=2
 LIBUDEV_AGE=9
 
 SUBDIRS += libudev/docs
index 5811490a34599cbfdb4078938bda213a33c405fa..e5f8cc3e46b765d2af84ebcfed0123c33db689d5 100644 (file)
@@ -67,6 +67,7 @@ struct udev_device {
        int devlink_priority;
        int refcount;
        dev_t devnum;
+       int ifindex;
        int watch_handle;
        int maj, min;
        bool parent_set;
@@ -187,6 +188,8 @@ void udev_device_add_property_from_string_parse(struct udev_device *udev_device,
                udev_device_set_seqnum(udev_device, strtoull(&property[7], NULL, 10));
        } else if (strncmp(property, "TIMEOUT=", 8) == 0) {
                udev_device_set_timeout(udev_device, strtoull(&property[8], NULL, 10));
+       } else if (strncmp(property, "IFINDEX=", 8) == 0) {
+               udev_device_set_ifindex(udev_device, strtoull(&property[8], NULL, 10));
        } else {
                udev_device_add_property_from_string(udev_device, property);
        }
@@ -358,6 +361,8 @@ int udev_device_read_uevent_file(struct udev_device *udev_device)
                        maj = strtoull(&line[6], NULL, 10);
                else if (strncmp(line, "MINOR=", 6) == 0)
                        min = strtoull(&line[6], NULL, 10);
+               else if (strncmp(line, "IFINDEX=", 8) == 0)
+                       udev_device_set_ifindex(udev_device, strtoull(&line[8], NULL, 10));
                else if (strncmp(line, "DEVNAME=", 8) == 0)
                        udev_device_set_knodename(udev_device, &line[8]);
 
@@ -1536,3 +1541,14 @@ int udev_device_set_watch_handle(struct udev_device *udev_device, int handle)
        udev_device->watch_handle = handle;
        return 0;
 }
+
+int udev_device_get_ifindex(struct udev_device *udev_device)
+{
+       return udev_device->ifindex;
+}
+
+int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
+{
+       udev_device->ifindex = ifindex;
+       return 0;
+}
index 7ed4afc42c7d1db91e50b494cbdba6ab59709560..c9ed46211cb57fb8179f8cbf67a36e0123a30b8e 100644 (file)
@@ -99,6 +99,8 @@ int udev_device_get_devlink_priority(struct udev_device *udev_device);
 int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio);
 int udev_device_get_watch_handle(struct udev_device *udev_device);
 int udev_device_set_watch_handle(struct udev_device *udev_device, int handle);
+int udev_device_get_ifindex(struct udev_device *udev_device);
+int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex);
 void udev_device_set_info_loaded(struct udev_device *device);
 
 /* libudev-device-private.c */
index 2efab5b39d882d65b9413b29afc3f09a818e9174..21dde824eedd5baa8413614dc995da57a886a2ea 100644 (file)
@@ -123,6 +123,7 @@ struct event {
        const char *devpath_old;
        dev_t devnum;
        bool is_block;
+       int ifindex;
 };
 
 static struct event *node_to_event(struct udev_list_node *node)
@@ -419,6 +420,7 @@ static int event_queue_insert(struct udev_device *dev)
        event->devpath_old = udev_device_get_devpath_old(dev);
        event->devnum = udev_device_get_devnum(dev);
        event->is_block = (strcmp("block", udev_device_get_subsystem(dev)) == 0);
+       event->ifindex = udev_device_get_ifindex(dev);
 
        udev_queue_export_device_queued(udev_queue_export, dev);
        info(event->udev, "seq %llu queued, '%s' '%s'\n", udev_device_get_seqnum(dev),
@@ -486,6 +488,10 @@ static bool is_devpath_busy(struct event *event)
                if (major(event->devnum) != 0 && event->devnum == loop_event->devnum && event->is_block == loop_event->is_block)
                        return true;
 
+               /* check network device ifindex */
+               if (event->ifindex != 0 && event->ifindex == loop_event->ifindex)
+                       return true;
+
                /* check our old name */
                if (event->devpath_old != NULL && strcmp(loop_event->devpath, event->devpath_old) == 0) {
                        event->delaying_seqnum = loop_event->seqnum;
@@ -501,6 +507,11 @@ static bool is_devpath_busy(struct event *event)
 
                /* identical device event found */
                if (loop_event->devpath_len == event->devpath_len) {
+                       /* devices names might have changed/swapped in the meantime */
+                       if (major(event->devnum) != 0 && (event->devnum != loop_event->devnum || event->is_block != loop_event->is_block))
+                               continue;
+                       if (event->ifindex != 0 && event->ifindex != loop_event->ifindex)
+                               continue;
                        event->delaying_seqnum = loop_event->seqnum;
                        return true;
                }