Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:philipsb:newer-kernels-on-sle10
udev
udev-trigger-use-qsort
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File udev-trigger-use-qsort of Package udev
diff --git a/udev/udevadm-trigger.c b/udev/udevadm-trigger.c index f0535f5..71a1894 100644 --- a/udev/udevadm-trigger.c +++ b/udev/udevadm-trigger.c @@ -37,7 +37,6 @@ static int verbose; static int dry_run; -LIST_HEAD(device_list); LIST_HEAD(filter_subsystem_match_list); LIST_HEAD(filter_subsystem_nomatch_list); LIST_HEAD(filter_attr_match_list); @@ -46,6 +45,75 @@ static int sock = -1; static struct sockaddr_un saddr; static socklen_t saddrlen; +struct syspath { + char *syspath; + size_t len; +}; + +static struct syspath *devices; +static unsigned int devices_cur; +static unsigned int devices_max; + +static void syspath_cleanup(void) +{ + unsigned int i; + + for (i = 0; i < devices_cur; i++) + free(devices[i].syspath); + free(devices); + devices = NULL; + devices_cur = 0; + devices_max = 0; +} + +static int syspath_add(const char *syspath) +{ + char *path; + struct syspath *entry; + + /* double array size if needed */ + if (devices_cur >= devices_max) { + struct syspath *buf; + unsigned int add; + + add = devices_max; + if (add < 1024) + add = 1024; + buf = realloc(devices, (devices_max + add) * sizeof(struct syspath)); + if (buf == NULL) + return -ENOMEM; + devices = buf; + devices_max += add; + } + + path = strdup(syspath); + if (path == NULL) + return -ENOMEM; + entry = &devices[devices_cur]; + entry->syspath = path; + entry->len = strlen(path); + devices_cur++; + return 0; +} + +static int syspath_cmp(const void *p1, const void *p2) +{ + const struct syspath *path1 = p1; + const struct syspath *path2 = p2; + size_t len; + int ret; + + len = MIN(path1->len, path2->len); + ret = memcmp(path1->syspath, path2->syspath, len); + if (ret == 0) { + if (path1->len < path2->len) + ret = -1; + else if (path1->len > path2->len) + ret = 1; + } + return ret; +} + /* devices that should run last cause of their dependencies */ static int delay_device(const char *devpath) { @@ -87,7 +155,7 @@ static int device_list_insert(struct udev *udev, const char *path) if (util_resolve_sys_link(udev, devpath, sizeof(devpath)) != 0) return -1; - name_list_add(udev, &device_list, devpath, 1); + syspath_add(devpath); return 0; } @@ -238,29 +306,44 @@ static int pass_to_socket(struct udev *udev, const char *devpath, const char *ac static void exec_list(struct udev *udev, const char *action, const char *env) { - struct name_entry *loop_device; - struct name_entry *tmp_device; + unsigned int i; + unsigned int max; + struct syspath *prev = NULL; + + qsort(devices, devices_cur, sizeof(struct syspath), syspath_cmp); - list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) { - if (delay_device(loop_device->name)) + max = devices_cur; + for (i = 0; i < max; i++) { + struct syspath *entry = &devices[i]; + + /* skip duplicated entries */ + if (prev != NULL && + entry->len == prev->len && + memcmp(entry->syspath, prev->syspath, entry->len) == 0) + continue; + prev = entry; + + /* skip to be delayed devices, and add them to the end of the list */ + if (delay_device(entry->syspath)) { + syspath_add(entry->syspath); continue; + } + if (sock >= 0) - pass_to_socket(udev, loop_device->name, action, env); + pass_to_socket(udev, entry->syspath, action, env); else - trigger_uevent(udev, loop_device->name, action); - list_del(&loop_device->node); - free(loop_device); + trigger_uevent(udev, entry->syspath, action); } + /* add and cleanup delayed devices from end of list */ + for (i = max; i < devices_cur; i++) { + struct syspath *entry = &devices[i]; - /* trigger remaining delayed devices */ - list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) { if (sock >= 0) - pass_to_socket(udev, loop_device->name, action, env); + pass_to_socket(udev, entry->syspath, action, env); else - trigger_uevent(udev, loop_device->name, action); - list_del(&loop_device->node); - free(loop_device); + trigger_uevent(udev, entry->syspath, action); } + syspath_cleanup(); } static int subsystem_filtered(const char *subsystem)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor