From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kay Sievers Date: Thu, 14 Oct 2004 02:39:13 +0000 Subject: remove sleeps from udev as it is external now Message-Id: <20041014023913.GA13748@vrfy.org> MIME-Version: 1 Content-Type: multipart/mixed; boundary="J2SCkAp4GZ/dPZZf" List-Id: To: linux-hotplug@vger.kernel.org --J2SCkAp4GZ/dPZZf Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here we remove all the sysfs sleep loops from udev as wait_for_sysfs will do this for us and any other hotplug user. We still keep a small blacklist of subsystems we don't care about but any missing entry here will no longer lead to a spinning udev waiting for files. Thanks, Kay --J2SCkAp4GZ/dPZZf Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="udev-kill-sleep-01.patch" ===== namedev.c 1.151 vs edited ===== --- 1.151/namedev.c 2004-10-14 01:04:51 +02:00 +++ edited/namedev.c 2004-10-14 03:26:30 +02:00 @@ -346,69 +346,6 @@ } } -/* - * Note, we can have multiple files for different busses in here due - * to the mess that USB has for its device tree... - */ -static struct bus_file { - char *bus; - char *file; -} bus_files[] = { - { .bus = "scsi", .file = "vendor" }, - { .bus = "usb", .file = "idVendor" }, - { .bus = "usb", .file = "iInterface" }, - { .bus = "usb-serial", .file = "detach_state" }, - { .bus = "ide", .file = "detach_state" }, - { .bus = "pci", .file = "vendor" }, - {} -}; - -static void wait_for_device_to_initialize(struct sysfs_device *sysfs_device) -{ - /* sleep until we see the file for this specific bus type show up this - * is needed because we can easily out-run the kernel in looking for - * these files before the paticular subsystem has created them in the - * sysfs tree properly. - * - * And people thought that the /sbin/hotplug event system was going to - * be slow, poo on you for arguing that before even testing it... - */ - struct bus_file *b = &bus_files[0]; - struct sysfs_attribute *tmpattr; - int found = 0; - int loop = WAIT_FOR_FILE_SECONDS * WAIT_FOR_FILE_RETRY_FREQ; - - while (1) { - if (b->bus == NULL) { - if (!found) - break; - /* give the kernel a chance to create the file */ - usleep(1000 * 1000 / WAIT_FOR_FILE_RETRY_FREQ); - --loop; - if (loop == 0) - break; - b = &bus_files[0]; - } - if (strcmp(sysfs_device->bus, b->bus) == 0) { - found = 1; - dbg("looking for file '%s' on bus '%s'", b->file, b->bus); - tmpattr = sysfs_get_device_attr(sysfs_device, b->file); - if (tmpattr) { - /* found it! */ - goto exit; - } - dbg("can't find '%s' file", b->file); - } - ++b; - } - if (!found) - dbg("did not find bus type '%s' on list of bus_id_files, " - "please report to ", - sysfs_device->bus); -exit: - return; /* here to prevent compiler warning... */ -} - static void fix_kernel_name(struct udevice *udev) { char *temp = udev->kernel_name; @@ -650,108 +587,6 @@ return 0; } -static int whitelist_search(struct sysfs_class_device *class_dev) -{ - char *sysblock = "/sys/block"; - int i; - - static char *list[] = { - "nb", - "ram", - "loop", - "fd", - "md", - "dos_cd", - "double", - "flash", - "msd", - "rflash", - "rom", - "rrom", - "sbpcd", - "pcd", - "pf", - "scd", - "ubd", - NULL, - }; - - if (strncmp(class_dev->path, sysblock, strlen(sysblock))) - return 0; - - for (i=0; list[i] != NULL; i++) - if (!strncmp(class_dev->name, list[i], strlen(list[i]))) - return 1; - - return 0; -} - -static struct sysfs_device *get_sysfs_device(struct sysfs_class_device *class_dev) -{ - struct sysfs_device *sysfs_device; - struct sysfs_class_device *class_dev_parent; - int loop; - - /* Figure out where the device symlink is at. For char devices this will - * always be in the class_dev->path. But for block devices, it's different. - * The main block device will have the device symlink in it's path, but - * all partitions have the symlink in its parent directory. - * But we need to watch out for block devices that do not have parents, yet - * look like a partition (fd0, loop0, etc.) They all do not have a device - * symlink yet. We do sit and spin on waiting for them right now unless - * they happen to be in the whitelist in which case we exit. - */ - class_dev_parent = sysfs_get_classdev_parent(class_dev); - if (class_dev_parent != NULL) - dbg("given class device has a parent, use this instead"); - - loop = WAIT_FOR_FILE_SECONDS * WAIT_FOR_FILE_RETRY_FREQ; - while (loop--) { - if (udev_sleep) { - if (whitelist_search(class_dev)) { - sysfs_device = NULL; - goto exit; - } - usleep(1000 * 1000 / WAIT_FOR_FILE_RETRY_FREQ); - } - - if (class_dev_parent) - sysfs_device = sysfs_get_classdev_device(class_dev_parent); - else - sysfs_device = sysfs_get_classdev_device(class_dev); - if (sysfs_device != NULL) - goto device_found; - } - dbg("timed out waiting for device symlink, continuing on anyway..."); - -device_found: - /* We have another issue with just the wait above - the sysfs part of - * the kernel may not be quick enough to have created the link to the - * device under the "bus" subsystem. Due to this, the sysfs_device->bus - * will not contain the actual bus name :( - */ - if (sysfs_device) { - if (sysfs_device->bus[0] != '\0') - goto bus_found; - - while (loop--) { - if (udev_sleep) - usleep(1000 * 1000 / WAIT_FOR_FILE_RETRY_FREQ); - sysfs_get_device_bus(sysfs_device); - - if (sysfs_device->bus[0] != '\0') - goto bus_found; - } - dbg("timed out waiting to find the device bus, continuing on anyway"); - goto exit; -bus_found: - dbg("device %s is registered with bus '%s'", - sysfs_device->name, sysfs_device->bus); - } -exit: - return sysfs_device; -} - static int match_rule(struct config_device *dev, struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device) { while (1) { @@ -859,6 +694,7 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *udev) { + struct sysfs_class_device *class_dev_parent; struct sysfs_device *sysfs_device = NULL; struct config_device *dev; struct perm_device *perm; @@ -866,17 +702,26 @@ char *pos; udev->mode = 0; + dbg("class_dev->name='%s'", class_dev->name); + + /* Figure out where the "device"-symlink is at. For char devices this will + * always be in the class_dev->path. On block devices, only the main block + * device will have the device symlink in it's path. All partition devices + * need to look at the symlink in its parent directory. + */ + class_dev_parent = sysfs_get_classdev_parent(class_dev); + if (class_dev_parent != NULL) { + dbg("given class device has a parent, use this instead"); + sysfs_device = sysfs_get_classdev_device(class_dev_parent); + } else { + sysfs_device = sysfs_get_classdev_device(class_dev); + } - /* find the sysfs_device associated with this class device */ - sysfs_device = get_sysfs_device(class_dev); if (sysfs_device) { - dbg("sysfs_device->path='%s'", sysfs_device->path); - dbg("sysfs_device->bus_id='%s'", sysfs_device->bus_id); - dbg("sysfs_device->bus='%s'", sysfs_device->bus); + dbg("found /device-device: path='%s', bus_id='%s', bus='%s'", + sysfs_device->path, sysfs_device->bus_id, sysfs_device->bus); strfieldcpy(udev->bus_id, sysfs_device->bus_id); - wait_for_device_to_initialize(sysfs_device); } - dbg("class_dev->name = '%s'", class_dev->name); strfieldcpy(udev->kernel_name, class_dev->name); fix_kernel_name(udev); ===== udev.8.in 1.60 vs edited ===== --- 1.60/udev.8.in 2004-09-07 13:12:59 +02:00 +++ edited/udev.8.in 2004-10-14 03:14:12 +02:00 @@ -20,13 +20,6 @@ .B udev config file. .TP -.B UDEV_NO_SLEEP -The default behavior of -.B udev -is to wait until all the sysfs files of the device chain are populated. If set, -.B udev -will continue, regardless of the state of the device representation. -.TP .B UDEV_NO_DEVD The default behavior of .B udev ===== udev.c 1.66 vs edited ===== --- 1.66/udev.c 2004-10-14 00:22:37 +02:00 +++ edited/udev.c 2004-10-14 04:09:31 +02:00 @@ -75,14 +75,34 @@ } } -static char *subsystem_blacklist[] = { - "scsi_host", - "scsi_device", - "usb_host", - "pci_bus", - "pcmcia_socket", - "" -}; +/* list of subsystems we don't care about. not listing such systems here + * is not critical, but it makes it faster as we don't look for the "dev" file + */ +static int subsystem_without_dev(const char *subsystem) +{ + char *subsystem_blacklist[] = { + "scsi_host", + "scsi_device", + "usb_host", + "pci_bus", + "pcmcia_socket", + "bluetooth", + "i2c-adapter", + "pci_bus", + "ieee1394", + "ieee1394_host", + "ieee1394_node", + NULL + }; + char **subsys; + + for (subsys = subsystem_blacklist; *subsys != NULL; subsys++) { + if (strcmp(subsystem, *subsys) == 0) + return 1; + } + + return 0; +} int main(int argc, char *argv[], char *envp[]) { @@ -92,7 +112,6 @@ char *action; char *devpath = ""; char *subsystem = ""; - int i; int retval = -EINVAL; enum { ADD, @@ -143,20 +162,16 @@ } /* skip blacklisted subsystems */ - i = 0; - while (subsystem_blacklist[i][0] != '\0') { - if (strcmp(subsystem, subsystem_blacklist[i]) == 0) { - dbg("don't care about '%s' devices", subsystem); - goto exit; - } - i++; - } + if (subsystem_without_dev(subsystem)) { + dbg("don't care about '%s' devices", subsystem); + exit(0); + }; } /* set signal handlers */ act.sa_handler = (void (*) (int))sig_handler; sigemptyset (&act.sa_mask); - /* alarm must interrupt syscalls*/ + /* alarm must not restart syscalls*/ sigaction(SIGALRM, &act, NULL); sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); @@ -172,7 +187,6 @@ case UDEVSTART: dbg("udevstart"); namedev_init(); - udev_sleep = 0; retval = udev_start(); break; case ADD: ===== udev.h 1.63 vs edited ===== --- 1.63/udev.h 2004-10-13 23:16:25 +02:00 +++ edited/udev.h 2004-10-14 03:16:33 +02:00 @@ -27,8 +27,6 @@ #include "libsysfs/sysfs/libsysfs.h" #define ALARM_TIMEOUT 30 -#define WAIT_FOR_FILE_SECONDS 10 -#define WAIT_FOR_FILE_RETRY_FREQ 10 #define COMMENT_CHARACTER '#' #define NAME_SIZE 256 @@ -90,7 +88,6 @@ extern char default_owner_str[OWNER_SIZE]; extern char default_group_str[GROUP_SIZE]; extern int udev_log; -extern int udev_sleep; extern int udev_dev_d; #endif ===== udev_add.c 1.76 vs edited ===== --- 1.76/udev_add.c 2004-10-13 22:31:48 +02:00 +++ edited/udev_add.c 2004-10-14 04:32:18 +02:00 @@ -52,14 +52,9 @@ #include "selinux.h" -/* - * Right now the major/minor of a device is stored in a file called - * "dev" in sysfs. - * The number is stored as: - * MM:mm - * MM is the major - * mm is the minor - * The value is in decimal. +/* + * the major/minor of a device is stored in a file called "dev" + * The number is stored in decimal values in the format: M:m */ static int get_major_minor(struct sysfs_class_device *class_dev, struct udevice *udev) { @@ -345,35 +340,6 @@ return class_dev; } -/* wait for the "dev" file to show up in the directory in sysfs. - * If it doesn't happen in about 10 seconds, give up. - */ -static int sleep_for_file(const char *path, char* file) -{ - char filename[SYSFS_PATH_MAX + 6]; - int loop = WAIT_FOR_FILE_SECONDS * WAIT_FOR_FILE_RETRY_FREQ; - int retval; - - strfieldcpy(filename, sysfs_path); - strfieldcat(filename, path); - strfieldcat(filename, file); - - while (loop--) { - struct stat buf; - - dbg("looking for '%s'", filename); - retval = stat(filename, &buf); - if (retval == 0) - goto exit; - - /* sleep to give the kernel a chance to create the dev file */ - usleep(1000 * 1000 / WAIT_FOR_FILE_RETRY_FREQ); - } - retval = -ENODEV; -exit: - return retval; -} - static int rename_net_if(struct udevice *dev, int fake) { int sk; @@ -408,25 +374,11 @@ struct udevice dev; char devpath[DEVPATH_SIZE]; char *pos; - int retval; + int retval = 0; memset(&dev, 0x00, sizeof(dev)); dev.type = get_device_type(path, subsystem); - switch (dev.type) { - case 'b': - case 'c': - retval = sleep_for_file(path, "/dev"); - break; - - case 'n': - retval = sleep_for_file(path, "/address"); - break; - - default: - dbg("unknown device type '%c'", dev.type); - return -1; - } class_dev = get_class_dev(path); if (class_dev == NULL) @@ -435,8 +387,8 @@ if (dev.type == 'b' || dev.type == 'c') { retval = get_major_minor(class_dev, &dev); if (retval != 0) { - dbg("get_major_minor failed"); - goto exit; + dbg("no dev-file found, do nothing"); + goto close; } } @@ -484,6 +436,7 @@ exit: selinux_restore(); +close: sysfs_close_class_device(class_dev); return retval; ===== udev_config.c 1.21 vs edited ===== --- 1.21/udev_config.c 2004-09-14 16:02:10 +02:00 +++ edited/udev_config.c 2004-10-14 03:13:13 +02:00 @@ -50,7 +50,6 @@ char default_owner_str[OWNER_SIZE]; char default_group_str[GROUP_SIZE]; int udev_log; -int udev_sleep; int udev_dev_d; @@ -78,11 +77,6 @@ strfieldcpy(udev_rules_filename, UDEV_RULES_FILE); strfieldcpy(udev_permissions_filename, UDEV_PERMISSION_FILE); udev_log = string_is_true(UDEV_LOG_DEFAULT); - - udev_sleep = 1; - env = getenv("UDEV_NO_SLEEP"); - if (env && string_is_true(env)) - udev_sleep = 0; udev_dev_d = 1; env = getenv("UDEV_NO_DEVD"); --J2SCkAp4GZ/dPZZf-- ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel