[systemd-commits] 7 commits - TODO man/systemd-nspawn.xml src/core src/journal src/machine src/nspawn src/shared src/systemctl src/sysusers src/test

Lennart Poettering lennart at kemper.freedesktop.org
Fri Dec 12 08:30:37 PST 2014


 TODO                       |    3 +-
 man/systemd-nspawn.xml     |   45 ++++++++++++++++++++----------
 src/core/ima-setup.c       |    2 -
 src/journal/coredump.c     |    2 -
 src/machine/machine-dbus.c |    2 -
 src/nspawn/nspawn.c        |   67 +++++++++++++++++++++++++++++++++++++--------
 src/shared/copy.c          |   14 ++++-----
 src/shared/copy.h          |    4 +-
 src/shared/util.c          |   52 +++++++++++++++++++++++++++++++++-
 src/shared/util.h          |    1 
 src/systemctl/systemctl.c  |    4 +-
 src/sysusers/sysusers.c    |    2 -
 src/test/test-copy.c       |    4 +-
 13 files changed, 156 insertions(+), 46 deletions(-)

New commits:
commit 98cd2651988619bf606f0b27825440c4638a7e0b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 12 17:30:02 2014 +0100

    update TODO

diff --git a/TODO b/TODO
index 89dbd13..19459b3 100644
--- a/TODO
+++ b/TODO
@@ -35,6 +35,8 @@ External:
 
 Features:
 
+* when a start job for a device unit is queued, when systemd runs in a container, make it fail immediately instead of wait for all eternity
+
 * port libmount hookup to use API's own inotify interface, as soon as that is table in libmount
 
 * bash completion for busctl, to make it truly useful
@@ -558,7 +560,6 @@ Features:
 * nspawn:
   - bind mount read-only the cgroup tree higher than nspawn
   - refuses to boot containers without /etc/machine-id (OK?), and with empty /etc/machine-id (not OK).
-  - support taking a btrfs snapshot at startup and dropping it afterwards
   - introduce machines.target to order after all nspawn instances
   - systemd-nspawn at .service should fail if some nspawn arg is invalid, with Type=notify
   - PID 1 doesn't apply nspawns devices cgroup policy

commit 667993e88eb7519c6674fe9a9e985619817465e0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 12 17:29:12 2014 +0100

    man: fedora 21 has been release, suggest 21 as fedora version in example yum command line

diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index d7d60e5..fdb0c29 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -780,7 +780,7 @@
                 <example>
                         <title>Boot a minimal Fedora distribution in a container</title>
 
-                        <programlisting># yum -y --releasever=19 --nogpg --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=fedora install systemd passwd yum fedora-release vim-minimal
+                        <programlisting># yum -y --releasever=21 --nogpg --installroot=/srv/mycontainer --disablerepo='*' --enablerepo=fedora install systemd passwd yum fedora-release vim-minimal
 # systemd-nspawn -bD /srv/mycontainer</programlisting>
 
                         <para>This installs a minimal Fedora distribution into

commit b9ba4dabbab8a58a044ec42655e11e65bd3ecc47
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 12 17:26:31 2014 +0100

    nspawn: when booting in ephemeral mode, append random token to machine name
    
    Also, when booting up an ephemeral container of / use the system
    hostname as default machine name.
    
    This way specifiyng -M is unnecessary when booting up an ephemeral
    container, while allowing any number of ephemeral containers to run from
    the same tree.

diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index b66c34d..d7d60e5 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -231,8 +231,10 @@
                                 its root directory (as configured with
                                 <option>--directory=</option>), that
                                 is removed immediately when the
-                                container terminates. May not be
-                                specified together with
+                                container terminates. This option is
+                                only supported if the root file system
+                                is <literal>btrfs</literal>. May not
+                                be specified together with
                                 <option>--image=</option> or
                                 <option>--template=</option>.</para></listitem>
                         </varlistentry>
@@ -303,13 +305,22 @@
 
                                 <listitem><para>Sets the machine name
                                 for this container. This name may be
