From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kay Sievers Date: Fri, 19 Nov 2004 16:03:44 +0000 Subject: Re: [adventure] replace /sbin/hotplug by udevd Message-Id: <20041119160344.GA9932@vrfy.org> MIME-Version: 1 Content-Type: multipart/mixed; boundary="Q68bSM7Ycu6FN28Q" List-Id: References: <20041118002726.GA4281@vrfy.org> In-Reply-To: <20041118002726.GA4281@vrfy.org> To: linux-hotplug@vger.kernel.org --Q68bSM7Ycu6FN28Q Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Thu, Nov 18, 2004 at 11:27:55PM -0800, Greg KH wrote: > On Fri, Nov 19, 2004 at 02:11:40AM +0100, Kay Sievers wrote: > > The question is not what we can do _with_ udev for people who don't want > > udev, right? :) > > Heh, true. > > Ok, I like the idea, it's just going to take a while for me to get used > to it. I also need to think about how everyone's going to convert over > to this new scheme (or not...) Yeah, it's a good question, how to convert. We need to test it, then we will get an idea, I expect. To make the testing easier, here is a version which should by default behave like the current udev. Only if /proc/sys/kernel/hotplug is set to call udevsend we switch over to the new scheme and /etc/hotplug.d is handled from udev. Thanks, Kay --Q68bSM7Ycu6FN28Q Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="udev-as-hotplugd-04.patch" ===== dev_d.c 1.20 vs edited ===== --- 1.20/dev_d.c 2004-11-11 22:32:18 +01:00 +++ edited/dev_d.c 2004-11-19 16:00:50 +01:00 @@ -37,6 +37,12 @@ static int run_program(const char *filen int fd; struct udevice *udev = data; + /* prevent a loop if we handle /etc/hotplug.d */ + if (strstr(filename, "udev.hotplug") != NULL) { + dbg("prevent loop, don't call link pointing to ourself"); + return 0; + } + dbg("running %s", filename); pid = fork(); @@ -96,13 +102,17 @@ void dev_d_execute(struct udevice *udev, temp = strchr(temp, '/'); } - snprintf(dirname, PATH_MAX, "%s/%s", basedir, udev->name); - dirname[PATH_MAX-1] = '\0'; - call_foreach_file(run_program, dirname, suffix, udev); - - snprintf(dirname, PATH_MAX, "%s/%s", basedir, udev->subsystem); - dirname[PATH_MAX-1] = '\0'; - call_foreach_file(run_program, dirname, suffix, udev); + if (udev->name[0] != '\0') { + snprintf(dirname, PATH_MAX, "%s/%s", basedir, udev->name); + dirname[PATH_MAX-1] = '\0'; + call_foreach_file(run_program, dirname, suffix, udev); + } + + if (udev->subsystem[0] != '\0') { + snprintf(dirname, PATH_MAX, "%s/%s", basedir, udev->subsystem); + dirname[PATH_MAX-1] = '\0'; + call_foreach_file(run_program, dirname, suffix, udev); + } snprintf(dirname, PATH_MAX, "%s/default", basedir); dirname[PATH_MAX-1] = '\0'; ===== udev.c 1.82 vs edited ===== --- 1.82/udev.c 2004-11-13 06:51:09 +01:00 +++ edited/udev.c 2004-11-19 16:16:40 +01:00 @@ -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,66 +70,22 @@ int main(int argc, char *argv[], char *e { struct sigaction act; struct sysfs_class_device *class_dev; + struct sysfs_device *devices_dev; struct udevice udev; char path[SYSFS_PATH_MAX]; + char helper[256]; + int fd; + int len; 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(); - 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); @@ -137,51 +95,114 @@ int main(int argc, char *argv[], char *e 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: - dbg("udevstart"); + udev_set_values(&udev, devpath, subsystem, action); + + if (strstr(argv[0], "udevstart") || (argv[1] != NULL && strstr(argv[1], "udevstart"))) { + dbg("event: udevstart"); udev_log = 0; 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"); - break; - } - dbg("opened class_dev->name='%s'", class_dev->name); + goto exit; + } - /* init rules */ - namedev_init(); + if (!action) { + dbg("no action"); + goto hotplug; + } + + if (!subsystem) { + dbg("no subsystem"); + goto hotplug; + } + + if (!devpath) { + dbg("no devpath"); + goto hotplug; + } + + if ((strncmp(devpath, "/block/", 7) == 0) || (strncmp(devpath, "/class/", 7) == 0)) { + if (strcmp(action, "add") == 0) { + /* wait for sysfs and possibly add node */ + dbg("event: udev add"); - /* name, create node, store in db */ - retval = udev_add_device(&udev, class_dev); + /* skip blacklisted subsystems */ + if (udev.type != 'n' && subsystem_expect_no_dev(udev.subsystem)) { + dbg("don't care about '%s' devices", udev.subsystem); + goto hotplug; + }; + + snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, udev.devpath); + class_dev = wait_class_device_open(path); + if (class_dev == NULL) { + dbg ("sysfs_open_class_device_path failed"); + goto hotplug; + } + 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); + } - /* run dev.d/ scripts if we created a node or changed a netif name */ - if (udev.devname[0] != '\0') { - setenv("DEVNAME", udev.devname, 1); + sysfs_close_class_device(class_dev); + } else if (strcmp(action, "remove") == 0) { + /* possibly remove a node */ + dbg("event: udev remove"); + + /* get node from db, delete it */ + retval = udev_remove_device(&udev); + + /* run scripts */ dev_d_execute(&udev, DEVD_DIR, DEVD_SUFFIX); } + } else if ((strncmp(devpath, "/devices/", 9) == 0)) { + if (strcmp(action, "add") == 0) { + /* wait for sysfs */ + dbg("event: 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("error: devices device unavailable (probably remove has beaten us)"); + goto hotplug; + } + 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 scripts */ - dev_d_execute(&udev, DEVD_DIR, DEVD_SUFFIX); + sysfs_close_device(devices_dev); + } else if (strcmp(action, "remove") == 0) { + dbg("event: devices remove"); + } + } else { + dbg("event: unhandled"); } + +hotplug: + /* call the hotplug scripts if udevsend is the helper */ + fd = open("/proc/sys/kernel/hotplug", O_RDONLY); + if (fd < 0) + goto exit; + + len = read(fd, helper, 256); + if (len < 0) + goto exit; + helper[len] = '\0'; + + if (strstr(helper, "udevsend")) + dev_d_execute(&udev, HOTPLUGD_DIR, HOTPLUG_SUFFIX); exit: logging_close(); ===== udev.h 1.72 vs edited ===== --- 1.72/udev.h 2004-11-13 06:43:23 +01:00 +++ edited/udev.h 2004-11-19 15:57:18 +01:00 @@ -44,6 +44,9 @@ #define DEVD_DIR "/etc/dev.d" #define DEVD_SUFFIX ".dev" +#define HOTPLUGD_DIR "/etc/hotplug.d" +#define HOTPLUG_SUFFIX ".hotplug" + struct udevice { char devpath[DEVPATH_SIZE]; char subsystem[SUBSYSTEM_SIZE]; --Q68bSM7Ycu6FN28Q-- ------------------------------------------------------- This SF.Net email is sponsored by: InterSystems CACHE FREE OODBMS DOWNLOAD - A multidimensional database that combines robust object and relational technologies, making it a perfect match for Java, C++,COM, XML, ODBC and JDBC. www.intersystems.com/match8 _______________________________________________ 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