X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udevd.c;h=3c29c2be6e1ef67cefc37f2fe15b9b3913962051;hb=87da5b2c65e0a889093c27189212505328aea4ab;hp=2337493f1ebdf00c37f431b1397f73d8f23fc2b0;hpb=f602ccf0723f116c2c3a77e057a0540027aa38b8;p=elogind.git diff --git a/udevd.c b/udevd.c index 2337493f1..3c29c2be6 100644 --- a/udevd.c +++ b/udevd.c @@ -38,8 +38,8 @@ #include "list.h" #include "udev.h" -#include "udev_lib.h" #include "udev_version.h" +#include "udev_utils.h" #include "udevd.h" #include "logging.h" @@ -64,7 +64,6 @@ static void reap_sigchilds(void); char *udev_bin; #ifdef LOG -unsigned char logname[LOGNAME_SIZE]; void log_message (int level, const char *format, ...) { va_list args; @@ -124,6 +123,7 @@ static void msg_queue_insert(struct hotplug_msg *msg) /* forks event and removes event from run queue when finished */ static void udev_run(struct hotplug_msg *msg) { + char *const argv[] = { "udev", msg->subsystem, NULL }; pid_t pid; pid = fork(); @@ -132,7 +132,7 @@ static void udev_run(struct hotplug_msg *msg) /* child */ close(udevsendsock); logging_close(); - execle(udev_bin, "udev", msg->subsystem, NULL, msg->envp); + execve(udev_bin, argv, msg->envp); dbg("exec of child failed"); _exit(1); break; @@ -150,22 +150,40 @@ static void udev_run(struct hotplug_msg *msg) } } -/* returns already running task with devpath */ +/* returns still running task for the same event sequence */ static struct hotplug_msg *running_with_devpath(struct hotplug_msg *msg) { struct hotplug_msg *loop_msg; + int i; + list_for_each_entry(loop_msg, &running_list, list) { if (loop_msg->devpath == NULL || msg->devpath == NULL) continue; - if (strcmp(loop_msg->devpath, msg->devpath) == 0) - return loop_msg; + /* is a parent or child device event still running */ + for (i = 0; i < DEVPATH_SIZE; i++) { + if (loop_msg->devpath[i] == '\0' || msg->devpath[i] == '\0') + return loop_msg; + + if (loop_msg->devpath[i] != msg->devpath[i]) + break; + } + + /* is the physical device event still running on an add sequence */ + if (msg->physdevpath && msg->action && strcmp(msg->action, "add") == 0) + for (i = 0; i < DEVPATH_SIZE; i++) { + if (loop_msg->devpath[i] == '\0' || msg->physdevpath[i] == '\0') + return loop_msg; + + if (loop_msg->devpath[i] != msg->physdevpath[i]) + break; + } } return NULL; } -/* exec queue management routine executes the events and delays events for the same devpath */ +/* exec queue management routine executes the events and serializes events in the same sequence */ static void exec_queue_manager(void) { struct hotplug_msg *loop_msg; @@ -180,8 +198,8 @@ static void exec_queue_manager(void) udev_run(loop_msg); dbg("moved seq %llu to running list", loop_msg->seqnum); } else { - dbg("delay seq %llu, cause seq %llu already working on '%s'", - loop_msg->seqnum, msg->seqnum, msg->devpath); + dbg("delay seq %llu (%s), cause seq %llu (%s) is still running", + loop_msg->seqnum, loop_msg->devpath, msg->seqnum, msg->devpath); } } } @@ -291,7 +309,7 @@ static void handle_udevsend_msg(int sock) /* copy environment buffer and reconstruct envp */ memcpy(msg->envbuf, usend_msg.envbuf, envbuf_size); bufpos = 0; - for (i = 0; (bufpos < envbuf_size) && (i < HOTPLUG_NUM_ENVP-1); i++) { + for (i = 0; (bufpos < envbuf_size) && (i < HOTPLUG_NUM_ENVP-2); i++) { int keylen; char *key; @@ -313,7 +331,11 @@ static void handle_udevsend_msg(int sock) if (strncmp(key, "SEQNUM=", 7) == 0) msg->seqnum = strtoull(&key[7], NULL, 10); + + if (strncmp(key, "PHYSDEVPATH=", 12) == 0) + msg->physdevpath = &key[12]; } + msg->envp[i++] = "UDEVD_EVENT=1"; msg->envp[i] = NULL; /* if no seqnum is given, we move straight to exec queue */