-                                used to identify this container on the
-                                host, and is used to initialize the
-                                container's hostname (which the
-                                container can choose to override,
-                                however). If not specified, the last
-                                component of the root directory of the
-                                container is used.</para></listitem>
+                                used to identify this container during
+                                its runtime (for example in tools like
+                                <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                                and similar), and is used to
+                                initialize the container's hostname
+                                (which the container can choose to
+                                override, however). If not specified,
+                                the last component of the root
+                                directory path of the container is
+                                used, possibly suffixed with a random
+                                identifier in case
+                                <option>--ephemeral</option> mode is
+                                selected. If the root directory
+                                selected is the host's root directory
+                                the host's hostname is used as default
+                                instead.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
@@ -814,13 +825,16 @@
                 </example>
 
                 <example>
-                        <title>Boot into a <literal>btrfs</literal> snapshot of the host system</title>
+                        <title>Boot into an ephemeral <literal>btrfs</literal> snapshot of the host system</title>
 
-                        <programlisting># btrfs subvolume snapshot / /.tmp
-# systemd-nspawn --private-network -D /.tmp -b</programlisting>
+                        <programlisting># systemd-nspawn -D / -xb</programlisting>
 
                         <para>This runs a copy of the host system in a
-                        <literal>btrfs</literal> snapshot.</para>
+                        <literal>btrfs</literal> snapshot which is
+                        removed immediately when the container
+                        exits. All file system changes made during
+                        runtime will be lost on shutdown,
+                        hence.</para>
                 </example>
 
                 <example>
@@ -847,7 +861,8 @@
                         <citerefentry project='die-net'><refentrytitle>debootstrap</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                         <citerefentry project='archlinux'><refentrytitle>pacman</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.slice</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-                        <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                        <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>btrfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>
                 </para>
         </refsect1>
 
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 651a451..9ca53cd 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -2875,7 +2875,11 @@ static int determine_names(void) {
         }
 
         if (!arg_machine) {
-                arg_machine = strdup(basename(arg_image ?: arg_directory));
+                if (arg_directory && path_equal(arg_directory, "/"))
+                        arg_machine = gethostname_malloc();
+                else
+                        arg_machine = strdup(basename(arg_image ?: arg_directory));
+
                 if (!arg_machine)
                         return log_oom();
 
@@ -2884,6 +2888,21 @@ static int determine_names(void) {
                         log_error("Failed to determine machine name automatically, please use -M.");
                         return -EINVAL;
                 }
+
+                if (arg_ephemeral) {
+                        char *b;
+
+                        /* Add a random suffix when this is an
+                         * ephemeral machine, so that we can run many
+                         * instances at once without manually having
+                         * to specify -M each time. */
+
+                        if (asprintf(&b, "%s-%016" PRIx64, arg_machine, random_u64()) < 0)
+                                return log_oom();
+
+                        free(arg_machine);
+                        arg_machine = b;
+                }
         }
 
         return 0;

