From: kay.sievers@vrfy.org Date: Tue, 23 Nov 2004 06:34:56 +0000 (+0100) Subject: [PATCH] integrate wait_for_sysfs in udev X-Git-Tag: 047~40 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c449b25e3f998efe8f5988632126fb468ee55fc5;p=systemd [PATCH] integrate wait_for_sysfs in udev Move the wait_for_sysfs logic into the udev binary. udev is called for every hotplug event. It also waits for /devices events. --- diff --git a/Makefile b/Makefile index de08f7cf..c89fa0fe 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,6 @@ SENDER = udevsend INFO = udevinfo TESTER = udevtest STARTER = udevstart -WAIT = wait_for_sysfs VERSION = 046 INSTALL_DIR = /usr/local/bin RELEASE_NAME = $(ROOT)-$(VERSION) @@ -178,7 +177,7 @@ CFLAGS += -I$(PWD)/libsysfs/sysfs \ # config files automatically generated GEN_CONFIGS = $(LOCAL_CFG_DIR)/udev.conf -all: $(ROOT) $(SENDER) $(DAEMON) $(INFO) $(TESTER) $(WAIT) $(GEN_CONFIGS) +all: $(ROOT) $(SENDER) $(DAEMON) $(INFO) $(TESTER) $(GEN_CONFIGS) @extras="$(EXTRAS)" ; for target in $$extras ; do \ echo $$target ; \ $(MAKE) prefix=$(prefix) \ @@ -282,7 +281,6 @@ $(INFO).o: $(GEN_HEADERS) $(HOST_PROGS) $(DAEMON).o: $(GEN_HEADERS) $(HOST_PROGS) $(SENDER).o: $(GEN_HEADERS) $(HOST_PROGS) $(STARTER).o: $(GEN_HEADERS) $(HOST_PROGS) -$(WAIT).o: $(GEN_HEADERS) $(HOST_PROGS) $(ROOT): $(LIBC) $(ROOT).o $(OBJS) $(HEADERS) $(GEN_MANPAGES) $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udev.o $(OBJS) $(LIB_OBJS) $(ARCH_LIB_OBJS) @@ -304,10 +302,6 @@ $(SENDER): $(LIBC) $(SENDER).o $(OBJS) udevd.h $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevsend.o $(LIB_OBJS) $(ARCH_LIB_OBJS) $(QUIET) $(STRIPCMD) $@ -$(WAIT): $(WAIT).o $(OBJS) $(HEADERS) $(LIBC) - $(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) $(WAIT).o udev_sysfs.o udev_lib.o udev_config.o $(SYSFS) $(LIB_OBJS) $(ARCH_LIB_OBJS) - $(QUIET) $(STRIPCMD) $@ - #.c.o: # $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) -c -o $@ $< .c.o: @@ -317,7 +311,7 @@ $(WAIT): $(WAIT).o $(OBJS) $(HEADERS) $(LIBC) clean: -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \ | xargs rm -f - -rm -f core $(ROOT) $(GEN_HEADERS) $(GEN_CONFIGS) $(GEN_MANPAGES) $(INFO) $(DAEMON) $(SENDER) $(TESTER) $(WAIT) + -rm -f core $(ROOT) $(GEN_HEADERS) $(GEN_CONFIGS) $(GEN_MANPAGES) $(INFO) $(DAEMON) $(SENDER) $(TESTER) -rm -f ccdv $(MAKE) -C klibc clean @extras="$(EXTRAS)" ; for target in $$extras ; do \ @@ -417,10 +411,8 @@ install: install-initscript install-config install-man install-dev.d all $(INSTALL_PROGRAM) -D $(SENDER) $(DESTDIR)$(sbindir)/$(SENDER) $(INSTALL_PROGRAM) -D $(INFO) $(DESTDIR)$(usrbindir)/$(INFO) $(INSTALL_PROGRAM) -D $(TESTER) $(DESTDIR)$(usrbindir)/$(TESTER) - $(INSTALL_PROGRAM) -D $(WAIT) $(DESTDIR)$(sbindir)/$(WAIT) - ln -f -s $(sbindir)/udev $(DESTDIR)$(sbindir)/$(STARTER) - ln -f -s $(sbindir)/$(SENDER) $(DESTDIR)$(hotplugdir)/10-udev.hotplug - - ln -f -s $(sbindir)/$(WAIT) $(DESTDIR)$(hotplugdir)/05-wait_for_sysfs.hotplug ifndef DESTDIR - killall $(DAEMON) - rm -rf $(udevdb) @@ -433,7 +425,6 @@ endif uninstall: uninstall-man uninstall-dev.d - rm $(hotplugdir)/10-udev.hotplug - - rm $(hotplugdir)/05-wait_for_sysfs.hotplug - rm $(configdir)/rules.d/50-udev.rules - rm $(configdir)/permissions.d/50-udev.permissions - rm $(configdir)/udev.conf @@ -447,7 +438,6 @@ uninstall: uninstall-man uninstall-dev.d - rm $(sbindir)/$(STARTER) - rm $(usrbindir)/$(INFO) - rm $(usrbindir)/$(TESTER) - - rm $(usrbindir)/$(WAIT) - rmdir $(hotplugdir) - rm -rf $(udevdb) - rmdir $(udevdir) diff --git a/udev.c b/udev.c index 605a55bf..8e6d06f1 100644 --- a/udev.c +++ b/udev.c @@ -4,6 +4,7 @@ * Userspace devfs * * Copyright (C) 2003,2004 Greg Kroah-Hartman + * Copyright (C) 2004 Kay Sievers * * 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 @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -68,70 +70,19 @@ int main(int argc, char *argv[], char *envp[]) { struct sigaction act; struct sysfs_class_device *class_dev; + struct sysfs_device *devices_dev; struct udevice udev; char path[SYSFS_PATH_MAX]; int retval = -EINVAL; - enum { - ADD, - REMOVE, - UDEVSTART, - } act_type; + const char *error; + const char *action = getenv("ACTION"); + const char *devpath = getenv("DEVPATH"); + const char *subsystem = argv[1]; dbg("version %s", UDEV_VERSION); logging_init("udev"); udev_init_config(); - /* export logging flag, callouts may want to do the same as udev */ - if (udev_log) - setenv("UDEV_LOG", "1", 1); - - if (strstr(argv[0], "udevstart") || (argv[1] != NULL && strstr(argv[1], "udevstart"))) { - act_type = UDEVSTART; - } else { - const char *action = getenv("ACTION"); - const char *devpath = getenv("DEVPATH"); - const char *subsystem = argv[1]; - - if (!action) { - dbg("no action?"); - goto exit; - } - if (strcmp(action, "add") == 0) { - act_type = ADD; - } else if (strcmp(action, "remove") == 0) { - act_type = REMOVE; - } else { - dbg("no action '%s' for us", action); - goto exit; - } - - if (!devpath) { - dbg("no devpath?"); - goto exit; - } - dbg("looking at '%s'", devpath); - - /* we only care about class devices and block stuff */ - if (!strstr(devpath, "class") && !strstr(devpath, "block")) { - dbg("not a block or class device"); - goto exit; - } - - if (!subsystem) { - dbg("no subsystem"); - goto exit; - } - - udev_set_values(&udev, devpath, subsystem, action); - - /* skip blacklisted subsystems */ - if (udev.type != 'n' && subsystem_expect_no_dev(subsystem)) { - dbg("don't care about '%s' devices", subsystem); - goto exit; - }; - - } - /* set signal handlers */ act.sa_handler = (void (*) (int))sig_handler; sigemptyset (&act.sa_mask); @@ -141,57 +92,110 @@ int main(int argc, char *argv[], char *envp[]) sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); - /* trigger timout to interrupt blocking syscalls */ + /* trigger timeout to interrupt blocking syscalls */ alarm(ALARM_TIMEOUT); - switch(act_type) { - case UDEVSTART: + udev_set_values(&udev, devpath, subsystem, action); + + if (strstr(argv[0], "udevstart") || (argv[1] != NULL && strstr(argv[1], "udevstart"))) { dbg("udevstart"); - /* disable all logging as it's much too slow on some facilities */ + /* disable all logging, as it's much too slow on some facilities */ udev_log = 0; - unsetenv("UDEV_LOG"); namedev_init(); retval = udev_start(); - break; - case ADD: - dbg("udev add"); - - /* open the device */ - snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, udev.devpath); - class_dev = sysfs_open_class_device_path(path); - if (class_dev == NULL) { - dbg ("sysfs_open_class_device_path failed"); - goto exit; - } - dbg("opened class_dev->name='%s'", class_dev->name); + goto exit; + } - /* init rules */ - namedev_init(); + if (!action) { + dbg("no action"); + goto exit; + } + + if (!subsystem) { + dbg("no subsystem"); + goto exit; + } + + if (!devpath) { + dbg("no devpath"); + goto exit; + } - /* name, create node, store in db */ - retval = udev_add_device(&udev, class_dev); + /* export logging flag, called scripts may want to do the same as udev */ + if (udev_log) + setenv("UDEV_LOG", "1", 1); + + if ((strncmp(devpath, "/block/", 7) == 0) || (strncmp(devpath, "/class/", 7) == 0)) { + if (strcmp(action, "add") == 0) { + /* wait for sysfs and possibly add node */ + dbg("udev add"); + + /* skip blacklisted subsystems */ + if (udev.type != 'n' && subsystem_expect_no_dev(udev.subsystem)) { + dbg("don't care about '%s' devices", udev.subsystem); + goto exit; + }; + + snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, udev.devpath); + class_dev = wait_class_device_open(path); + if (class_dev == NULL) { + dbg ("open class device failed"); + goto exit; + } + dbg("opened class_dev->name='%s'", class_dev->name); + + wait_for_class_device(class_dev, &error); + + /* init rules, permissions */ + namedev_init(); + + /* name, create node, store in db */ + retval = udev_add_device(&udev, class_dev); + + /* run dev.d/ scripts if we created a node or changed a netif name */ + if (udev.devname[0] != '\0') { + setenv("DEVNAME", udev.devname, 1); + dev_d_execute(&udev, DEVD_DIR, DEVD_SUFFIX); + } + + sysfs_close_class_device(class_dev); + } else if (strcmp(action, "remove") == 0) { + /* possibly remove a node */ + dbg("udev remove"); + + /* get node from db, delete it */ + retval = udev_remove_device(&udev); + + /* run dev.d/ scripts if we're not instructed to ignore the event */ + if (udev.devname[0] != '\0') { + setenv("DEVNAME", udev.devname, 1); + dev_d_execute(&udev, DEVD_DIR, DEVD_SUFFIX); + } - /* run dev.d/ scripts if we created a node or changed a netif name */ - if (udev.devname[0] != '\0') { - setenv("DEVNAME", udev.devname, 1); - dev_d_execute(&udev, DEVD_DIR, DEVD_SUFFIX); } + } else if ((strncmp(devpath, "/devices/", 9) == 0)) { + if (strcmp(action, "add") == 0) { + /* wait for sysfs */ + dbg("devices add"); - sysfs_close_class_device(class_dev); - break; - case REMOVE: - dbg("udev remove"); + snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, devpath); + devices_dev = wait_devices_device_open(path); + if (!devices_dev) { + dbg("devices device unavailable (probably remove has beaten us)"); + goto exit; + } + dbg("devices device opened '%s'", path); - /* get node from db, delete it*/ - retval = udev_remove_device(&udev); + wait_for_devices_device(devices_dev, &error); - /* run dev.d/ scripts if we're not instructed to ignore the event */ - if (udev.devname[0] != '\0') { - setenv("DEVNAME", udev.devname, 1); - dev_d_execute(&udev, DEVD_DIR, DEVD_SUFFIX); + sysfs_close_device(devices_dev); + } else if (strcmp(action, "remove") == 0) { + dbg("devices remove"); } + } else { + dbg("unhandled"); } exit: diff --git a/wait_for_sysfs.c b/wait_for_sysfs.c deleted file mode 100644 index 84a25adb..00000000 --- a/wait_for_sysfs.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * wait_for_sysfs.c - small program to delay the execution - * of /etc/hotplug.d/ programs, until sysfs - * is fully populated by the kernel. Depending on - * the type of device, we wait for all expected - * directories and then just exit. - * - * Copyright (C) 2004 Kay Sievers - * Copyright (C) 2004 Greg Kroah-Hartman - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "libsysfs/sysfs/libsysfs.h" -#include "udev_lib.h" -#include "udev_version.h" -#include "udev_sysfs.h" -#include "logging.h" - -#ifdef LOG -unsigned char logname[LOGNAME_SIZE]; -void log_message(int level, const char *format, ...) -{ - va_list args; - - va_start(args, format); - vsyslog(level, format, args); - va_end(args); -} -#endif - -int main(int argc, char *argv[], char *envp[]) -{ - const char *devpath = ""; - const char *action; - const char *subsystem; - char sysfs_mnt_path[SYSFS_PATH_MAX]; - char filename[SYSFS_PATH_MAX]; - struct sysfs_class_device *class_dev; - struct sysfs_device *devices_dev; - int rc = 0; - const char *error = NULL; - - logging_init("wait_for_sysfs"); - - if (argc != 2) { - dbg("error: subsystem"); - return 1; - } - subsystem = argv[1]; - - devpath = getenv ("DEVPATH"); - if (!devpath) { - dbg("error: no DEVPATH"); - rc = 1; - goto exit; - } - - action = getenv ("ACTION"); - if (!action) { - dbg("error: no ACTION"); - rc = 1; - goto exit; - } - - /* we only wait on an add event */ - if (strcmp(action, "add") != 0) { - dbg("no add ACTION"); - goto exit; - } - - if (sysfs_get_mnt_path(sysfs_mnt_path, SYSFS_PATH_MAX) != 0) { - dbg("error: no sysfs path"); - rc = 2; - goto exit; - } - - if ((strncmp(devpath, "/block/", 7) == 0) || (strncmp(devpath, "/class/", 7) == 0)) { - snprintf(filename, SYSFS_PATH_MAX, "%s%s", sysfs_mnt_path, devpath); - filename[SYSFS_PATH_MAX-1] = '\0'; - - /* skip bad events where we get no device for the class */ - if (strncmp(devpath, "/class/", 7) == 0 && strchr(&devpath[7], '/') == NULL) { - dbg("no device name for '%s', bad event", devpath); - goto exit; - } - - /* open the class device we are called for */ - class_dev = wait_class_device_open(filename); - if (!class_dev) { - dbg("error: class device unavailable (probably remove has beaten us)"); - goto exit; - } - dbg("class device opened '%s'", filename); - - /* wait for the class device with possible physical device and bus */ - wait_for_class_device(class_dev, &error); - - /* - * we got too many unfixable class/net errors, kernel later than 2.6.10-rc1 will - * solve this by exporting the needed information with the hotplug event - * until we use this just don't print any error for net devices, but still - * wait for it. - */ - if (strncmp(devpath, "/class/net/", 11) == 0) - error = NULL; - - sysfs_close_class_device(class_dev); - - } else if ((strncmp(devpath, "/devices/", 9) == 0)) { - snprintf(filename, SYSFS_PATH_MAX, "%s%s", sysfs_mnt_path, devpath); - filename[SYSFS_PATH_MAX-1] = '\0'; - - /* open the path we are called for */ - 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 devices device */ - wait_for_devices_device(devices_dev, &error); - - sysfs_close_device(devices_dev); - - } else { - dbg("unhandled sysfs path, no need to wait"); - } - -exit: - if (error) { - info("either wait_for_sysfs (udev %s) needs an update to handle the device '%s' " - "properly (%s) or the sysfs-support of your device's driver needs to be fixed, " - "please report to ", - UDEV_VERSION, devpath, error); - rc =3; - } else { - dbg("result: waiting for sysfs successful '%s'", devpath); - } - - logging_close(); - exit(rc); -}