From: Kay Sievers Date: Thu, 19 Apr 2007 20:21:05 +0000 (+0200) Subject: udevd: fix serialization of events X-Git-Tag: 174~1998 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc630edad4631f4c046052f504a67ce9df381531;p=systemd udevd: fix serialization of events We see sequences like: UEVENT[1176966403.907336] add@/block/dasda UDEV [1176966403.920359] add@/block/dasda UEVENT[1176966403.964379] add@/block/dasda/dasda1 UEVENT[1176966403.964438] add@/block/dasda/dasda2 UEVENT[1176966403.964483] online@/block/dasda UEVENT[1176966403.964519] online@/block/dasda/dasda1 UEVENT[1176966403.964555] online@/block/dasda/dasda2 UDEV [1176966403.967413] add@/block/dasda/dasda1 UDEV [1176966403.968719] add@/block/dasda/dasda2 UDEV [1176966403.974750] online@/block/dasda/dasda1 UDEV [1176966403.982241] online@/block/dasda/dasda2 UDEV [1176966403.999847] online@/block/dasda where the event for the disk (last event) should come before the events for the partitons. We skipped events for dependency reasons, but the dependency check for later events did not see the skipped events. --- diff --git a/udevd.c b/udevd.c index 8f3329ea..dccc745e 100644 --- a/udevd.c +++ b/udevd.c @@ -495,26 +495,49 @@ static int compare_devpath(const char *running, const char *waiting) return 0; } -/* returns still running task for the same device, its parent or its physical device */ -static int running_with_devpath(struct udevd_uevent_msg *msg, int limit) +/* lookup event for identical, parent, child, or physical device */ +static int devpath_busy(struct udevd_uevent_msg *msg, int limit) { struct udevd_uevent_msg *loop_msg; int childs_count = 0; + /* check exec-queue which may still contain delayed events we depend on */ + list_for_each_entry(loop_msg, &exec_list, node) { + /* skip ourself and all later events */ + if (loop_msg->seqnum >= msg->seqnum) + break; + + /* check identical, parent, or child device event */ + if (compare_devpath(loop_msg->devpath, msg->devpath) != 0) { + dbg("%llu, device event still pending %llu (%s)", + msg->seqnum, loop_msg->seqnum, loop_msg->devpath); + return 2; + } + + /* check physical device event (special case of parent) */ + if (msg->physdevpath && msg->action && strcmp(msg->action, "add") == 0) + if (compare_devpath(loop_msg->devpath, msg->physdevpath) != 0) { + dbg("%llu, physical device event still pending %llu (%s)", + msg->seqnum, loop_msg->seqnum, loop_msg->devpath); + return 3; + } + } + + /* check runing-queue for still running events */ list_for_each_entry(loop_msg, &running_list, node) { if (limit && childs_count++ > limit) { - dbg("%llu, maximum number (%i) of child reached", msg->seqnum, childs_count); + dbg("%llu, maximum number (%i) of childs reached", msg->seqnum, childs_count); return 1; } - /* return running parent/child device event */ + /* check identical, parent, or child device event */ if (compare_devpath(loop_msg->devpath, msg->devpath) != 0) { - dbg("%llu, child device event still running %llu (%s)", + dbg("%llu, device event still running %llu (%s)", msg->seqnum, loop_msg->seqnum, loop_msg->devpath); return 2; } - /* return running physical device event */ + /* check physical device event (special case of parent) */ if (msg->physdevpath && msg->action && strcmp(msg->action, "add") == 0) if (compare_devpath(loop_msg->devpath, msg->physdevpath) != 0) { dbg("%llu, physical device event still running %llu (%s)", @@ -522,11 +545,10 @@ static int running_with_devpath(struct udevd_uevent_msg *msg, int limit) return 3; } } - return 0; } -/* exec queue management routine executes the events and serializes events in the same sequence */ +/* serializes events for the identical and parent and child devices */ static void msg_queue_manager(void) { struct udevd_uevent_msg *loop_msg; @@ -552,8 +574,8 @@ static void msg_queue_manager(void) } } - /* don't run two processes for the same devpath and wait for the parent*/ - if (running_with_devpath(loop_msg, max_childs)) { + /* serialize and wait for parent or child events */ + if (devpath_busy(loop_msg, max_childs) != 0) { dbg("delay seq %llu (%s)", loop_msg->seqnum, loop_msg->devpath); continue; }