aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--RELEASE-NOTES9
-rw-r--r--udev.c1
-rw-r--r--udev.h1
-rw-r--r--udev_add.c1
-rw-r--r--udev_device.c1
-rw-r--r--udev_event.c39
-rw-r--r--udev_rules.c5
-rw-r--r--udev_sysfs.c298
-rw-r--r--udev_sysfs.h40
-rw-r--r--udevstart.c1
-rw-r--r--udevtest.c1
12 files changed, 44 insertions, 355 deletions
diff --git a/Makefile b/Makefile
index c68db3b9..de305cb9 100644
--- a/Makefile
+++ b/Makefile
@@ -61,7 +61,6 @@ HEADERS = \
udev_utils.h \
udev_rules.h \
udev_db.h \
- udev_sysfs.h \
logging.h \
udev_libc_wrapper.h \
udev_selinux.h \
@@ -73,7 +72,6 @@ UDEV_OBJS = \
udev_config.o \
udev_add.o \
udev_remove.o \
- udev_sysfs.o \
udev_db.o \
udev_rules.o \
udev_rules_parse.o \
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 80627038..18e2829b 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,3 +1,12 @@
+udev 076
+========
+All built-in logic to work around bad sysfs timing is removed with this
+version. The need to wait for sysfs files is almost fixed with a kernel
+version that doesn't work with this udev version anyway. Until we fix
+the timing of the "bus" link creation, the former integrated logic should
+be emulated by a rule placed before all other rules:
+ ACTION=="add", DEVPATH=="/devices/*", ENV{PHYSDEVBUS}=="?*", WAIT_FOR_SYSFS="bus"
+
udev 075
========
Silent a too verbose error logging for the old hotplug.d/ dev.d/
diff --git a/udev.c b/udev.c
index 17867180..f2d6f665 100644
--- a/udev.c
+++ b/udev.c
@@ -34,7 +34,6 @@
#include "udev_libc_wrapper.h"
#include "udev.h"
#include "udev_utils.h"
-#include "udev_sysfs.h"
#include "udev_version.h"
#include "udev_rules.h"
#include "logging.h"
diff --git a/udev.h b/udev.h
index ecc0a44f..e61b692d 100644
--- a/udev.h
+++ b/udev.h
@@ -84,6 +84,7 @@ struct udevice {
extern int udev_init_device(struct udevice *udev, const char* devpath, const char *subsystem, const char *action);
extern void udev_cleanup_device(struct udevice *udev);
+extern dev_t get_devt(struct sysfs_class_device *class_dev);
extern int udev_process_event(struct udev_rules *rules, struct udevice *udev);
extern int udev_add_device(struct udevice *udev, struct sysfs_class_device *class_dev);
extern int udev_remove_device(struct udevice *udev);
diff --git a/udev_add.c b/udev_add.c
index f4ad55a8..1a224a17 100644
--- a/udev_add.c
+++ b/udev_add.c
@@ -37,7 +37,6 @@
#include "udev_libc_wrapper.h"
#include "udev.h"
#include "udev_utils.h"
-#include "udev_sysfs.h"
#include "udev_version.h"
#include "logging.h"
#include "udev_rules.h"
diff --git a/udev_device.c b/udev_device.c
index ad6f7063..7821c91c 100644
--- a/udev_device.c
+++ b/udev_device.c
@@ -37,7 +37,6 @@
#include "udev.h"
#include "logging.h"
#include "udev_utils.h"
-#include "udev_sysfs.h"
#include "list.h"
diff --git a/udev_event.c b/udev_event.c
index b50fbf4c..353aff09 100644
--- a/udev_event.c
+++ b/udev_event.c
@@ -28,38 +28,62 @@
#include <ctype.h>
#include <dirent.h>
#include <syslog.h>
+#include <sys/stat.h>
+#include "libsysfs/sysfs/libsysfs.h"
#include "udev_libc_wrapper.h"
#include "udev.h"
#include "logging.h"
#include "udev_rules.h"
#include "udev_utils.h"
-#include "udev_sysfs.h"
#include "list.h"
+dev_t get_devt(struct sysfs_class_device *class_dev)
+{
+ struct sysfs_attribute *attr = NULL;
+ unsigned int major, minor;
+ char *maj, *min;
+
+ maj = getenv("MAJOR");
+ min = getenv("MINOR");
+
+ if (maj && min) {
+ major = atoi(maj);
+ minor = atoi(min);
+ } else {
+ attr = sysfs_get_classdev_attr(class_dev, "dev");
+ if (attr == NULL)
+ return 0;
+ dbg("dev='%s'", attr->value);
+
+ if (sscanf(attr->value, "%u:%u", &major, &minor) != 2)
+ return 0;
+ }
+
+ dbg("found major=%d, minor=%d", major, minor);
+ return makedev(major, minor);
+}
+
int udev_process_event(struct udev_rules *rules, struct udevice *udev)
{
int retval;
char path[PATH_SIZE];
- const char *error;
if (udev->type == DEV_BLOCK || udev->type == DEV_CLASS || udev->type == DEV_NET) {
/* handle device node */
if (strcmp(udev->action, "add") == 0) {
struct sysfs_class_device *class_dev;
- /* wait for sysfs of /sys/class /sys/block */
dbg("node add");
snprintf(path, sizeof(path), "%s%s", sysfs_path, udev->devpath);
path[sizeof(path)-1] = '\0';
- class_dev = wait_class_device_open(path);
+ class_dev = sysfs_open_class_device_path(path);
if (class_dev == NULL) {
dbg("open class device failed");
return 0;
}
dbg("opened class_dev->name='%s'", class_dev->name);
- wait_for_class_device(class_dev, &error);
/* get major/minor */
if (udev->type == DEV_BLOCK || udev->type == DEV_CLASS)
@@ -113,17 +137,16 @@ int udev_process_event(struct udev_rules *rules, struct udevice *udev)
} else if (udev->type == DEV_DEVICE && strcmp(udev->action, "add") == 0) {
struct sysfs_device *devices_dev;
- /* wait for sysfs of /sys/devices/ */
dbg("devices add");
snprintf(path, sizeof(path), "%s%s", sysfs_path, udev->devpath);
path[sizeof(path)-1] = '\0';
- devices_dev = wait_devices_device_open(path);
+ devices_dev = sysfs_open_device_path(path);
if (!devices_dev) {
dbg("devices device unavailable (probably remove has beaten us)");
return 0;
}
+
dbg("devices device opened '%s'", path);
- wait_for_devices_device(devices_dev, &error);
udev_rules_get_run(rules, udev, NULL, devices_dev);
sysfs_close_device(devices_dev);
if (udev->ignore_device) {
diff --git a/udev_rules.c b/udev_rules.c
index 137ad27d..a3100f8e 100644
--- a/udev_rules.c
+++ b/udev_rules.c
@@ -376,7 +376,7 @@ attr_found:
return 0;
}
-#define WAIT_LOOP_PER_SECOND 20
+#define WAIT_LOOP_PER_SECOND 50
static int wait_for_sysfs(struct udevice *udev, const char *file, int timeout)
{
char filename[PATH_SIZE];
@@ -392,9 +392,10 @@ static int wait_for_sysfs(struct udevice *udev, const char *file, int timeout)
info("file appeared after %i loops", (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
return 0;
}
+ info("wait for %i mseconds", 1000 / WAIT_LOOP_PER_SECOND);
usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
}
- info("waiting for '%s' failed", filename);
+ err("waiting for '%s' failed", filename);
return -1;
}
diff --git a/udev_sysfs.c b/udev_sysfs.c
deleted file mode 100644
index 71aa827d..00000000
--- a/udev_sysfs.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * udev_sysfs.c - sysfs linux kernel specific knowledge
- *
- * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
- * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-#include "libsysfs/sysfs/libsysfs.h"
-#include "udev_version.h"
-#include "udev_sysfs.h"
-#include "udev_utils.h"
-#include "logging.h"
-
-/* list of subsystem specific files, NULL if there is no file to wait for */
-dev_t get_devt(struct sysfs_class_device *class_dev)
-{
- struct sysfs_attribute *attr = NULL;
- unsigned int major, minor;
-
- attr = sysfs_get_classdev_attr(class_dev, "dev");
- if (attr == NULL)
- return 0;
- dbg("dev='%s'", attr->value);
-
- if (sscanf(attr->value, "%u:%u", &major, &minor) != 2)
- return 0;
- dbg("found major=%d, minor=%d", major, minor);
-
- return makedev(major, minor);
-}
-
-/* wait for a devices device specific file to show up */
-int wait_for_devices_device(struct sysfs_device *devices_dev,
- const char **error)
-{
- static const struct device_file {
- const char *bus;
- const char *file;
- } device_files[] = {
- { .bus = "scsi", .file = "vendor" },
- { .bus = "usb", .file = "idVendor" },
- { .bus = "usb", .file = "iInterface" },
- { .bus = "usb", .file = "bNumEndpoints" },
- { .bus = "usb-serial", .file = "bus" },
- { .bus = "ide", .file = "bus" },
- { .bus = "pci", .file = "vendor" },
- { .bus = "pci_express", .file = "bus" },
- { .bus = "platform", .file = "bus" },
- { .bus = "pcmcia", .file = "bus" },
- { .bus = "i2c", .file = "bus" },
- { .bus = "ieee1394", .file = "node_count" },
- { .bus = "ieee1394", .file = "nodeid" },
- { .bus = "ieee1394", .file = "address" },
- { .bus = "bttv-sub", .file = NULL },
- { .bus = "pnp", .file = "bus" },
- { .bus = "eisa", .file = "bus" },
- { .bus = "serio", .file = "bus" },
- { .bus = "pseudo", .file = "bus" },
- { .bus = "mmc", .file = "bus" },
- { .bus = "macio", .file = "bus" },
- { .bus = "of_platform", .file = "bus" },
- { .bus = "vio", .file = "bus" },
- { .bus = "ecard", .file = "bus" },
- { .bus = "sa1111-rab", .file = "bus" },
- { .bus = "amba", .file = "bus" },
- { .bus = "locomo-bus", .file = "bus" },
- { .bus = "logicmodule", .file = "bus" },
- { .bus = "parisc", .file = "bus" },
- { .bus = "ocp", .file = "bus" },
- { .bus = "dio", .file = "bus" },
- { .bus = "MCA", .file = "bus" },
- { .bus = "wl", .file = "bus" },
- { .bus = "ccwgroup", .file = "bus" },
- { .bus = "css", .file = "bus" },
- { .bus = "ccw", .file = "bus" },
- { .bus = "iucv", .file = "bus" },
- { NULL, NULL }
- };
- const struct device_file *devicefile = NULL;
- int loop;
-
- 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) {
- if (sysfs_get_device_bus(devices_dev) == 0)
- break;
-
- usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
- }
- if (loop == 0) {
- dbg("error: getting bus device link");
- if (error)
- *error = "no bus device link";
- return -1;
- }
- dbg("bus device link found for bus '%s'", devices_dev->bus);
-
- /* 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 (devicefile = device_files; devicefile->bus != NULL; devicefile++) {
- if (strcmp(devices_dev->bus, devicefile->bus) == 0) {
- char filename[PATH_SIZE];
- struct stat stats;
-
- if (devicefile->file == NULL) {
- dbg("bus '%s' has no file to wait for", devices_dev->bus);
- return 0;
- }
-
- found_bus_type = 1;
- snprintf(filename, sizeof(filename), "%s/%s", devices_dev->path, devicefile->file);
- filename[sizeof(filename)-1] = '\0';
- dbg("looking at bus '%s' device for specific file '%s'", devices_dev->bus, filename);
-
- if (stat(filename, &stats) == 0) {
- dbg("bus '%s' device specific file '%s' found", devices_dev->bus, devicefile->file);
- return 0;
- }
- }
- }
- if (found_bus_type == 0) {
- if (error)
- *error = "unknown bus";
- info("error: unknown bus, please report to "
- "<linux-hotplug-devel@lists.sourceforge.net> '%s'", devices_dev->bus);
- return -1;
- }
- usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
- }
-
- dbg("error: getting '%s' device specific file '%s'", devices_dev->bus, devicefile->file);
- if (error)
- *error = "bus device specific file unavailable";
- return -1;
-}
-
-
-struct sysfs_class_device *wait_class_device_open(const char *path)
-{
- struct sysfs_class_device *class_dev = NULL;
- int loop;
-
- loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
- while (--loop) {
- class_dev = sysfs_open_class_device_path(path);
- if (class_dev)
- break;
-
- usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
- }
-
- return class_dev;
-}
-
-int wait_for_class_device(struct sysfs_class_device *class_dev,
- const char **error)
-{
- const struct subsystem_file {
- const char *subsystem;
- const char *file;
- } subsystem_files[] = {
- { .subsystem = "net", .file = "ifindex" },
- { .subsystem = "scsi_host", .file = "unique_id" },
- { .subsystem = "pcmcia_socket", .file = "card_type" },
- { .subsystem = "bluetooth", .file = "address" },
- { .subsystem = "firmware", .file = "data" },
- { .subsystem = "fc_transport", .file = "port_id" },
- { .subsystem = "fc_host", .file = "port_id" },
- { .subsystem = "spi_transport", .file = "width" },
- { .subsystem = "spi_host", .file = "width" },
- { NULL, NULL }
- };
-
- const struct subsystem_file *subsys_file;
- struct sysfs_class_device *class_dev_parent;
- struct sysfs_device *devices_dev = NULL;
- char filename[PATH_SIZE];
- int loop;
-
- /* look if we want to wait for a file */
- for (subsys_file = subsystem_files; subsys_file->subsystem != NULL; subsys_file++)
- if (strcmp(class_dev->classname, subsys_file->subsystem) == 0)
- break;
-
- if (subsys_file->file == NULL) {
- dbg("class '%s' has no file to wait for", class_dev->classname);
- return 0;
- }
-
- snprintf(filename, sizeof(filename), "%s/%s", class_dev->path, subsys_file->file);
- filename[sizeof(filename)-1] = '\0';
- dbg("looking at class '%s' for specific file '%s'", class_dev->classname, filename);
-
- loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
- while (--loop) {
- struct stat stats;
-
- if (stat(class_dev->path, &stats) == -1) {
- dbg("'%s' now disappeared (probably remove has beaten us)", class_dev->path);
- return -ENODEV;
- }
-
- if (stat(filename, &stats) == 0) {
- dbg("class '%s' specific file '%s' found", class_dev->classname, subsys_file->file);
- return 0;
- }
-
- usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
- }
-
- dbg("error: getting class '%s' specific file '%s'", class_dev->classname, subsys_file->file);
- if (error)
- *error = "class specific file unavailable";
- return -1;
-
- /* skip devices without devices-link */
- if (getenv("PHYSDEVPATH") == NULL) {
- dbg("the kernel says, that there is no physical device for '%s'", class_dev->path);
- return 1;
- }
-
- /* the symlink may be on the parent device */
- class_dev_parent = sysfs_get_classdev_parent(class_dev);
- if (class_dev_parent)
- dbg("looking at parent device for device link '%s'", class_dev_parent->path);
-
- /* wait for the symlink to the devices device */
- dbg("waiting for symlink to devices device");
- loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
- while (--loop) {
- if (class_dev_parent)
- devices_dev = sysfs_get_classdev_device(class_dev_parent);
- else
- devices_dev = sysfs_get_classdev_device(class_dev);
-
- if (devices_dev)
- break;
-
- usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
- }
- if (!devices_dev) {
- dbg(" error: no devices device symlink found");
- if (error)
- *error = "no device symlink";
- return -ENODEV;
- }
- dbg("device symlink found pointing to '%s'", devices_dev->path);
-
- return wait_for_devices_device(devices_dev, error);
-}
-
-struct sysfs_device *wait_devices_device_open(const char *path)
-{
- struct sysfs_device *devices_dev = NULL;
- int loop;
-
- loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
- while (--loop) {
- devices_dev = sysfs_open_device_path(path);
- if (devices_dev)
- break;
-
- usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
- }
-
- return devices_dev;
-}
diff --git a/udev_sysfs.h b/udev_sysfs.h
deleted file mode 100644
index 5b87d6bf..00000000
--- a/udev_sysfs.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * udev_sysfs.h
- *
- * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
- * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef _UDEV_SYSFS_H_
-#define _UDEV_SYSFS_H_
-
-#include "libsysfs/sysfs/libsysfs.h"
-
-#define WAIT_MAX_SECONDS 3
-#define WAIT_LOOP_PER_SECOND 20
-
-extern dev_t get_devt(struct sysfs_class_device *class_dev);
-
-/* /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);
-
-/* /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/udevstart.c b/udevstart.c
index 8ee079db..11063f67 100644
--- a/udevstart.c
+++ b/udevstart.c
@@ -40,7 +40,6 @@
#include "libsysfs/sysfs/libsysfs.h"
#include "udev_libc_wrapper.h"
-#include "udev_sysfs.h"
#include "udev.h"
#include "udev_version.h"
#include "logging.h"
diff --git a/udevtest.c b/udevtest.c
index 4890b683..1be3fa95 100644
--- a/udevtest.c
+++ b/udevtest.c
@@ -28,7 +28,6 @@
#include "libsysfs/sysfs/libsysfs.h"
#include "udev.h"
-#include "udev_sysfs.h"
#include "udev_utils.h"
#include "udev_version.h"
#include "udev_rules.h"