udevd: do not wrongly delay events for devices with swapped names

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.
This commit is contained in:
Kay Sievers 2010-10-13 13:03:27 +02:00
parent 457c67e7c1
commit fc416258f3
4 changed files with 30 additions and 1 deletions

View file

@ -35,7 +35,7 @@ DISTCHECK_HOOKS =
# libudev
# ------------------------------------------------------------------------------
LIBUDEV_CURRENT=9
LIBUDEV_REVISION=1
LIBUDEV_REVISION=2
LIBUDEV_AGE=9
SUBDIRS += libudev/docs

View 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;
}

View 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 */

View 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;
}