[systemd-commits] 5 commits - src/core src/libsystemd-bus src/login src/machine src/nspawn

Lennart Poettering lennart at kemper.freedesktop.org
Wed Nov 6 02:32:21 CET 2013


 src/core/cgroup.c                |   16 ++++-----
 src/core/shutdown.c              |   16 +++++++--
 src/libsystemd-bus/bus-message.c |   15 ++++++++
 src/login/logind-core.c          |    4 +-
 src/machine/machine.c            |    7 +++
 src/machine/machined.c           |    9 +++--
 src/machine/machined.h           |    1 
 src/nspawn/nspawn.c              |   69 +++++++++++++++++++++++++++++++++++----
 8 files changed, 114 insertions(+), 23 deletions(-)

New commits:
commit 1f0cd86b3dc0f938ce179cdddc62fc0f584e599d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 6 02:05:06 2013 +0100

    nspawn: explicitly terminate machines when we exit nspawn
    
    https://bugs.freedesktop.org/show_bug.cgi?id=68370
    https://bugzilla.redhat.com/show_bug.cgi?id=988883

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 80903a7..9f88713 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -33,8 +33,6 @@
 #include <sys/prctl.h>
 #include <sys/capability.h>
 #include <getopt.h>
-#include <sys/poll.h>
-#include <sys/epoll.h>
 #include <termios.h>
 #include <sys/signalfd.h>
 #include <grp.h>
@@ -43,9 +41,9 @@
 #include <sys/socket.h>
 #include <linux/netlink.h>
 
-#include <systemd/sd-daemon.h>
-#include <systemd/sd-bus.h>
-
+#include "sd-daemon.h"
+#include "sd-bus.h"
+#include "sd-id128.h"
 #include "log.h"
 #include "util.h"
 #include "mkdir.h"
@@ -56,12 +54,12 @@
 #include "strv.h"
 #include "path-util.h"
 #include "loopback-setup.h"
-#include "sd-id128.h"
 #include "dev-setup.h"
 #include "fdset.h"
 #include "build.h"
 #include "fileio.h"
 #include "bus-util.h"
+#include "bus-error.h"
 #include "ptyfwd.h"
 
 #ifndef TTY_GID
@@ -955,10 +953,64 @@ static int register_machine(void) {
                         strempty(arg_directory),
                         !isempty(arg_slice), "Slice", "s", arg_slice);
         if (r < 0) {
-                log_error("Failed to register machine: %s", error.message ? error.message : strerror(-r));
+                log_error("Failed to register machine: %s", bus_error_message(&error, r));
+                return r;
+        }
+
+        return 0;
+}
+
+static int terminate_machine(pid_t pid) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        const char *path;
+        int r;
+
+        r = sd_bus_open_system(&bus);
+        if (r < 0) {
+                log_error("Failed to open system bus: %s", strerror(-r));
+                return r;
+        }
+
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.machine1",
+                        "/org/freedesktop/machine1",
+                        "org.freedesktop.machine1.Manager",
+                        "GetMachineByPID",
+                        &error,
+                        &reply,
+                        "u",
+                        (uint32_t) pid);
+        if (r < 0) {
+                /* Note that the machine might already have been
+                 * cleaned up automatically, hence don't consider it a
+                 * failure if we cannot get the machine object. */
+                log_debug("Failed to get machine: %s", bus_error_message(&error, r));
+                return 0;
+        }
+
+        r = sd_bus_message_read(reply, "o", &path);
+        if (r < 0) {
+                log_error("Failed to parse GetMachineByPID() reply: %s", bus_error_message(&error, r));
                 return r;
         }
 
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.machine1",
+                        path,
+                        "org.freedesktop.machine1.Machine",
+                        "Terminate",
+                        &error,
+                        NULL,
+                        NULL);
+        if (r < 0) {
+                log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
+                return 0;
+        }
+
         return 0;
 }
 
@@ -1391,6 +1443,9 @@ int main(int argc, char *argv[]) {
                 putc('\n', stdout);
 
                 /* Kill if it is not dead yet anyway */
+                terminate_machine(pid);
+
+                /* Redundant, but better safe than sorry */
                 kill(pid, SIGKILL);
 
                 k = wait_for_terminate(pid, &status);

commit d3e84ddb885e9d5f0ae9930eb905910e3a81f157
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 6 02:03:04 2013 +0100

    machined: keep track of the initial leader PID of a machine
    
    This way we can without races always determine the machine for a leader
    PID. This allows machine managers to query the machine for a forked off
    container/VM  without a race where the child might already have died
    before we could read the cgroup information from /proc/$PID/cgroup.

diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index 6506f22..9c31bf8 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -348,7 +348,7 @@ int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
 
         r = cg_pid_get_unit(pid, &unit);
         if (r < 0)
-                return r;
+                return 0;
 
         s = hashmap_get(m->session_units, unit);
         if (!s)
@@ -371,7 +371,7 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
 
         r = cg_pid_get_slice(pid, &unit);
         if (r < 0)
-                return r;
+                return 0;
 
         u = hashmap_get(m->user_units, unit);
         if (!u)
diff --git a/src/machine/machine.c b/src/machine/machine.c
index a33a111..cf3ef15 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -85,6 +85,9 @@ void machine_free(Machine *m) {
 
         hashmap_remove(m->manager->machines, m->name);
 
+        if (m->leader > 0)
+                hashmap_remove_value(m->manager->machine_leaders, UINT_TO_PTR(m->leader), m);
+
         sd_bus_message_unref(m->create_message);
 
         free(m->name);
@@ -263,6 +266,10 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
         if (m->started)
                 return 0;
 
+        r = hashmap_put(m->manager->machine_leaders, UINT_TO_PTR(m->leader), m);
+        if (r < 0)
+                return r;
+
         /* Create cgroup */
         r = machine_start_scope(m, properties, error);
         if (r < 0)
diff --git a/src/machine/machined.c b/src/machine/machined.c
index 25de0d5..a5f5293 100644
--- a/src/machine/machined.c
+++ b/src/machine/machined.c
@@ -46,8 +46,9 @@ Manager *manager_new(void) {
 
         m->machines = hashmap_new(string_hash_func, string_compare_func);
         m->machine_units = hashmap_new(string_hash_func, string_compare_func);
+        m->machine_leaders = hashmap_new(trivial_hash_func, trivial_compare_func);
 
-        if (!m->machines || !m->machine_units) {
+        if (!m->machines || !m->machine_units || !m->machine_leaders) {
                 manager_free(m);
                 return NULL;
         }
@@ -71,6 +72,7 @@ void manager_free(Manager *m) {
 
         hashmap_free(m->machines);
         hashmap_free(m->machine_units);
+        hashmap_free(m->machine_leaders);
 
         sd_bus_unref(m->bus);
         sd_event_unref(m->event);
@@ -108,9 +110,10 @@ int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
 
         r = cg_pid_get_unit(pid, &unit);
         if (r < 0)
-                return r;
+                mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
+        else
+                mm = hashmap_get(m->machine_units, unit);
 
-        mm = hashmap_get(m->machine_units, unit);
         if (!mm)
                 return 0;
 
diff --git a/src/machine/machined.h b/src/machine/machined.h
index dfb63bd..3f07d4d 100644
--- a/src/machine/machined.h
+++ b/src/machine/machined.h
@@ -40,6 +40,7 @@ struct Manager {
 
         Hashmap *machines;
         Hashmap *machine_units;
+        Hashmap *machine_leaders;
 
         LIST_HEAD(Machine, machine_gc_queue);
 };

commit cd6f997f71c3aba16aa08226d423d14cbc787f82
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 6 02:01:43 2013 +0100

    bus: handle serialization of NULL strings
    
    Instead of simply crashing be somewhat nicer and serialize a NULL string
    into the empty string and generate an error on signature and object path
    strings.

diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c
index e68b43b..437f6df 100644
--- a/src/libsystemd-bus/bus-message.c
+++ b/src/libsystemd-bus/bus-message.c
@@ -1347,14 +1347,29 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void
         switch (type) {
 
         case SD_BUS_TYPE_STRING:
+                /* To make things easy we'll serialize a NULL string
+                 * into the empty string */
+                p = strempty(p);
+
+                /* Fall through... */
         case SD_BUS_TYPE_OBJECT_PATH:
 
+                if (!p) {
+                        r = -EINVAL;
+                        goto fail;
+                }
+
                 align = 4;
                 sz = 4 + strlen(p) + 1;
                 break;
 
         case SD_BUS_TYPE_SIGNATURE:
 
+                if (!p) {
+                        r = -EINVAL;
+                        goto fail;
+                }
+
                 align = 1;
                 sz = 1 + strlen(p) + 1;
                 break;

commit 41f85451d36f14bfc2f78e687167eba9a2d4d67c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 5 22:17:03 2013 +0100

    shutdown: trim the cgroup tree on loop iteration
    
    This way we leave the cgroup empty before exiting in a container which
    makes sure the container manager will get cgroup notification event
    
    https://bugs.freedesktop.org/show_bug.cgi?id=68370
    https://bugzilla.redhat.com/show_bug.cgi?id=988883

diff --git a/src/core/shutdown.c b/src/core/shutdown.c
index 4709746..ea02b60 100644
--- a/src/core/shutdown.c
+++ b/src/core/shutdown.c
@@ -46,6 +46,7 @@
 #include "virt.h"
 #include "watchdog.h"
 #include "killall.h"
+#include "cgroup-util.h"
 
 #define FINALIZE_ATTEMPTS 50
 
@@ -131,12 +132,12 @@ static int pivot_to_new_root(void) {
 }
 
 int main(int argc, char *argv[]) {
-        _cleanup_free_ char *line = NULL;
-        int cmd, r;
-        unsigned retries;
         bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true;
         bool in_container, use_watchdog = false;
+        _cleanup_free_ char *line = NULL, *cgroup = NULL;
         char *arguments[3];
+        unsigned retries;
+        int cmd, r;
 
         /* suppress shutdown status output if 'quiet' is used  */
         r = read_one_line_file("/proc/cmdline", &line);
@@ -186,6 +187,8 @@ int main(int argc, char *argv[]) {
                 goto error;
         }
 
+        cg_get_root_path(&cgroup);
+
         use_watchdog = !!getenv("WATCHDOG_USEC");
 
         /* lock us into memory */
@@ -210,6 +213,13 @@ int main(int argc, char *argv[]) {
                 if (use_watchdog)
                         watchdog_ping();
 
+                /* Let's trim the cgroup tree on each iteration so
+                   that we leave an empty cgroup tree around, so that
+                   container managers get a nice notify event when we
+                   are down */
+                if (cgroup)
+                        cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false);
+
                 if (need_umount) {
                         log_info("Unmounting file systems.");
                         r = umount_all(&changed);

commit 15c60e99a974782351ca8a5ed438dc3729eb5fe7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Nov 5 22:14:52 2013 +0100

    cgroup: run PID 1 in the root cgroup
    
    This way cleaning up the cgroup tree on shutdown is a lot easier since
    we are in the root dir. Also PID 1 was previously artificially placed in
    system.slice, even though our rule actually was not to have processes in
    slices. The root slice otoh is magic anyway, so having PID 1 in there
    sounds less surprising.
    
    Of course, this means that PID is scheduled against the three top-level
    slices.

diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index f0a97e6..f2a99c7 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -589,8 +589,8 @@ pid_t unit_search_main_pid(Unit *u) {
 
 int manager_setup_cgroup(Manager *m) {
         _cleanup_free_ char *path = NULL;
+        char *e;
         int r;
-        char *e, *a;
 
         assert(m);
 
@@ -610,9 +610,13 @@ int manager_setup_cgroup(Manager *m) {
                 return r;
         }
 
-        /* Already in /system.slice? If so, let's cut this off again */
+        /* LEGACY: Already in /system.slice? If so, let's cut this
+         * off. This is to support live upgrades from older systemd
+         * versions where PID 1 was moved there. */
         if (m->running_as == SYSTEMD_SYSTEM) {
                 e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
+                if (!e)
+                        e = endswith(m->cgroup_root, "/system");
                 if (e)
                         *e = 0;
         }
@@ -643,12 +647,8 @@ int manager_setup_cgroup(Manager *m) {
                         log_debug("Release agent already installed.");
         }
 
-        /* 4. Realize the system slice and put us in there */
-        if (m->running_as == SYSTEMD_SYSTEM) {
-                a = strappenda(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
-                r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, a, 0);
-        } else
-                r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, 0);
+        /* 4. Make sure we are in the root cgroup */
+        r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, 0);
         if (r < 0) {
                 log_error("Failed to create root cgroup hierarchy: %s", strerror(-r));
                 return r;



More information about the systemd-commits mailing list