From edeb68c53f1cdc452016b4c8512586a70b1262e3 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Fri, 14 Jun 2013 22:56:39 +0200 Subject: [PATCH] static-nodes: move creation of static nodes from udevd to tmpfiles As of kmod v14, it is possible to export the static node information from /lib/modules/`uname -r`/modules.devname in tmpfiles.d(5) format. Use this functionality to let systemd-tmpfilesd create the static device nodes at boot, and drop the functionality from systemd-udevd. As an effect of this we can move from systemd-udevd to systemd-tmpfiles-setup-dev: * the conditional CAP_MKNOD (replaced by checking if /sys is mounted rw) * ordering before local-fs-pre.target (see 89d09e1b5c65a2d97840f682e0932c8bb499f166) --- Makefile.am | 11 +++- TODO | 4 -- configure.ac | 4 +- src/udev/udevd.c | 72 --------------------- units/.gitignore | 1 + units/kmod-static-nodes.service.in | 16 +++++ units/systemd-tmpfiles-setup-dev.service.in | 2 +- units/systemd-udevd.service.in | 4 +- 8 files changed, 33 insertions(+), 81 deletions(-) create mode 100644 units/kmod-static-nodes.service.in diff --git a/Makefile.am b/Makefile.am index 290ec1eb6..aa7e83022 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1464,10 +1464,18 @@ nodist_systemunit_DATA += \ SYSINIT_TARGET_WANTS += \ systemd-modules-load.service +if ENABLE_TMPFILES +nodist_systemunit_DATA += \ + units/kmod-static-nodes.service + +SYSINIT_TARGET_WANTS += \ + kmod-static-nodes.service +endif endif EXTRA_DIST += \ - units/systemd-modules-load.service.in + units/systemd-modules-load.service.in \ + units/kmod-static-nodes.service.in # ------------------------------------------------------------------------------ if ENABLE_TMPFILES @@ -4137,6 +4145,7 @@ substitutions = \ '|SUSHELL=$(SUSHELL)|' \ '|DEBUGTTY=$(DEBUGTTY)|' \ '|KILL=$(KILL)|' \ + '|KMOD=$(KMOD)|' \ '|QUOTAON=$(QUOTAON)|' \ '|QUOTACHECK=$(QUOTACHECK)|' \ '|SYSTEM_SYSVINIT_PATH=$(sysvinitdir)|' \ diff --git a/TODO b/TODO index d428fda5f..0498809ea 100644 --- a/TODO +++ b/TODO @@ -186,10 +186,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 - * seems that when we follow symlinks to units we prefer the symlink destination path over /etc and /usr. We shouldn't do that. Instead /etc should always override /run+/usr and also any symlink diff --git a/configure.ac b/configure.ac index 6fd5307c7..be867079c 100644 --- a/configure.ac +++ b/configure.ac @@ -74,6 +74,8 @@ AC_PATH_PROG([SETCAP], [setcap], [/usr/sbin/setcap]) AC_PATH_PROG([KILL], [kill], [/usr/bin/kill]) +AC_PATH_PROG([KMOD], [kmod], [/usr/bin/kmod]) + # gtkdocize greps for '^GTK_DOC_CHECK', so it needs to be on its own line m4_ifdef([GTK_DOC_CHECK], [ GTK_DOC_CHECK([1.18],[--flavour no-tmpl])], @@ -216,7 +218,7 @@ PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.3.2]) have_kmod=no AC_ARG_ENABLE(kmod, AS_HELP_STRING([--disable-kmod], [disable loadable modules support])) if test "x$enable_kmod" != "xno"; then - PKG_CHECK_MODULES(KMOD, [ libkmod >= 5 ], + PKG_CHECK_MODULES(KMOD, [ libkmod >= 14 ], [AC_DEFINE(HAVE_KMOD, 1, [Define if kmod is available]) have_kmod=yes], have_kmod=no) if test "x$have_kmod" = xno -a "x$enable_kmod" = xyes; then AC_MSG_ERROR([*** kmod support requested but libraries not found]) diff --git a/src/udev/udevd.c b/src/udev/udevd.c index 7d13b4f53..c4127cd03 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/.gitignore b/units/.gitignore index 0bcbb0095..9aee00f2a 100644 --- a/units/.gitignore +++ b/units/.gitignore @@ -58,3 +58,4 @@ /initrd-udevadm-cleanup-db.service /systemd-nspawn@.service /systemd-machined.service +/kmod-static-nodes.service diff --git a/units/kmod-static-nodes.service.in b/units/kmod-static-nodes.service.in new file mode 100644 index 000000000..f8a2d474e --- /dev/null +++ b/units/kmod-static-nodes.service.in @@ -0,0 +1,16 @@ +# 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 list of required static device nodes for the current kernel +DefaultDependencies=no +Before=sysinit.target systemd-tmpfiles-setup-dev.service + +[Service] +Type=oneshot +ExecStartPre=/usr/bin/mkdir -p /run/tmpfiles.d +ExecStart=@KMOD@ static-nodes --format=tmpfiles --output=/run/tmpfiles.d/kmod.conf diff --git a/units/systemd-tmpfiles-setup-dev.service.in b/units/systemd-tmpfiles-setup-dev.service.in index f029285bc..8073b1229 100644 --- a/units/systemd-tmpfiles-setup-dev.service.in +++ b/units/systemd-tmpfiles-setup-dev.service.in @@ -9,7 +9,7 @@ Description=Create static device nodes in /dev Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8) DefaultDependencies=no -Before=sysinit.target systemd-udevd.service +Before=sysinit.target local-fs-pre.target systemd-udevd.service ConditionCapability=CAP_MKNOD [Service] diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in index ddef42362..99f51304e 100644 --- a/units/systemd-udevd.service.in +++ b/units/systemd-udevd.service.in @@ -11,8 +11,8 @@ 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 -Before=sysinit.target local-fs-pre.target -ConditionCapability=CAP_MKNOD +Before=sysinit.target +ConditionPathIsReadWrite=/sys [Service] Type=notify -- 2.30.2