[systemd-commits] 5 commits - Makefile.am TODO man/systemd-nspawn.xml man/tmpfiles.d.xml src/nspawn src/tmpfiles tmpfiles.d/legacy.conf tmpfiles.d/systemd.conf tmpfiles.d/var.conf

Lennart Poettering lennart at kemper.freedesktop.org
Tue Jun 10 16:48:01 PDT 2014


 Makefile.am             |    3 +
 TODO                    |    2 -
 man/systemd-nspawn.xml  |   24 ++++++++++++
 man/tmpfiles.d.xml      |    6 ++-
 src/nspawn/nspawn.c     |   94 +++++++++++++++++++++++++++++++++++++++++-------
 src/tmpfiles/tmpfiles.c |   42 ++++++++++++++-------
 tmpfiles.d/legacy.conf  |    1 
 tmpfiles.d/systemd.conf |    5 --
 tmpfiles.d/var.conf     |   20 ++++++++++
 9 files changed, 162 insertions(+), 35 deletions(-)

New commits:
commit 1910cd0e05f7661986680e0a4472f4e857f90787
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jun 11 01:37:35 2014 +0200

    tmpfiles: when processing lines, always process prefixes before suffixes
    
    If two lines refer to paths that are suffix and prefix of each other,
    then always process the prefix first, the suffix second. In all other
    cases strictly process rules in the order they appear in the files.
    
    This makes creating /var/run as symlink to /run a lot more fun, since it
    is automatically created first.

diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 76cae39..5d8c2b5 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -109,7 +109,11 @@
                 of the directories they reside in. If multiple files
                 specify the same path, the entry in the file with the
                 lexicographically earliest name will be applied, all
-                all other conflicting entries logged as errors.</para>
+                all other conflicting entries will be logged as
+                errors. When two lines are prefix and suffix of each
+                other, then the prefix is always processed first, the
+                suffix later. Otherwise the files/directories are
+                processed in the order they are listed.</para>
 
                 <para>If the administrator wants to disable a
                 configuration file supplied by the vendor, the
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index d68693f..c6121bc 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -101,6 +101,8 @@ typedef struct Item {
         bool age_set:1;
 
         bool keep_first_level:1;
+
+        bool done:1;
 } Item;
 
 static bool arg_create = false;
