From d402af7d71be3b89eac5877a425f2c6bce5c4f3d Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Sat, 13 Nov 2004 12:36:47 +0100 Subject: [PATCH] [PATCH] don't wait for sysfs if the kernel(2.6.10-rc2) tells us what not to expect Newer kernels will tell us if we should wait for the "device" or the "bus" link. So don't waste the time with our lists or wait for the timeout. --- udev_lib.c | 24 ++++++++++++++++++ udev_lib.h | 2 +- udev_sysfs.c | 63 +++++++++++++++++++++++++++++------------------- udev_sysfs.h | 10 +++++--- wait_for_sysfs.c | 13 +++++----- 5 files changed, 77 insertions(+), 35 deletions(-) diff --git a/udev_lib.c b/udev_lib.c index 6807f817a..a3fab9632 100644 --- a/udev_lib.c +++ b/udev_lib.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "udev.h" #include "logging.h" @@ -72,6 +73,29 @@ void udev_set_values(struct udevice *udev, const char* devpath, udev->type = get_device_type(devpath, subsystem); } +int kernel_release_satisfactory(int version, int patchlevel, int sublevel) +{ + static struct utsname uts; + static int kversion = 0; + static int kpatchlevel; + static int ksublevel; + + if (kversion == 0) { + if (uname(&uts) != 0) + return -1; + + if (sscanf (uts.release, "%u.%u.%u", &kversion, &kpatchlevel, &ksublevel) != 3) { + kversion = 0; + return -1; + } + } + + if (kversion >= version && kpatchlevel >= patchlevel && ksublevel >= sublevel) + return 1; + else + return 0; +} + int create_path(const char *path) { char p[NAME_SIZE]; diff --git a/udev_lib.h b/udev_lib.h index 2bc9ba82a..80dc49cd5 100644 --- a/udev_lib.h +++ b/udev_lib.h @@ -79,12 +79,12 @@ do { \ extern char get_device_type(const char *path, const char *subsystem); extern void udev_set_values(struct udevice *udev, const char* devpath, const char *subsystem, const char* action); +extern int kernel_release_satisfactory(int version, int patchlevel, int sublevel); extern int create_path(const char *path); extern int file_map(const char *filename, char **buf, size_t *bufsize); extern void file_unmap(char *buf, size_t bufsize); extern size_t buf_get_line(char *buf, size_t buflen, size_t cur); extern void no_trailing_slash(char *path); - typedef int (*file_fnct_t)(const char *filename, void *data); extern int call_foreach_file(file_fnct_t fnct, const char *dirname, const char *suffix, void *data); diff --git a/udev_sysfs.c b/udev_sysfs.c index a11c430df..1953dd777 100644 --- a/udev_sysfs.c +++ b/udev_sysfs.c @@ -28,14 +28,13 @@ #include #include -#include "logging.h" +#include "libsysfs/sysfs/libsysfs.h" #include "udev_version.h" #include "udev_sysfs.h" -#include "libsysfs/sysfs/libsysfs.h" +#include "udev_lib.h" +#include "logging.h" -/* list of subsystem specific files - * NULL if there is no file to wait for - */ +/* list of subsystem specific files, NULL if there is no file to wait for */ static struct subsystem_file { char *subsystem; char *file; @@ -204,6 +203,13 @@ static int class_device_expect_no_device_link(struct sysfs_class_device *class_d struct class_device *classdevice; int len; + /* the kernel may tell us what to wait for */ + if (kernel_release_satisfactory(2,6,10) > 0) + if (getenv("PHYSDEVPATH") == NULL) { + dbg("the kernel says, that there is no physical device for '%s'", class_dev->path); + return 1; + } + for (classdevice = class_device; classdevice->subsystem != NULL; classdevice++) { if (strcmp(class_dev->classname, classdevice->subsystem) == 0) { /* see if no device in this class is expected to have a device-link */ @@ -229,7 +235,7 @@ static int class_device_expect_no_device_link(struct sysfs_class_device *class_d return 0; } -/* skip waiting for the bus */ +/* skip waiting for the bus of the devices device */ static int class_device_expect_no_bus(struct sysfs_class_device *class_dev) { static char *devices_without_bus[] = { @@ -250,14 +256,14 @@ static int class_device_expect_no_bus(struct sysfs_class_device *class_dev) return 0; } -/* wait for the bus and for a bus specific file to show up */ -int wait_for_bus_device(struct sysfs_device *devices_dev, +/* wait for a devices device specific file to show up */ +int wait_for_devices_device(struct sysfs_device *devices_dev, const char **error) { - static struct bus_file { + static struct device_file { char *bus; char *file; - } bus_files[] = { + } device_files[] = { { .bus = "scsi", .file = "vendor" }, { .bus = "usb", .file = "idVendor" }, { .bus = "usb", .file = "iInterface" }, @@ -272,9 +278,16 @@ int wait_for_bus_device(struct sysfs_device *devices_dev, { .bus = "ieee1394", .file = "address" }, { NULL, NULL } }; - struct bus_file *busfile; + struct device_file *devicefile; int loop; + /* the kernel may tell us what to wait for */ + if (kernel_release_satisfactory(2,6,10) > 0) + if (getenv("PHYSDEVBUS") == NULL) { + dbg("the kernel says, that there is no bus for '%s'", devices_dev->path); + return 0; + } + /* wait for the bus device link to the devices device */ loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND; while (--loop) { @@ -291,22 +304,22 @@ int wait_for_bus_device(struct sysfs_device *devices_dev, } dbg("bus device link found for bus '%s'", devices_dev->bus); - /* wait for a bus specific file to show up */ + /* wait for a bus device specific file to show up */ loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND; while (--loop) { int found_bus_type = 0; - for (busfile = bus_files; busfile->bus != NULL; busfile++) { - if (strcmp(devices_dev->bus, busfile->bus) == 0) { + for (devicefile = device_files; devicefile->bus != NULL; devicefile++) { + if (strcmp(devices_dev->bus, devicefile->bus) == 0) { char filename[SYSFS_PATH_MAX]; struct stat stats; found_bus_type = 1; - snprintf(filename, SYSFS_PATH_MAX-1, "%s/%s", devices_dev->path, busfile->file); - dbg("looking at bus '%s' for specific file '%s'", devices_dev->bus, filename); + snprintf(filename, SYSFS_PATH_MAX-1, "%s/%s", devices_dev->path, devicefile->file); + dbg("looking at bus '%s' device for specific file '%s'", devices_dev->bus, filename); if (stat(filename, &stats) == 0) { - dbg("bus '%s' specific file '%s' found", devices_dev->bus, busfile->file); + dbg("bus '%s' device specific file '%s' found", devices_dev->bus, devicefile->file); return 0; } } @@ -321,14 +334,14 @@ int wait_for_bus_device(struct sysfs_device *devices_dev, usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND); } - dbg("error: getting bus '%s' specific file '%s'", devices_dev->bus, busfile->file); + dbg("error: getting '%s' device specific file '%s'", devices_dev->bus, devicefile->file); if (error) - *error = "bus specific file unavailable"; + *error = "bus device specific file unavailable"; return -1; } -struct sysfs_class_device *open_class_device_wait(const char *path) +struct sysfs_class_device *wait_class_device_open(const char *path) { struct sysfs_class_device *class_dev; int loop; @@ -358,7 +371,7 @@ int wait_for_class_device(struct sysfs_class_device *class_dev, /* skip devices without devices-link */ if (class_device_expect_no_device_link(class_dev)) { dbg("no device symlink expected for '%s', ", class_dev->name); - return -ENODEV; + return 0; } /* the symlink may be on the parent device */ @@ -388,16 +401,16 @@ int wait_for_class_device(struct sysfs_class_device *class_dev, } dbg("device symlink found pointing to '%s'", devices_dev->path); - /* wait for the bus value */ + /* wait for the devices device */ if (class_device_expect_no_bus(class_dev)) { dbg("no bus device expected for '%s', ", class_dev->classname); return 0; - } else { - return wait_for_bus_device(devices_dev, error); } + + return wait_for_devices_device(devices_dev, error); } -struct sysfs_device *open_devices_device_wait(const char *path) +struct sysfs_device *wait_devices_device_open(const char *path) { struct sysfs_device *devices_dev; int loop; diff --git a/udev_sysfs.h b/udev_sysfs.h index 922db1be7..98ff53e11 100644 --- a/udev_sysfs.h +++ b/udev_sysfs.h @@ -28,9 +28,13 @@ #define WAIT_LOOP_PER_SECOND 20 extern int subsystem_expect_no_dev(const char *subsystem); -extern int wait_for_bus_device(struct sysfs_device *devices_dev, const char **error); + +/* /sys/class /sys/block devices */ +extern struct sysfs_class_device *wait_class_device_open(const char *path); extern int wait_for_class_device(struct sysfs_class_device *class_dev, const char **error); -extern struct sysfs_class_device *open_class_device_wait(const char *path); -extern struct sysfs_device *open_devices_device_wait(const char *path); + +/* /sys/devices devices */ +extern struct sysfs_device *wait_devices_device_open(const char *path); +extern int wait_for_devices_device(struct sysfs_device *devices_dev, const char **error); #endif /* _UDEV_SYSFS_H_ */ diff --git a/wait_for_sysfs.c b/wait_for_sysfs.c index 42b9d383d..84a25adb9 100644 --- a/wait_for_sysfs.c +++ b/wait_for_sysfs.c @@ -32,10 +32,11 @@ #include #include -#include "logging.h" +#include "libsysfs/sysfs/libsysfs.h" +#include "udev_lib.h" #include "udev_version.h" #include "udev_sysfs.h" -#include "libsysfs/sysfs/libsysfs.h" +#include "logging.h" #ifdef LOG unsigned char logname[LOGNAME_SIZE]; @@ -106,7 +107,7 @@ int main(int argc, char *argv[], char *envp[]) } /* open the class device we are called for */ - class_dev = open_class_device_wait(filename); + class_dev = wait_class_device_open(filename); if (!class_dev) { dbg("error: class device unavailable (probably remove has beaten us)"); goto exit; @@ -132,15 +133,15 @@ int main(int argc, char *argv[], char *envp[]) filename[SYSFS_PATH_MAX-1] = '\0'; /* open the path we are called for */ - devices_dev = open_devices_device_wait(filename); + devices_dev = wait_devices_device_open(filename); if (!devices_dev) { dbg("error: devices device unavailable (probably remove has beaten us)"); goto exit; } dbg("devices device opened '%s'", filename); - /* wait for the bus value */ - wait_for_bus_device(devices_dev, &error); + /* wait for the devices device */ + wait_for_devices_device(devices_dev, &error); sysfs_close_device(devices_dev); -- 2.30.2