systemd-tmpfiles has had support for creation of static nodes for some time (to replace copying nodes from /lib/udev/). Make sure these nodes are created before udev is started. Also, drop support for creating static nodes based on modules.devname from systemd-udevd. This allows it to run witohut CAP_MKNOD, moreover we no longer need to parse /usr/lib/modules/*/modules.devname. As a replacement for udevd's functionality, we let kmod generate a tmpfiles.d fragment based on the correct modules.devname file (see separate patch). We might want to split the kmod call out into its own unit file and ship that with kmod instead. Note: one functional change is that we no longer update the creation time on already existing device nodes. Is this important? If so, should tmpfiles learn to do that? Cc: <linux-modules@xxxxxxxxxxxxxxx> Cc: <linux-hotplug@xxxxxxxxxxxxxxx> --- Makefile.am | 5 +++ TODO | 4 -- src/udev/udevd.c | 72 ----------------------------------- units/systemd-static-nodes.service.in | 17 +++++++++ units/systemd-udevd.service.in | 5 +-- 5 files changed, 24 insertions(+), 79 deletions(-) create mode 100644 units/systemd-static-nodes.service.in diff --git a/Makefile.am b/Makefile.am index ec81f53..3c6adcb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -427,6 +427,7 @@ nodist_systemunit_DATA = \ units/systemd-kexec.service \ units/systemd-fsck@.service \ units/systemd-fsck-root.service \ + units/systemd-static-nodes.service \ units/systemd-udevd.service \ units/systemd-udev-trigger.service \ units/systemd-udev-settle.service \ @@ -468,6 +469,7 @@ EXTRA_DIST += \ units/systemd-fsck@xxxxxxxxxxx \ units/systemd-fsck-root.service.in \ units/user@xxxxxxxxxxx \ + units/systemd-static-nodes.service \ units/systemd-udevd.service \ units/systemd-udev-trigger.service \ units/systemd-udev-settle.service \ @@ -1925,11 +1927,13 @@ CLEANFILES += \ src/udev/udev.pc EXTRA_DIST += \ + units/systemd-static-nodes.service.in \ units/systemd-udevd.service.in \ units/systemd-udev-trigger.service.in \ units/systemd-udev-settle.service.in CLEANFILES += \ + units/systemd-static-nodes.service \ units/systemd-udevd.service \ units/systemd-udev-trigger.service \ units/systemd-udev-settle.service @@ -1938,6 +1942,7 @@ SOCKETS_TARGET_WANTS += \ systemd-udevd-control.socket \ systemd-udevd-kernel.socket SYSINIT_TARGET_WANTS += \ + systemd-static-nodes.service \ systemd-udevd.service \ systemd-udev-trigger.service diff --git a/TODO b/TODO index 369fb78..d70732d 100644 --- a/TODO +++ b/TODO @@ -51,10 +51,6 @@ Features: so that the coredump is properly written to the user's own journal file. -* move /usr/lib/modules/$(uname -r)/modules.devname parsing from udevd to - kmod static-nodes - call kmod as an early service, and drop CAP_MKNOD from udevd.service - * systemd-delta needs to be made aware of *.d/*.conf drop-in files for units. diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 2d9093d..642ca43 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -812,77 +812,6 @@ static void handle_signal(struct udev *udev, int signo) } } -static void static_dev_create_from_modules(struct udev *udev) -{ - struct utsname kernel; - char modules[UTIL_PATH_SIZE]; - char buf[4096]; - FILE *f; - - if (uname(&kernel) < 0) { - log_error("uname failed: %m"); - return; - } - - strscpyl(modules, sizeof(modules), ROOTPREFIX "/lib/modules/", kernel.release, "/modules.devname", NULL); - f = fopen(modules, "re"); - if (f == NULL) - return; - - while (fgets(buf, sizeof(buf), f) != NULL) { - char *s; - const char *modname; - const char *devname; - const char *devno; - int maj, min; - char type; - mode_t mode; - char filename[UTIL_PATH_SIZE]; - - if (buf[0] == '#') - continue; - - modname = buf; - s = strchr(modname, ' '); - if (s == NULL) - continue; - s[0] = '\0'; - - devname = &s[1]; - s = strchr(devname, ' '); - if (s == NULL) - continue; - s[0] = '\0'; - - devno = &s[1]; - s = strchr(devno, ' '); - if (s == NULL) - s = strchr(devno, '\n'); - if (s != NULL) - s[0] = '\0'; - if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3) - continue; - - mode = 0600; - if (type == 'c') - mode |= S_IFCHR; - else if (type == 'b') - mode |= S_IFBLK; - else - continue; - - strscpyl(filename, sizeof(filename), "/dev/", devname, NULL); - mkdir_parents_label(filename, 0755); - label_context_set(filename, mode); - log_debug("mknod '%s' %c%u:%u\n", filename, type, maj, min); - if (mknod(filename, mode, makedev(maj, min)) < 0 && errno == EEXIST) - utimensat(AT_FDCWD, filename, NULL, 0); - label_context_clear(); - } - - fclose(f); -} - static int systemd_fds(struct udev *udev, int *rctrl, int *rnetlink) { int ctrl = -1, netlink = -1; @@ -1067,7 +996,6 @@ int main(int argc, char *argv[]) mkdir("/run/udev", 0755); dev_setup(NULL); - static_dev_create_from_modules(udev); /* before opening new files, make sure std{in,out,err} fds are in a sane state */ if (daemonize) { diff --git a/units/systemd-static-nodes.service.in b/units/systemd-static-nodes.service.in new file mode 100644 index 0000000..8178c43 --- /dev/null +++ b/units/systemd-static-nodes.service.in @@ -0,0 +1,17 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Create static device nodes in /dev +DefaultDependencies=no +Before=sysinit.target local-fs-pre.target +ConditionCapability=CAP_MKNOD + +[Service] +Type=oneshot +ExecStart=@rootbindir@/kmod devname2tmpfile +ExecStart=@rootbindir@/systemd-tmpfiles --prefix=/dev --create diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in index ddef423..c0dc4f2 100644 --- a/units/systemd-udevd.service.in +++ b/units/systemd-udevd.service.in @@ -9,10 +9,9 @@ Description=udev Kernel Device Manager Documentation=man:systemd-udevd.service(8) man:udev(7) DefaultDependencies=no -Wants=systemd-udevd-control.socket systemd-udevd-kernel.socket -After=systemd-udevd-control.socket systemd-udevd-kernel.socket +Wants=systemd-static-nodes.service systemd-udevd-control.socket systemd-udevd-kernel.socket +After=systemd-static-nodes.service systemd-udevd-control.socket systemd-udevd-kernel.socket Before=sysinit.target local-fs-pre.target -ConditionCapability=CAP_MKNOD [Service] Type=notify -- 1.8.2.1 -- To unsubscribe from this list: send the line "unsubscribe linux-modules" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html