@@ -977,9 +979,23 @@ static int clean_item(Item *i) {
 
 static int process_item(Item *i) {
         int r, q, p;
+        char prefix[PATH_MAX];
 
         assert(i);
 
+        if (i->done)
+                return 0;
+
+        i->done = true;
+
+        PATH_FOREACH_PREFIX(prefix, i->path) {
+                Item *j;
+
+                j = hashmap_get(items, prefix);
+                if (j)
+                        process_item(j);
+        }
+
         r = arg_create ? create_item(i) : 0;
         q = arg_remove ? remove_item(i) : 0;
         p = arg_clean ? clean_item(i) : 0;

commit 7bc040fab802ff20eacd1745e393f1766c8c35d9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jun 11 01:26:28 2014 +0200

    tmpfiles: static variables populated immediately from the command line should be prefixed with arg_

diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 4c0f23e..d68693f 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -103,16 +103,13 @@ typedef struct Item {
         bool keep_first_level:1;
 } Item;
 
-static Hashmap *items = NULL, *globs = NULL;
-static Set *unix_sockets = NULL;
-
 static bool arg_create = false;
 static bool arg_clean = false;
 static bool arg_remove = false;
 static bool arg_boot = false;
 
-static char **include_prefixes = NULL;
-static char **exclude_prefixes = NULL;
+static char **arg_include_prefixes = NULL;
+static char **arg_exclude_prefixes = NULL;
 static char *arg_root = NULL;
 
 static const char conf_file_dirs[] =
@@ -127,6 +124,9 @@ static const char conf_file_dirs[] =
 
 #define MAX_DEPTH 256
 
+static Hashmap *items = NULL, *globs = NULL;
+static Set *unix_sockets = NULL;
+
 static bool needs_glob(ItemType t) {
         return IN_SET(t,
                       WRITE_FILE,
@@ -1048,19 +1048,19 @@ static bool item_equal(Item *a, Item *b) {
 static bool should_include_path(const char *path) {
         char **prefix;
 
-        STRV_FOREACH(prefix, exclude_prefixes) {
+        STRV_FOREACH(prefix, arg_exclude_prefixes) {
                 if (path_startswith(path, *prefix))
                         return false;
         }
 
-        STRV_FOREACH(prefix, include_prefixes) {
+        STRV_FOREACH(prefix, arg_include_prefixes) {
                 if (path_startswith(path, *prefix))
                         return true;
         }
 
         /* no matches, so we should include this path only if we
          * have no whitelist at all */
-        return strv_length(include_prefixes) == 0;
+        return strv_length(arg_include_prefixes) == 0;
 }
 
 static int parse_line(const char *fname, unsigned line, const char *buffer) {
@@ -1372,12 +1372,12 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_PREFIX:
-                        if (strv_push(&include_prefixes, optarg) < 0)
+                        if (strv_push(&arg_include_prefixes, optarg) < 0)
                                 return log_oom();
                         break;
 
                 case ARG_EXCLUDE_PREFIX:
-                        if (strv_push(&exclude_prefixes, optarg) < 0)
+                        if (strv_push(&arg_exclude_prefixes, optarg) < 0)
                                 return log_oom();
                         break;
 
@@ -1544,8 +1544,8 @@ finish:
         hashmap_free(items);
         hashmap_free(globs);
 
-        free(include_prefixes);
-        free(exclude_prefixes);
+        free(arg_include_prefixes);
+        free(arg_exclude_prefixes);
         free(arg_root);
 
         set_free_free(unix_sockets);

commit 06c17c39a8345deef1ecff4dd5ef262f968c9be2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jun 11 00:44:30 2014 +0200

    nspawn: add new --tmpfs= option to mount a tmpfs on specific directories, such as /var

diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index ccd3436..d668703 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -504,6 +504,30 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><option>--tmpfs=</option></term>
+
+                                <listitem><para>Mount a tmpfs file
+                                system into the container. Takes a
+                                single absolute path argument that
+                                specifies where to mount the tmpfs
+                                instance to (in which case the
+                                directory access mode will be chosen
+                                as 0755, owned by root/root), or
+                                optionally a colon-separated pair of
+                                path and mount option string, that is
+                                used for mounting (in which case the
+                                kernel default for access mode and
+                                owner will be chosen, unless otherwise
+                                specified). This option is
+                                particularly useful for mounting
+                                directories such as
+                                <filename>/var</filename> as tmpfs, to
+                                allow state-less systems, in
+                                particular when combined with
+                                <option>--read-only</option>.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><option>--setenv=</option></term>
 
                                 <listitem><para>Specifies an
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 867cf19..29ddfbb 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -146,6 +146,7 @@ static uint64_t arg_retain =
         (1ULL << CAP_MKNOD);
 static char **arg_bind = NULL;
 static char **arg_bind_ro = NULL;
+static char **arg_tmpfs = NULL;
 static char **arg_setenv = NULL;
 static bool arg_quiet = false;
 static bool arg_share_system = false;
@@ -200,6 +201,7 @@ static int help(void) {
                "     --bind=PATH[:PATH]     Bind mount a file or directory from the host into\n"
                "                            the container\n"
                "     --bind-ro=PATH[:PATH]  Similar, but creates a read-only bind mount\n"
+               "     --tmpfs=PATH:[OPTIONS] Mount an empty tmpfs to the specified directory\n"
                "     --setenv=NAME=VALUE    Pass an environment variable to PID 1\n"
                "     --share-system         Share system namespaces with host\n"
                "     --register=BOOLEAN     Register container as machine\n"
@@ -222,6 +224,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_LINK_JOURNAL,
                 ARG_BIND,
                 ARG_BIND_RO,
+                ARG_TMPFS,
                 ARG_SETENV,
                 ARG_SHARE_SYSTEM,
                 ARG_REGISTER,
@@ -247,6 +250,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "link-journal",          required_argument, NULL, ARG_LINK_JOURNAL      },
                 { "bind",                  required_argument, NULL, ARG_BIND              },
                 { "bind-ro",               required_argument, NULL, ARG_BIND_RO           },
+                { "tmpfs",                 required_argument, NULL, ARG_TMPFS             },
                 { "machine",               required_argument, NULL, 'M'                   },
                 { "slice",                 required_argument, NULL, 'S'                   },
                 { "setenv",                required_argument, NULL, ARG_SETENV            },
@@ -469,6 +473,42 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case ARG_TMPFS: {
+                        _cleanup_free_ char *a = NULL, *b = NULL;
+                        char *e;
+
+                        e = strchr(optarg, ':');
+                        if (e) {
+                                a = strndup(optarg, e - optarg);
+                                b = strdup(e + 1);
+                        } else {
+                                a = strdup(optarg);
+                                b = strdup("mode=0755");
+                        }
+
+                        if (!a || !b)
+                                return log_oom();
+
+                        if (!path_is_absolute(a)) {
+                                log_error("Invalid tmpfs specification: %s", optarg);
+                                return -EINVAL;
+                        }
+
+                        r = strv_push(&arg_tmpfs, a);
+                        if (r < 0)
+                                return log_oom();
+
+                        a = NULL;
+
+                        r = strv_push(&arg_tmpfs, b);
+                        if (r < 0)
+                                return log_oom();
+
+                        b = NULL;
+
+                        break;
+                }
+
                 case ARG_SETENV: {
                         char **n;
 
@@ -561,17 +601,17 @@ static int mount_all(const char *dest) {
         } MountPoint;
 
         static const MountPoint mount_table[] = {
-                { "proc",      "/proc",     "proc",  NULL,       MS_NOSUID|MS_NOEXEC|MS_NODEV, true  },
-                { "/proc/sys", "/proc/sys", NULL,    NULL,       MS_BIND, true                       },   /* Bind mount first */
-                { NULL,        "/proc/sys", NULL,    NULL,       MS_BIND|MS_RDONLY|MS_REMOUNT, true  },   /* Then, make it r/o */
-                { "sysfs",     "/sys",      "sysfs", NULL,       MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true  },
-                { "tmpfs",     "/dev",      "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME,     true  },
+                { "proc",      "/proc",     "proc",  NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV,           true  },
+                { "/proc/sys", "/proc/sys", NULL,    NULL,        MS_BIND,                                true  },   /* Bind mount first */
+                { NULL,        "/proc/sys", NULL,    NULL,        MS_BIND|MS_RDONLY|MS_REMOUNT,           true  },   /* Then, make it r/o */
+                { "sysfs",     "/sys",      "sysfs", NULL,        MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true  },
+                { "tmpfs",     "/dev",      "tmpfs", "mode=755",  MS_NOSUID|MS_STRICTATIME,               true  },
                 { "devpts",    "/dev/pts",  "devpts","newinstance,ptmxmode=0666,mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, true },
-                { "tmpfs",     "/dev/shm",  "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true  },
-                { "tmpfs",     "/run",      "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true  },
+                { "tmpfs",     "/dev/shm",  "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,      true  },
+                { "tmpfs",     "/run",      "tmpfs", "mode=755",  MS_NOSUID|MS_NODEV|MS_STRICTATIME,      true  },
 #ifdef HAVE_SELINUX
-                { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND,                      false },  /* Bind mount first */
-                { NULL,              "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, false },  /* Then, make it r/o */
+                { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND,                              false },  /* Bind mount first */
+                { NULL,              "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT,         false },  /* Then, make it r/o */
 #endif
         };
 
@@ -640,7 +680,7 @@ static int mount_binds(const char *dest, char **l, bool ro) {
         char **x, **y;
 
         STRV_FOREACH_PAIR(x, y, l) {
-                char *where;
+                _cleanup_free_ char *where = NULL;
                 struct stat source_st, dest_st;
                 int r;
 
@@ -649,12 +689,14 @@ static int mount_binds(const char *dest, char **l, bool ro) {
                         return -errno;
                 }
 
-                where = strappenda(dest, *y);
+                where = strappend(dest, *y);
+                if (!where)
+                        return log_oom();
+
                 r = stat(where, &dest_st);
                 if (r == 0) {
                         if ((source_st.st_mode & S_IFMT) != (dest_st.st_mode & S_IFMT)) {
-                                log_error("The file types of %s and %s do not match. Refusing bind mount",
-                                                *x, where);
+                                log_error("The file types of %s and %s do not match. Refusing bind mount", *x, where);
                                 return -EINVAL;
                         }
                 } else if (errno == ENOENT) {
@@ -667,6 +709,7 @@ static int mount_binds(const char *dest, char **l, bool ro) {
                         log_error("Failed to bind mount %s: %m", *x);
                         return -errno;
                 }
+
                 /* Create the mount point, but be conservative -- refuse to create block
                 * and char devices. */
                 if (S_ISDIR(source_st.st_mode))
@@ -699,6 +742,27 @@ static int mount_binds(const char *dest, char **l, bool ro) {
         return 0;
 }
 
+static int mount_tmpfs(const char *dest) {
+        char **i, **o;
+
+        STRV_FOREACH_PAIR(i, o, arg_tmpfs) {
+                _cleanup_free_ char *where = NULL;
+
+                where = strappend(dest, *i);
+                if (!where)
+                        return log_oom();
+
+                mkdir_label(where, 0755);
+
+                if (mount("tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, *o) < 0) {
+                        log_error("tmpfs mount to %s failed: %m", where);
+                        return -errno;
+                }
+        }
+
+        return 0;
+}
+
 static int setup_timezone(const char *dest) {
         _cleanup_free_ char *where = NULL, *p = NULL, *q = NULL, *check = NULL, *what = NULL;
         char *z, *y;
@@ -2998,6 +3062,9 @@ int main(int argc, char *argv[]) {
                         if (mount_binds(arg_directory, arg_bind_ro, true) < 0)
                                 goto child_fail;
 
+                        if (mount_tmpfs(arg_directory) < 0)
+                                goto child_fail;
+
                         if (setup_kdbus(arg_directory, kdbus_domain) < 0)
                                 goto child_fail;
 
@@ -3248,6 +3315,7 @@ finish:
         strv_free(arg_network_macvlan);
         strv_free(arg_bind);
         strv_free(arg_bind_ro);
+        strv_free(arg_tmpfs);
 
         return r;
 }

commit 9339db7187c61eb7ae7e6ffcddb2b2f2686954eb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jun 11 00:12:21 2014 +0200

    tmpfiles: always recreate the most basic directory structure in /var
    
    Let's allow booting up with /var empty. Only create the most basic
    directories to get to a working directory structure and symlink set in
    /var.

diff --git a/Makefile.am b/Makefile.am
index c67f063..3ea95e9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1725,7 +1725,8 @@ dist_tmpfiles_DATA = \
 	tmpfiles.d/systemd.conf \
 	tmpfiles.d/systemd-nologin.conf \
 	tmpfiles.d/tmp.conf \
-	tmpfiles.d/x11.conf
+	tmpfiles.d/x11.conf \
+	tmpfiles.d/var.conf
 
 if HAVE_SYSV_COMPAT
 dist_tmpfiles_DATA += \
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 89f6c6b..4c0f23e 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -750,7 +750,7 @@ static int create_item(Item *i) {
                 }
 
                 if (!streq(i->argument, x)) {
-                        log_error("%s is not the right symlinks.", i->path);
+                        log_error("%s is not the right symlink.", i->path);
                         return -EEXIST;
                 }
 
diff --git a/tmpfiles.d/legacy.conf b/tmpfiles.d/legacy.conf
index a165687..3219672 100644
--- a/tmpfiles.d/legacy.conf
+++ b/tmpfiles.d/legacy.conf
@@ -11,6 +11,7 @@
 # systems.
 
 d /run/lock 0755 root root -
+L /var/lock - - - - ../run/lock
 
 # /run/lock/subsys is used for serializing SysV service execution, and
 # hence without use on SysV-less systems.
diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf
index 85dc356..9554f38 100644
--- a/tmpfiles.d/systemd.conf
+++ b/tmpfiles.d/systemd.conf
@@ -10,11 +10,6 @@
 d /run/user 0755 root root ~10d
 F! /run/utmp 0664 root utmp -
 
-f /var/log/wtmp 0664 root utmp -
-f /var/log/btmp 0600 root utmp -
-
-d /var/cache/man - - - 30d
-
 d /run/systemd/ask-password 0755 root root -
 d /run/systemd/seats 0755 root root -
 d /run/systemd/sessions 0755 root root -
diff --git a/tmpfiles.d/var.conf b/tmpfiles.d/var.conf
new file mode 100644
index 0000000..10d2e49
--- /dev/null
+++ b/tmpfiles.d/var.conf
@@ -0,0 +1,20 @@
+#  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.
+
+# See tmpfiles.d(5) for details
+
+L /var/run - - - - ../run
+
+d /var/log 0755 - - -
+f /var/log/wtmp 0664 root utmp -
+f /var/log/btmp 0600 root utmp -
+
+d /var/cache 0755 - - -
+d /var/cache/man - - - 30d
+
+d /var/lib 0755 - - -
+d /var/spool 0755 - - -

commit 61147436a37ecf523cf3a08f10d139371a4a55ad
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jun 11 00:07:07 2014 +0200

    update TODO

diff --git a/TODO b/TODO
index fdd1126..1d7df40 100644
--- a/TODO
+++ b/TODO
@@ -36,8 +36,6 @@ Features:
 
 * support setting empty environment variables with Environment= and EnvironmentFile=
 
-* tmpfiles: figure out relation between Z and m?
-
 * machined/machinectl: sort IP addresses we return by scope and protocol
 * machined: write NSS module for looking up IP addresses for machines
 



More information about the systemd-commits mailing list