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 89d09e1b5c)
This commit is contained in:
Tom Gundersen 2013-06-14 22:56:39 +02:00
parent fec79699da
commit edeb68c53f
8 changed files with 33 additions and 81 deletions

View File

@ -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)|' \

4
TODO
View File

@ -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

View File

@ -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])

View File

@ -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) {

1
units/.gitignore vendored
View File

@ -58,3 +58,4 @@
/initrd-udevadm-cleanup-db.service
/systemd-nspawn@.service
/systemd-machined.service
/kmod-static-nodes.service

View File

@ -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

View File

@ -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]

View File

@ -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