[systemd-devel] [PATCH] [RFC] udevd: let tmpfiles create all static nodes

Tom Gundersen teg at jklm.no
Thu Apr 11 08:48:31 PDT 2013


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 at vger.kernel.org>
Cc: <linux-hotplug at vger.kernel.org>
---
 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 at .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 at .service.in \
 	units/systemd-fsck-root.service.in \
 	units/user at .service.in \
+	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



More information about the systemd-devel mailing list