[systemd-devel] [PATCH v2] tools: add static-nodes tool
Tom Gundersen
teg at jklm.no
Tue Apr 16 06:10:09 PDT 2013
On Tue, Apr 16, 2013 at 1:20 AM, Lucas De Marchi
<lucas.demarchi at profusion.mobi> wrote:
> Hi Tom,
Hi Lucas,
Thanks for your review!
> On Fri, Apr 12, 2013 at 9:15 PM, Tom Gundersen <teg at jklm.no> wrote:
>> This tool reads modules.devname from the current kernel directory and outputs
>> the information.
>>
>> For now only the tmpfiles.d(5) format is supported, but more could easily be
>> added in the future if there is a need.
>>
>> When booting with systemd, the new tool is called at boot to instruct
>> systemd-tmpfiles to create the necessary static modules before starting
>> systemd-udevd.
>>
>> This means nothing but kmod needs to reads the private files under /lib/modules/.
>
> For me this would be the main goal of this patch or anything similar to this.
Yeah, I agree.
>> Cc: <linux-hotplug at vger.kernel.org>
>> Cc: <systemd-devel at lists.freedesktop.org>
>> ---
>>
>> v2: adressed concerns raised by Dave, and made the tool a bit more generic so
>> more output formats may be added in the future as suggested by Lucas. Also
>> included the systemd unit file to hook this up with systemd.
>>
>> Makefile.am | 20 ++++-
>> configure.ac | 8 ++
>> tools/kmod-static-nodes.service.in | 16 ++++
>> tools/kmod.c | 1 +
>> tools/kmod.h | 1 +
>> tools/static-nodes.c | 163 +++++++++++++++++++++++++++++++++++++
>> 6 files changed, 207 insertions(+), 2 deletions(-)
>> create mode 100644 tools/kmod-static-nodes.service.in
>> create mode 100644 tools/static-nodes.c
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 9feaf96..333e861 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -36,6 +36,9 @@ SED_PROCESS = \
>> %.pc: %.pc.in Makefile
>> $(SED_PROCESS)
>>
>> +%.service: %.service.in Makefile
>> + $(SED_PROCESS)
>> +
>> LIBKMOD_CURRENT=4
>> LIBKMOD_REVISION=2
>> LIBKMOD_AGE=2
>> @@ -88,6 +91,17 @@ pkgconfig_DATA = libkmod/libkmod.pc
>> EXTRA_DIST += libkmod/libkmod.pc.in
>> CLEANFILES += libkmod/libkmod.pc
>>
>> +if HAVE_SYSTEMD
>> +systemdsystemunit_DATA = tools/kmod-static-nodes.service
>> +EXTRA_DIST += tools/kmod-static-nodes.service.in
>> +CLEANFILES += tools/kmod-static-nodes.service
>> +
>> +install-data-hook:
>> + $(MKDIR_P) $(DESTDIR)$(systemdsystemunitdir)/sysinit.target.wants
>> + ln -sf ../kmod-static-nodes.service \
>> + $(DESTDIR)$(systemdsystemunitdir)/sysinit.target.wants/kmod-static-nodes.service
>> +endif
>> +
>> install-exec-hook:
>> if test "$(libdir)" != "$(rootlibdir)"; then \
>> $(MKDIR_P) $(DESTDIR)$(rootlibdir) && \
>> @@ -109,7 +123,8 @@ noinst_SCRIPTS = tools/insmod tools/rmmod tools/lsmod \
>> tools_kmod_SOURCES = tools/kmod.c tools/kmod.h tools/lsmod.c \
>> tools/rmmod.c tools/insmod.c \
>> tools/modinfo.c tools/modprobe.c \
>> - tools/depmod.c tools/log.h tools/log.c
>> + tools/depmod.c tools/log.h tools/log.c \
>> + tools/static-nodes.c
>> tools_kmod_LDADD = libkmod/libkmod-util.la \
>> libkmod/libkmod.la
>>
>> @@ -211,7 +226,8 @@ testsuite-distclean:
>> DISTCLEAN_LOCAL_HOOKS += testsuite-distclean
>> EXTRA_DIST += testsuite/rootfs-pristine
>>
>> -DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --sysconfdir=/etc --with-zlib
>> +DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --sysconfdir=/etc --with-zlib \
>> + --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
>>
>> distclean-local: $(DISTCLEAN_LOCAL_HOOKS)
>>
>> diff --git a/configure.ac b/configure.ac
>> index 566b317..af5ed52 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -76,6 +76,13 @@ AS_IF([test "x$with_zlib" != "xno"], [
>> AC_MSG_NOTICE([zlib support not requested])
>> ])
>>
>> +AC_ARG_WITH([systemdsystemunitdir],
>> + AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
>> + [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
>> +if test "x$with_systemdsystemunitdir" != xno; then
>> + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
>> +fi
>> +AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
>>
>> #####################################################################
>> # --enable-
>> @@ -200,6 +207,7 @@ AC_MSG_RESULT([
>> compiler: ${CC}
>> cflags: ${with_cflags} ${CFLAGS}
>> ldflags: ${with_ldflags} ${LDFLAGS}
>> + systemdsystemunitdir: ${with_systemdsystemunitdir}
>>
>> tools: ${enable_tools}
>> logging: ${enable_logging}
>> diff --git a/tools/kmod-static-nodes.service.in b/tools/kmod-static-nodes.service.in
>> new file mode 100644
>> index 0000000..be8482e
>> --- /dev/null
>> +++ b/tools/kmod-static-nodes.service.in
>
> I'm not sure we want the service file to live in kmod repository.
> Maybe we could let this in systemd and in kmod we only add the support
> to create this type of information?
I don't really mind. For now I'll drop it, and we can agree on where
to put it later.
>> @@ -0,0 +1,16 @@
>> +# This file is part of kmod.
>> +#
>> +# kmod 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 static nodes to be created in /dev
>> +DefaultDependencies=no
>> +Before=sysinit.target systemd-static-nodes.service
>> +
>> +[Service]
>> +Type=oneshot
>> +ExecStart=/bin/mkdir -p /run/tmpfiles.d
>> +ExecStart=@prefix@/bin/kmod static-nodes tmpfiles --output=/run/tmpfiles.d/kmod.conf
>
> The syntax is a bit cumbersome too, but since we still don't have any
> command (except from the test-only "list") I think we could let this
> as is and change later, before a new release.
>
> IMO it should be kmod static-nodes --format=...
>
> It's ok to implement only the tmpfiles output, though the default
> should be an human readable format, just like git commands are.
Thanks for the suggestions, makes sense. I resent with these changes.
>> diff --git a/tools/kmod.c b/tools/kmod.c
>> index ebb8875..347bb7d 100644
>> --- a/tools/kmod.c
>> +++ b/tools/kmod.c
>> @@ -37,6 +37,7 @@ static const struct kmod_cmd kmod_cmd_help;
>> static const struct kmod_cmd *kmod_cmds[] = {
>> &kmod_cmd_help,
>> &kmod_cmd_list,
>> + &kmod_cmd_static_nodes,
>> };
>>
>> static const struct kmod_cmd *kmod_compat_cmds[] = {
>> diff --git a/tools/kmod.h b/tools/kmod.h
>> index 80fa4c2..68a646a 100644
>> --- a/tools/kmod.h
>> +++ b/tools/kmod.h
>> @@ -35,5 +35,6 @@ extern const struct kmod_cmd kmod_cmd_compat_modprobe;
>> extern const struct kmod_cmd kmod_cmd_compat_depmod;
>>
>> extern const struct kmod_cmd kmod_cmd_list;
>> +extern const struct kmod_cmd kmod_cmd_static_nodes;
>>
>> #include "log.h"
>> diff --git a/tools/static-nodes.c b/tools/static-nodes.c
>> new file mode 100644
>> index 0000000..a79fc3d
>> --- /dev/null
>> +++ b/tools/static-nodes.c
>> @@ -0,0 +1,163 @@
>> +/*
>> + * kmod-static-nodes - manage modules.devname
>> + *
>> + * Copyright (C) 2004-2012 Kay Sievers <kay at vrfy.org>
>> + * Copyright (C) 2011-2013 ProFUSION embedded systems
>> + * Copyright (C) 2013 Tom Gundersen <teg at jklm.no>
>> + *
>> + * This program is free software: you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation, either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <stddef.h>
>> +#include <getopt.h>
>> +#include <errno.h>
>> +#include <unistd.h>
>> +#include <string.h>
>> +#include <limits.h>
>> +#include <sys/utsname.h>
>> +#include <sys/stat.h>
>> +#include <sys/types.h>
>> +#include "libkmod-util.h"
>> +
>> +#include "kmod.h"
>> +
>> +static const char cmdopts_s[] = "o:h";
>> +static const struct option cmdopts[] = {
>> + { "output", required_argument, 0, 'o'},
>> + { "help", no_argument, 0, 'h'},
>> + { },
>> +};
>> +
>> +static void help(void)
>> +{
>> + printf("Usage:\n"
>> + "\t%s static-nodes format [options]\n"
>> + "\n"
>> + "kmod static-nodes outputs the static-node information of the currently running kernel.\n"
>> + "\n"
>> + "Options:\n"
>> + "\t-o, --output=FILE write output to file\n"
>> + "\t-h, --help show this help\n"
>> + "\n"
>> + "Formats:\n"
>> + " tmpfiles the tmpfiles.d(5) used by systemd-tmpfiles.\n",
>> + program_invocation_short_name);
>> +}
>> +
>> +static int write_tmpfile(FILE *in, FILE *out) {
>> + char buf[4096];
>> + int ret = EXIT_SUCCESS;
>> +
>> + while (fgets(buf, sizeof(buf), in) != NULL) {
>> + char devname[PATH_MAX];
>> + char type;
>> + unsigned int maj, min;
>> + int matches;
>> +
>> + if (buf[0] == '#')
>> + continue;
>> +
>> + matches = sscanf(buf, "%*s %s %c%u:%u", devname, &type, &maj, &min);
>> + if (matches != 4 || (type != 'c' && type != 'b')) {
>> + fprintf(stderr, "Error: invalid devname entry: %s", buf);
>> + ret = EXIT_FAILURE;
>> + continue;
>> + }
>> +
>> + fprintf(out, "%c /dev/%s 0600 - - - %u:%u\n", type, devname, maj, min);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int do_static_nodes(int argc, char *argv[])
>> +{
>> + struct utsname kernel;
>> + char modules[PATH_MAX];
>> + FILE *in = NULL, *out = stdout;
>> + int ret = EXIT_SUCCESS;
>> +
>> + for (;;) {
>> + int c, idx = 0;
>> +
>> + c = getopt_long(argc - 1, argv + 1, cmdopts_s, cmdopts, &idx);
>> + if (c == -1) {
>> + break;
>> + }
>> + switch (c) {
>> + case 'o':
>> + out = fopen(optarg, "we");
>> + if (out == NULL) {
>> + fprintf(stderr, "Error: could not create %s!\n", optarg);
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> + break;
>> + case 'h':
>> + help();
>> + goto finish;
>> + case '?':
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + default:
>> + fprintf(stderr, "Unexpected commandline option '%c'.\n", c);
>> + help();
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> + }
>> +
>> + if (argc < 2) {
>> + help();
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> +
>> + if (!streq(argv[1], "tmpfiles")) {
>> + fprintf(stderr, "Unknown format: '%s'.\n", argv[1]);
>> + help();
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> +
>> + if (uname(&kernel) < 0) {
>> + fputs("Error: uname failed!\n", stderr);
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> + snprintf(modules, sizeof(modules), "/lib/modules/%s/modules.devname", kernel.release);
>> + in = fopen(modules, "re");
>> + if (in == NULL && errno != ENOENT) {
>> + fprintf(stderr, "Error: could not open /lib/modules/%s/modules.devname!\n", kernel.release);
>> + ret = EXIT_FAILURE;
>> + goto finish;
>> + }
>> +
>> + ret = write_tmpfile(in, out);
>> +
>> +finish:
>> + if (in)
>> + fclose(in);
>> + if (out)
>> + fclose(out);
>> + return ret;
>> +}
>> +
>> +const struct kmod_cmd kmod_cmd_static_nodes = {
>> + .name = "static-nodes",
>> + .cmd = do_static_nodes,
>> + .help = "outputs the static-node information of the currently running kernel",
>> +};
>> --
>
>
> Lucas De Marchi
More information about the systemd-devel
mailing list