aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>2004-11-13 12:36:47 +0100
committerGreg KH <gregkh@suse.de>2005-04-26 22:27:34 -0700
commitd402af7d71be3b89eac5877a425f2c6bce5c4f3d (patch)
tree6a58878421d250fd1c2d45409f35b20d57320a36
parent2092fbcdebf5313f29b43bdaa57a22baf0c0269f (diff)
downloadudev-d402af7d71be3b89eac5877a425f2c6bce5c4f3d.tar.gz
[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.
-rw-r--r--udev_lib.c24
-rw-r--r--udev_lib.h2
-rw-r--r--udev_sysfs.c63
-rw-r--r--udev_sysfs.h10
-rw-r--r--wait_for_sysfs.c13
5 files changed, 77 insertions, 35 deletions
diff --git a/udev_lib.c b/udev_lib.c
index 6807f817..a3fab963 100644
--- a/udev_lib.c
+++ b/udev_lib.c
@@ -28,6 +28,7 @@
#include <dirent.h>
#include <sys/stat.h>
#include <sys/mman.h>
+#include <sys/utsname.h>
#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 2bc9ba82..80dc49cd 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 a11c430d..1953dd77 100644
--- a/udev_sysfs.c
+++ b/udev_sysfs.c
@@ -28,14 +28,13 @@
#include <errno.h>
#include <sys/stat.h>
-#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 922db1be..98ff53e1 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 42b9d383..84a25adb 100644
--- a/wait_for_sysfs.c
+++ b/wait_for_sysfs.c
@@ -32,10 +32,11 @@
#include <errno.h>
#include <sys/stat.h>
-#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);