commit c4e34a612c81266773cf8358cb38a43d2e43474e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 12 16:59:15 2014 +0100

    nspawn: allow spawning ephemeral nspawn containers based on the root file system of the OS
    
    This works now:
    
            # systemd-nspawn -xb -D / -M foobar
    
    Which boots up an ephemeral container, based on the host's root file
    system. Or in other words: you can now run the very same host OS you
    booted your system with also in a container, on top of it, without
    having it interfere. Great for testing whether the init system you are
    hacking on still boots without reboot the system!

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index f6f20ab..651a451 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -2942,8 +2942,8 @@ int main(int argc, char *argv[]) {
         if (arg_directory) {
                 assert(!arg_image);
 
-                if (path_equal(arg_directory, "/")) {
-                        log_error("Spawning container on root directory not supported.");
+                if (path_equal(arg_directory, "/") && !arg_ephemeral) {
+                        log_error("Spawning container on root directory is not supported. Consider using --ephemeral.");
                         r = -EINVAL;
                         goto finish;
                 }
@@ -2964,7 +2964,21 @@ int main(int argc, char *argv[]) {
                 } else if (arg_ephemeral) {
                         char *np;
 
-                        r = tempfn_random(arg_directory, &np);
+                        /* If the specified path is a mount point we
+                         * generate the new snapshot immediately
+                         * inside it under a random name. However if
+                         * the specified is not a mount point we
+                         * create the new snapshot in the parent
+                         * directory, just next to it. */
+                        r = path_is_mount_point(arg_directory, false);
+                        if (r < 0) {
+                                log_error_errno(r, "Failed to determine whether directory %s is mount point: %m", arg_directory);
+                                goto finish;
+                        }
+                        if (r > 0)
+                                r = tempfn_random_child(arg_directory, &np);
+                        else
+                                r = tempfn_random(arg_directory, &np);
                         if (r < 0) {
                                 log_error_errno(r, "Failed to generate name for snapshot: %m");
                                 goto finish;
diff --git a/src/shared/util.c b/src/shared/util.c
index 254b563..ee95a4b 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -6977,6 +6977,14 @@ int tempfn_xxxxxx(const char *p, char **ret) {
         assert(p);
         assert(ret);
 
+        /*
+         * Turns this:
+         *         /foo/bar/waldo
+         *
+         * Into this:
+         *         /foo/bar/.waldoXXXXXX
+         */
+
         fn = basename(p);
         if (!filename_is_valid(fn))
                 return -EINVAL;
@@ -6987,7 +6995,7 @@ int tempfn_xxxxxx(const char *p, char **ret) {
 
         strcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), "."), fn), "XXXXXX");
 
-        *ret = t;
+        *ret = path_kill_slashes(t);
         return 0;
 }
 
@@ -7000,6 +7008,14 @@ int tempfn_random(const char *p, char **ret) {
         assert(p);
         assert(ret);
 
+        /*
+         * Turns this:
+         *         /foo/bar/waldo
+         *
+         * Into this:
+         *         /foo/bar/.waldobaa2a261115984a9
+         */
+
         fn = basename(p);
         if (!filename_is_valid(fn))
                 return -EINVAL;
@@ -7018,7 +7034,39 @@ int tempfn_random(const char *p, char **ret) {
 
         *x = 0;
 
-        *ret = t;
+        *ret = path_kill_slashes(t);
+        return 0;
+}
+
+int tempfn_random_child(const char *p, char **ret) {
+        char *t, *x;
+        uint64_t u;
+        unsigned i;
+
+        assert(p);
+        assert(ret);
+
+        /* Turns this:
+         *         /foo/bar/waldo
+         * Into this:
+         *         /foo/bar/waldo/.3c2b6219aa75d7d0
+         */
+
+        t = new(char, strlen(p) + 2 + 16 + 1);
+        if (!t)
+                return -ENOMEM;
+
+        x = stpcpy(stpcpy(t, p), "/.");
+
+        u = random_u64();
+        for (i = 0; i < 16; i++) {
+                *(x++) = hexchar(u & 0xF);
+                u >>= 4;
+        }
+
+        *x = 0;
+
+        *ret = path_kill_slashes(t);
         return 0;
 }
 
diff --git a/src/shared/util.h b/src/shared/util.h
index 9a878ca..a8ccf20 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -1018,6 +1018,7 @@ int fflush_and_check(FILE *f);
 
 int tempfn_xxxxxx(const char *p, char **ret);
 int tempfn_random(const char *p, char **ret);
+int tempfn_random_child(const char *p, char **ret);
 
 bool is_localhost(const char *hostname);
 

commit df9a75e480ecbfe230589a7c1e8e0bb790ee0595
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 12 16:58:57 2014 +0100

    nspawn: don't link journals in ephemeral mode

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 8082166..f6f20ab 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -687,6 +687,11 @@ static int parse_argv(int argc, char *argv[]) {
                 return -EINVAL;
         }
 
+        if (arg_ephemeral && !IN_SET(arg_link_journal, LINK_NO, LINK_AUTO)) {
+                log_error("--ephemeral and --link-journal= may not be combined.");
+                return -EINVAL;
+        }
+
         if (arg_volatile != VOLATILE_NO && arg_read_only) {
                 log_error("Cannot combine --read-only with --volatile. Note that --volatile already implies a read-only base hierarchy.");
                 return -EINVAL;
@@ -1317,6 +1322,10 @@ static int setup_journal(const char *directory) {
         char *id;
         int r;
 
+        /* Don't link journals in ephemeral mode */
+        if (arg_ephemeral)
+                return 0;
+
         p = strappend(directory, "/etc/machine-id");
         if (!p)
                 return log_oom();
@@ -1345,8 +1354,7 @@ static int setup_journal(const char *directory) {
                          "Host and machine ids are equal (%s): refusing to link journals", id);
                 if (arg_link_journal == LINK_AUTO)
                         return 0;
-                return
-                        -EEXIST;
+                return -EEXIST;
         }
 
         if (arg_link_journal == LINK_NO)

commit 53e438e3016e6b8304834d784fd0bbfeeb17cb77
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 12 16:58:30 2014 +0100

    nspawn: properly unset arg_link_journal_try, when --link-journal= is specified

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 1bfc99d..8082166 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -477,15 +477,19 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_LINK_JOURNAL:
-                        if (streq(optarg, "auto"))
+                        if (streq(optarg, "auto")) {
                                 arg_link_journal = LINK_AUTO;
-                        else if (streq(optarg, "no"))
+                                arg_link_journal_try = false;
+                        } else if (streq(optarg, "no")) {
                                 arg_link_journal = LINK_NO;
-                        else if (streq(optarg, "guest"))
+                                arg_link_journal_try = false;
+                        } else if (streq(optarg, "guest")) {
                                 arg_link_journal = LINK_GUEST;
-                        else if (streq(optarg, "host"))
+                                arg_link_journal_try = false;
+                        } else if (streq(optarg, "host")) {
                                 arg_link_journal = LINK_HOST;
-                        else if (streq(optarg, "try-guest")) {
+                                arg_link_journal_try = false;
+                        } else if (streq(optarg, "try-guest")) {
                                 arg_link_journal = LINK_GUEST;
                                 arg_link_journal_try = true;
                         } else if (streq(optarg, "try-host")) {

commit 7430ec6ac08f2c0416d9f806964c46b30f3862b2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Dec 12 16:24:33 2014 +0100

    copy: use btrfs reflinking only whe we know we copy full files

diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c
index 8e4fed1..0e0d16a 100644
--- a/src/core/ima-setup.c
+++ b/src/core/ima-setup.c
@@ -66,7 +66,7 @@ int ima_setup(void) {
                 return 0;
         }
 
-        r = copy_bytes(policyfd, imafd, -1);
+        r = copy_bytes(policyfd, imafd, (off_t) -1, false);
         if (r < 0)
                 log_error_errno(r, "Failed to load the IMA custom policy file "IMA_POLICY_PATH": %m");
         else
diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index 8678ec6..a37e5eb 100644
--- a/src/journal/coredump.c
+++ b/src/journal/coredump.c
@@ -316,7 +316,7 @@ static int save_external_coredump(
         if (fd < 0)
                 return log_error_errno(errno, "Failed to create coredump file %s: %m", tmp);
 
-        r = copy_bytes(STDIN_FILENO, fd, arg_process_size_max);
+        r = copy_bytes(STDIN_FILENO, fd, arg_process_size_max, false);
         if (r == -EFBIG) {
                 log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", info[INFO_PID], info[INFO_COMM]);
                 goto fail;
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 72ae6c6..f6fd9cf 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -344,7 +344,7 @@ int bus_machine_method_get_os_release(sd_bus *bus, sd_bus_message *message, void
                                 _exit(EXIT_FAILURE);
                 }
 
-                r = copy_bytes(fd, pair[1], (off_t) -1);
+                r = copy_bytes(fd, pair[1], (off_t) -1, false);
                 if (r < 0)
                         _exit(EXIT_FAILURE);
 
diff --git a/src/shared/copy.c b/src/shared/copy.c
index 233dbbc..b4a85c7 100644
--- a/src/shared/copy.c
+++ b/src/shared/copy.c
@@ -25,7 +25,7 @@
 #include "btrfs-util.h"
 #include "copy.h"
 
-int copy_bytes(int fdf, int fdt, off_t max_bytes) {
+int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) {
         bool try_sendfile = true;
         int r;
 
@@ -33,10 +33,10 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes) {
         assert(fdt >= 0);
 
         /* Try btrfs reflinks first. */
-        if (max_bytes == (off_t) -1) {
+        if (try_reflink && max_bytes == (off_t) -1) {
                 r = btrfs_reflink(fdf, fdt);
                 if (r >= 0)
-                        return 0;
+                        return r;
         }
 
         for (;;) {
@@ -131,7 +131,7 @@ static int fd_copy_regular(int df, const char *from, const struct stat *st, int
         if (fdt < 0)
                 return -errno;
 
-        r = copy_bytes(fdf, fdt, (off_t) -1);
+        r = copy_bytes(fdf, fdt, (off_t) -1, true);
         if (r < 0) {
                 unlinkat(dt, to, 0);
                 return r;
@@ -318,7 +318,7 @@ int copy_tree_fd(int dirfd, const char *to, bool merge) {
         return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, merge);
 }
 
-int copy_file_fd(const char *from, int fdt) {
+int copy_file_fd(const char *from, int fdt, bool try_reflink) {
         _cleanup_close_ int fdf = -1;
 
         assert(from);
@@ -328,7 +328,7 @@ int copy_file_fd(const char *from, int fdt) {
         if (fdf < 0)
                 return -errno;
 
-        return copy_bytes(fdf, fdt, (off_t) -1);
+        return copy_bytes(fdf, fdt, (off_t) -1, try_reflink);
 }
 
 int copy_file(const char *from, const char *to, int flags, mode_t mode) {
@@ -341,7 +341,7 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode) {
         if (fdt < 0)
                 return -errno;
 
-        r = copy_file_fd(from, fdt);
+        r = copy_file_fd(from, fdt, true);
         if (r < 0) {
                 close(fdt);
                 unlink(to);
diff --git a/src/shared/copy.h b/src/shared/copy.h
index 15faf54..201fe69 100644
--- a/src/shared/copy.h
+++ b/src/shared/copy.h
@@ -24,8 +24,8 @@
 #include <stdbool.h>
 #include <sys/types.h>
 
-int copy_file_fd(const char *from, int to);
+int copy_file_fd(const char *from, int to, bool try_reflink);
 int copy_file(const char *from, const char *to, int flags, mode_t mode);
 int copy_tree(const char *from, const char *to, bool merge);
 int copy_tree_fd(int dirfd, const char *to, bool merge);
-int copy_bytes(int fdf, int fdt, off_t max_bytes);
+int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 5ed430c..a75e9de 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -4641,7 +4641,7 @@ static int cat(sd_bus *bus, char **args) {
                                ansi_highlight_off());
                         fflush(stdout);
 
-                        r = copy_file_fd(fragment_path, STDOUT_FILENO);
+                        r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
                         if (r < 0) {
                                 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
                                 continue;
@@ -4656,7 +4656,7 @@ static int cat(sd_bus *bus, char **args) {
                                ansi_highlight_off());
                         fflush(stdout);
 
-                        r = copy_file_fd(*path, STDOUT_FILENO);
+                        r = copy_file_fd(*path, STDOUT_FILENO, false);
                         if (r < 0) {
                                 log_warning_errno(r, "Failed to cat %s: %m", *path);
                                 continue;
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 647eb57..0baa2c3 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -215,7 +215,7 @@ static int make_backup(const char *target, const char *x) {
         if (r < 0)
                 return r;
 
-        r = copy_bytes(src, fileno(dst), (off_t) -1);
+        r = copy_bytes(src, fileno(dst), (off_t) -1, true);
         if (r < 0)
                 goto fail;
 
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index d2cad08..d70a0be 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -67,8 +67,8 @@ static void test_copy_file_fd(void) {
         assert_se(out_fd >= 0);
 
         assert_se(write_string_file(in_fn, text) == 0);
-        assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd) < 0);
-        assert_se(copy_file_fd(in_fn, out_fd) >= 0);
+        assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd, true) < 0);
+        assert_se(copy_file_fd(in_fn, out_fd, true) >= 0);
         assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
 
         assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);



More information about the systemd-commits mailing list