From 820e3b30db4d40b2fd045441e7671824b9637f5b Mon Sep 17 00:00:00 2001
From: Tom Gundersen <teg@jklm.no>
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.
---
 Makefile.am                     |  3 ++
 TODO                            |  4 ---
 configure.ac                    |  2 +-
 src/udev/udevd.c                | 72 -----------------------------------------
 units/kmod-static-nodes.service | 16 +++++++++
 units/systemd-udevd.service.in  |  1 -
 6 files changed, 20 insertions(+), 78 deletions(-)
 create mode 100644 units/kmod-static-nodes.service

diff --git a/Makefile.am b/Makefile.am
index 290ec1e..483f241 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1459,14 +1459,17 @@ rootlibexec_PROGRAMS += \
 	systemd-modules-load
 
 nodist_systemunit_DATA += \
+	units/kmod-static-nodes.service \
 	units/systemd-modules-load.service
 
 SYSINIT_TARGET_WANTS += \
+	kmod-static-nodes.service \
 	systemd-modules-load.service
 
 endif
 
 EXTRA_DIST += \
+	units/kmod-static-nodes.service \
 	units/systemd-modules-load.service.in
 
 # ------------------------------------------------------------------------------
diff --git a/TODO b/TODO
index d428fda..0498809 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 6fd5307..205a5e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -216,7 +216,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 7d13b4f..c4127cd 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/kmod-static-nodes.service b/units/kmod-static-nodes.service
new file mode 100644
index 0000000..00548a9
--- /dev/null
+++ b/units/kmod-static-nodes.service
@@ -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-static-nodes.service
+
+[Service]
+Type=oneshot
+ExecStartPre=/usr/bin/mkdir -p /run/tmpfiles.d
+ExecStart=/usr/bin/kmod static-nodes --format=tmpfiles --output=/run/tmpfiles.d/kmod.conf
diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in
index ddef423..0d25fcd 100644
--- a/units/systemd-udevd.service.in
+++ b/units/systemd-udevd.service.in
@@ -12,7 +12,6 @@ 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
 
 [Service]
 Type=notify
-- 
1.8.3.2

