chiark / gitweb /
core: add transient units
[elogind.git] / src / core / mount.c
index 92e2f73..3cc3e65 100644 (file)
 #include <sys/epoll.h>
 #include <signal.h>
 
+#include "manager.h"
 #include "unit.h"
 #include "mount.h"
 #include "load-fragment.h"
 #include "load-dropin.h"
 #include "log.h"
+#include "sd-messages.h"
 #include "strv.h"
 #include "mkdir.h"
 #include "path-util.h"
@@ -80,6 +82,7 @@ static void mount_init(Unit *u) {
         }
 
         kill_context_init(&m->kill_context);
+        cgroup_context_init(&m->cgroup_context);
 
         /* We need to make sure that /bin/mount is always called in
          * the same process group as us, so that the autofs kernel
@@ -125,7 +128,8 @@ static void mount_done(Unit *u) {
         mount_parameters_done(&m->parameters_proc_self_mountinfo);
         mount_parameters_done(&m->parameters_fragment);
 
-        exec_context_done(&m->exec_context);
+        cgroup_context_done(&m->cgroup_context);
+        exec_context_done(&m->exec_context, manager_is_reloading_or_reexecuting(u->manager));
         exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
         m->control_command = NULL;
 
@@ -134,7 +138,7 @@ static void mount_done(Unit *u) {
         unit_unwatch_timer(u, &m->timer_watch);
 }
 
-static MountParameters* get_mount_parameters_fragment(Mount *m) {
+_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
         assert(m);
 
         if (m->from_fragment)
@@ -143,7 +147,7 @@ static MountParameters* get_mount_parameters_fragment(Mount *m) {
         return NULL;
 }
 
-static MountParameters* get_mount_parameters(Mount *m) {
+_pure_ static MountParameters* get_mount_parameters(Mount *m) {
         assert(m);
 
         if (m->from_proc_self_mountinfo)
@@ -221,9 +225,11 @@ static int mount_add_swap_links(Mount *m) {
 
         assert(m);
 
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP])
-                if ((r = swap_add_one_mount_link(SWAP(other), m)) < 0)
+        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP]) {
+                r = swap_add_one_mount_link(SWAP(other), m);
+                if (r < 0)
                         return r;
+        }
 
         return 0;
 }
@@ -234,9 +240,11 @@ static int mount_add_path_links(Mount *m) {
 
         assert(m);
 
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH])
-                if ((r = path_add_one_mount_link(PATH(other), m)) < 0)
+        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH]) {
+                r = path_add_one_mount_link(PATH(other), m);
+                if (r < 0)
                         return r;
+        }
 
         return 0;
 }
@@ -247,9 +255,11 @@ static int mount_add_automount_links(Mount *m) {
 
         assert(m);
 
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT])
-                if ((r = automount_add_one_mount_link(AUTOMOUNT(other), m)) < 0)
+        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT]) {
+                r = automount_add_one_mount_link(AUTOMOUNT(other), m);
+                if (r < 0)
                         return r;
+        }
 
         return 0;
 }
@@ -260,9 +270,11 @@ static int mount_add_socket_links(Mount *m) {
 
         assert(m);
 
-        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SOCKET])
-                if ((r = socket_add_one_mount_link(SOCKET(other), m)) < 0)
+        LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SOCKET]) {
+                r = socket_add_one_mount_link(SOCKET(other), m);
+                if (r < 0)
                         return r;
+        }
 
         return 0;
 }
@@ -283,7 +295,7 @@ static int mount_add_requires_mounts_links(Mount *m) {
 }
 
 static char* mount_test_option(const char *haystack, const char *needle) {
-        struct mntent me;
+        struct mntent me = { .mnt_opts = (char*) haystack };
 
         assert(needle);
 
@@ -293,9 +305,6 @@ static char* mount_test_option(const char *haystack, const char *needle) {
         if (!haystack)
                 return NULL;
 
-        zero(me);
-        me.mnt_opts = (char*) haystack;
-
         return hasmntopt(&me, needle);
 }
 
@@ -320,6 +329,12 @@ static bool mount_is_bind(MountParameters *p) {
         if (p->fstype && streq(p->fstype, "bind"))
                 return true;
 
+        if (mount_test_option(p->options, "rbind"))
+                return true;
+
+        if (p->fstype && streq(p->fstype, "rbind"))
+                return true;
+
         return false;
 }
 
@@ -352,17 +367,21 @@ static int mount_add_device_links(Mount *m) {
         if (!p->what)
                 return 0;
 
-        if (!mount_is_bind(p) &&
-            !path_equal(m->where, "/")) {
-                r = unit_add_node_link(UNIT(m), p->what, false);
-                if (r < 0)
-                        return r;
-        }
+        if (mount_is_bind(p))
+                return 0;
+
+        if (!is_device_path(p->what))
+                return 0;
+
+        if (path_equal(m->where, "/"))
+                return 0;
+
+        r = unit_add_node_link(UNIT(m), p->what, false);
+        if (r < 0)
+                return r;
 
         if (p->passno > 0 &&
-            !mount_is_bind(p) &&
-            !path_equal(m->where, "/") &&
-            UNIT(m)->manager->running_as == MANAGER_SYSTEM) {
+            UNIT(m)->manager->running_as == SYSTEMD_SYSTEM) {
                 char *name;
                 Unit *fsck;
                 /* Let's add in the fsck service */
@@ -374,7 +393,8 @@ static int mount_add_device_links(Mount *m) {
 
                 r = manager_load_unit_prepare(UNIT(m)->manager, name, NULL, NULL, &fsck);
                 if (r < 0) {
-                        log_warning("Failed to prepare unit %s: %s", name, strerror(-r));
+                        log_warning_unit(name,
+                                         "Failed to prepare unit %s: %s", name, strerror(-r));
                         free(name);
                         return r;
                 }
@@ -396,7 +416,7 @@ static int mount_add_quota_links(Mount *m) {
 
         assert(m);
 
-        if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
+        if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
                 return 0;
 
         p = get_mount_parameters_fragment(m);
@@ -418,31 +438,49 @@ static int mount_add_quota_links(Mount *m) {
 }
 
 static int mount_add_default_dependencies(Mount *m) {
-        int r;
+        const char *after, *after2, *online;
         MountParameters *p;
-        const char *after;
+        int r;
 
         assert(m);
 
-        if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
+        if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
                 return 0;
 
-        p = get_mount_parameters_fragment(m);
+        p = get_mount_parameters(m);
+
         if (!p)
                 return 0;
 
         if (path_equal(m->where, "/"))
                 return 0;
 
-        if (mount_is_network(p))
+        if (mount_is_network(p)) {
                 after = SPECIAL_REMOTE_FS_PRE_TARGET;
-        else
+                after2 = SPECIAL_NETWORK_TARGET;
+                online = SPECIAL_NETWORK_ONLINE_TARGET;
+        } else {
                 after = SPECIAL_LOCAL_FS_PRE_TARGET;
+                after2 = NULL;
+                online = NULL;
+        }
 
-        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, after, NULL, true);
+        r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
         if (r < 0)
                 return r;
 
+        if (after2) {
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after2, NULL, true);
+                if (r < 0)
+                        return r;
+        }
+
+        if (online) {
+                r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, online, NULL, true);
+                if (r < 0)
+                        return r;
+        }
+
         r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
         if (r < 0)
                 return r;
@@ -481,11 +519,13 @@ static int mount_fix_timeouts(Mount *m) {
         if (!t)
                 return -ENOMEM;
 
-        r = parse_usec(t, &u);
+        r = parse_sec(t, &u);
         free(t);
 
         if (r < 0) {
-                log_warning("Failed to parse timeout for %s, ignoring: %s", m->where, timeout);
+                log_warning_unit(UNIT(m)->id,
+                                 "Failed to parse timeout for %s, ignoring: %s",
+                                 m->where, timeout);
                 return r;
         }
 
@@ -517,22 +557,29 @@ static int mount_verify(Mount *m) {
         free(e);
 
         if (!b) {
-                log_error("%s's Where setting doesn't match unit name. Refusing.", UNIT(m)->id);
+                log_error_unit(UNIT(m)->id,
+                               "%s's Where setting doesn't match unit name. Refusing.",
+                               UNIT(m)->id);
                 return -EINVAL;
         }
 
         if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
-                log_error("Cannot create mount unit for API file system %s. Refusing.", m->where);
+                log_error_unit(UNIT(m)->id,
+                               "Cannot create mount unit for API file system %s. Refusing.",
+                               m->where);
                 return -EINVAL;
         }
 
         if (UNIT(m)->fragment_path && !m->parameters_fragment.what) {
-                log_error("%s's What setting is missing. Refusing.", UNIT(m)->id);
+                log_error_unit(UNIT(m)->id,
+                               "%s's What setting is missing. Refusing.", UNIT(m)->id);
                 return -EBADMSG;
         }
 
         if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) {
-                log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing.", UNIT(m)->id);
+                log_error_unit(UNIT(m)->id,
+                               "%s has PAM enabled. Kill mode must be set to control-group'. Refusing.",
+                               UNIT(m)->id);
                 return -EINVAL;
         }
 
@@ -543,10 +590,6 @@ static int mount_add_extras(Mount *m) {
         Unit *u = UNIT(m);
         int r;
 
-        r = unit_add_exec_dependencies(u, &m->exec_context);
-        if (r < 0)
-                return r;
-
         if (UNIT(m)->fragment_path)
                 m->from_fragment = true;
 
@@ -558,6 +601,10 @@ static int mount_add_extras(Mount *m) {
 
         path_kill_slashes(m->where);
 
+        r = unit_add_exec_dependencies(u, &m->exec_context);
+        if (r < 0)
+                return r;
+
         if (!UNIT(m)->description) {
                 r = unit_set_description(u, m->where);
                 if (r < 0)
@@ -602,7 +649,7 @@ static int mount_add_extras(Mount *m) {
                         return r;
         }
 
-        r = unit_add_default_cgroups(u);
+        r = unit_add_default_slice(u);
         if (r < 0)
                 return r;
 
@@ -694,15 +741,16 @@ static void mount_set_state(Mount *m, MountState state) {
                  state == MOUNT_UNMOUNTING_SIGTERM ||
                  state == MOUNT_UNMOUNTING_SIGKILL ||
                  state == MOUNT_FAILED) {
-               if (state != old_state)
-                       mount_notify_automount(m, -ENODEV);
-       }
+                if (state != old_state)
+                        mount_notify_automount(m, -ENODEV);
+        }
 
         if (state != old_state)
-                log_debug("%s changed %s -> %s",
-                          UNIT(m)->id,
-                          mount_state_to_string(old_state),
-                          mount_state_to_string(state));
+                log_debug_unit(UNIT(m)->id,
+                               "%s changed %s -> %s",
+                               UNIT(m)->id,
+                               mount_state_to_string(old_state),
+                               mount_state_to_string(state));
 
         unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
         m->reload_result = MOUNT_SUCCESS;
@@ -737,10 +785,12 @@ static int mount_coldplug(Unit *u) {
                         if (m->control_pid <= 0)
                                 return -EBADMSG;
 
-                        if ((r = unit_watch_pid(UNIT(m), m->control_pid)) < 0)
+                        r = unit_watch_pid(UNIT(m), m->control_pid);
+                        if (r < 0)
                                 return r;
 
-                        if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
+                        r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+                        if (r < 0)
                                 return r;
                 }
 
@@ -796,27 +846,31 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
         assert(c);
         assert(_pid);
 
-        if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
+        unit_realize_cgroup(UNIT(m));
+
+        r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+        if (r < 0)
                 goto fail;
 
-        if ((r = exec_spawn(c,
-                            NULL,
-                            &m->exec_context,
-                            NULL, 0,
-                            UNIT(m)->manager->environment,
-                            true,
-                            true,
-                            true,
-                            UNIT(m)->manager->confirm_spawn,
-                            UNIT(m)->cgroup_bondings,
-                            UNIT(m)->cgroup_attributes,
-                            NULL,
-                            UNIT(m)->id,
-                            NULL,
-                            &pid)) < 0)
+        r = exec_spawn(c,
+                       NULL,
+                       &m->exec_context,
+                       NULL, 0,
+                       UNIT(m)->manager->environment,
+                       true,
+                       true,
+                       true,
+                       UNIT(m)->manager->confirm_spawn,
+                       UNIT(m)->cgroup_mask,
+                       UNIT(m)->cgroup_path,
+                       UNIT(m)->id,
+                       NULL,
+                       &pid);
+        if (r < 0)
                 goto fail;
 
-        if ((r = unit_watch_pid(UNIT(m), pid)) < 0)
+        r = unit_watch_pid(UNIT(m), pid);
+        if (r < 0)
                 /* FIXME: we need to do something here */
                 goto fail;
 
@@ -836,6 +890,7 @@ static void mount_enter_dead(Mount *m, MountResult f) {
         if (f != MOUNT_SUCCESS)
                 m->result = f;
 
+        exec_context_tmp_dirs_done(&m->exec_context);
         mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
 }
 
@@ -850,53 +905,25 @@ static void mount_enter_mounted(Mount *m, MountResult f) {
 
 static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
         int r;
-        Set *pid_set = NULL;
-        bool wait_for_exit = false;
 
         assert(m);
 
         if (f != MOUNT_SUCCESS)
                 m->result = f;
 
-        if (m->kill_context.kill_mode != KILL_NONE) {
-                int sig = (state == MOUNT_MOUNTING_SIGTERM ||
-                           state == MOUNT_UNMOUNTING_SIGTERM ||
-                           state == MOUNT_REMOUNTING_SIGTERM) ? m->kill_context.kill_signal : SIGKILL;
-
-                if (m->control_pid > 0) {
-                        if (kill_and_sigcont(m->control_pid, sig) < 0 && errno != ESRCH)
-
-                                log_warning("Failed to kill control process %li: %m", (long) m->control_pid);
-                        else
-                                wait_for_exit = true;
-                }
-
-                if (m->kill_context.kill_mode == KILL_CONTROL_GROUP) {
-
-                        if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
-
-                        /* Exclude the control pid from being killed via the cgroup */
-                        if (m->control_pid > 0)
-                                if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0)
-                                        goto fail;
-
-                        r = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, sig, true, false, pid_set, NULL);
-                        if (r < 0) {
-                                if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
-                                        log_warning("Failed to kill control group: %s", strerror(-r));
-                        } else if (r > 0)
-                                wait_for_exit = true;
-
-                        set_free(pid_set);
-                        pid_set = NULL;
-                }
-        }
+        r = unit_kill_context(
+                        UNIT(m),
+                        &m->kill_context,
+                        state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM,
+                        -1,
+                        m->control_pid,
+                        false);
+        if (r < 0)
+                goto fail;
 
-        if (wait_for_exit) {
-                if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
+        if (r > 0) {
+                r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+                if (r < 0)
                         goto fail;
 
                 mount_set_state(m, state);
@@ -908,15 +935,29 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
         return;
 
 fail:
-        log_warning("%s failed to kill processes: %s", UNIT(m)->id, strerror(-r));
+        log_warning_unit(UNIT(m)->id,
+                         "%s failed to kill processes: %s", UNIT(m)->id, strerror(-r));
 
         if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
                 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
         else
                 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
+}
+
+void warn_if_dir_nonempty(const char *unit, const char* where) {
+        assert(unit);
+        assert(where);
+
+        if (dir_is_empty(where) > 0)
+                return;
 
-        if (pid_set)
-                set_free(pid_set);
+        log_struct_unit(LOG_NOTICE,
+                   unit,
+                   "MESSAGE=%s: Directory %s to mount over is not empty, mounting anyway.",
+                   unit, where,
+                   "WHERE=%s", where,
+                   MESSAGE_ID(SD_MESSAGE_OVERMOUNTING),
+                   NULL);
 }
 
 static void mount_enter_unmounting(Mount *m) {
@@ -944,7 +985,9 @@ static void mount_enter_unmounting(Mount *m) {
         return;
 
 fail:
-        log_warning("%s failed to run 'umount' task: %s", UNIT(m)->id, strerror(-r));
+        log_warning_unit(UNIT(m)->id,
+                         "%s failed to run 'umount' task: %s",
+                         UNIT(m)->id, strerror(-r));
         mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
 }
 
@@ -959,6 +1002,8 @@ static void mount_enter_mounting(Mount *m) {
 
         mkdir_p_label(m->where, m->directory_mode);
 
+        warn_if_dir_nonempty(m->meta.id, m->where);
+
         /* Create the source directory for bind-mounts if needed */
         p = get_mount_parameters_fragment(m);
         if (p && mount_is_bind(p))
@@ -981,7 +1026,8 @@ static void mount_enter_mounting(Mount *m) {
 
         mount_unwatch_control_pid(m);
 
-        if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
+        r = mount_spawn(m, m->control_command, &m->control_pid);
+        if (r < 0)
                 goto fail;
 
         mount_set_state(m, MOUNT_MOUNTING);
@@ -989,7 +1035,9 @@ static void mount_enter_mounting(Mount *m) {
         return;
 
 fail:
-        log_warning("%s failed to run 'mount' task: %s", UNIT(m)->id, strerror(-r));
+        log_warning_unit(UNIT(m)->id,
+                         "%s failed to run 'mount' task: %s",
+                         UNIT(m)->id, strerror(-r));
         mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
 }
 
@@ -1047,7 +1095,9 @@ static void mount_enter_remounting(Mount *m) {
         return;
 
 fail:
-        log_warning("%s failed to run 'remount' task: %s", UNIT(m)->id, strerror(-r));
+        log_warning_unit(UNIT(m)->id,
+                         "%s failed to run 'remount' task: %s",
+                         UNIT(m)->id, strerror(-r));
         m->reload_result = MOUNT_FAILURE_RESOURCES;
         mount_enter_mounted(m, MOUNT_SUCCESS);
 }
@@ -1134,6 +1184,8 @@ static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
         if (m->control_command_id >= 0)
                 unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
 
+        exec_context_serialize(&m->exec_context, UNIT(m), f);
+
         return 0;
 }
 
@@ -1149,7 +1201,7 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
                 MountState state;
 
                 if ((state = mount_state_from_string(value)) < 0)
-                        log_debug("Failed to parse state value %s", value);
+                        log_debug_unit(u->id, "Failed to parse state value %s", value);
                 else
                         m->deserialized_state = state;
         } else if (streq(key, "result")) {
@@ -1157,7 +1209,8 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
 
                 f = mount_result_from_string(value);
                 if (f < 0)
-                        log_debug("Failed to parse result value %s", value);
+                        log_debug_unit(UNIT(m)->id,
+                                       "Failed to parse result value %s", value);
                 else if (f != MOUNT_SUCCESS)
                         m->result = f;
 
@@ -1166,7 +1219,8 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
 
                 f = mount_result_from_string(value);
                 if (f < 0)
-                        log_debug("Failed to parse reload result value %s", value);
+                        log_debug_unit(UNIT(m)->id,
+                                       "Failed to parse reload result value %s", value);
                 else if (f != MOUNT_SUCCESS)
                         m->reload_result = f;
 
@@ -1174,38 +1228,56 @@ static int mount_deserialize_item(Unit *u, const char *key, const char *value, F
                 pid_t pid;
 
                 if (parse_pid(value, &pid) < 0)
-                        log_debug("Failed to parse control-pid value %s", value);
+                        log_debug_unit(UNIT(m)->id,
+                                       "Failed to parse control-pid value %s", value);
                 else
                         m->control_pid = pid;
         } else if (streq(key, "control-command")) {
                 MountExecCommand id;
 
                 if ((id = mount_exec_command_from_string(value)) < 0)
-                        log_debug("Failed to parse exec-command value %s", value);
+                        log_debug_unit(UNIT(m)->id,
+                                       "Failed to parse exec-command value %s", value);
                 else {
                         m->control_command_id = id;
                         m->control_command = m->exec_command + id;
                 }
+        } else if (streq(key, "tmp-dir")) {
+                char *t;
 
+                t = strdup(value);
+                if (!t)
+                        return log_oom();
+
+                m->exec_context.tmp_dir = t;
+        } else if (streq(key, "var-tmp-dir")) {
+                char *t;
+
+                t = strdup(value);
+                if (!t)
+                        return log_oom();
+
+                m->exec_context.var_tmp_dir = t;
         } else
-                log_debug("Unknown serialization key '%s'", key);
+                log_debug_unit(UNIT(m)->id,
+                               "Unknown serialization key '%s'", key);
 
         return 0;
 }
 
-static UnitActiveState mount_active_state(Unit *u) {
+_pure_ static UnitActiveState mount_active_state(Unit *u) {
         assert(u);
 
         return state_translation_table[MOUNT(u)->state];
 }
 
-static const char *mount_sub_state_to_string(Unit *u) {
+_pure_ static const char *mount_sub_state_to_string(Unit *u) {
         assert(u);
 
         return mount_state_to_string(MOUNT(u)->state);
 }
 
-static bool mount_check_gc(Unit *u) {
+_pure_ static bool mount_check_gc(Unit *u) {
         Mount *m = MOUNT(u);
 
         assert(m);
@@ -1246,8 +1318,9 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
         }
 
-        log_full(f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
-                 "%s mount process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
+        log_full_unit(f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, u->id,
+                      "%s mount process exited, code=%s status=%i",
+                      u->id, sigchld_code_to_string(code), status);
 
         /* Note that mount(8) returning and the kernel sending us a
          * mount table change event might happen out-of-order. If an
@@ -1314,27 +1387,33 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
 
         case MOUNT_MOUNTING:
         case MOUNT_MOUNTING_DONE:
-                log_warning("%s mounting timed out. Stopping.", u->id);
+                log_warning_unit(u->id,
+                                 "%s mounting timed out. Stopping.", u->id);
                 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         case MOUNT_REMOUNTING:
-                log_warning("%s remounting timed out. Stopping.", u->id);
+                log_warning_unit(u->id,
+                                 "%s remounting timed out. Stopping.", u->id);
                 m->reload_result = MOUNT_FAILURE_TIMEOUT;
                 mount_enter_mounted(m, MOUNT_SUCCESS);
                 break;
 
         case MOUNT_UNMOUNTING:
-                log_warning("%s unmounting timed out. Stopping.", u->id);
+                log_warning_unit(u->id,
+                                 "%s unmounting timed out. Stopping.", u->id);
                 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         case MOUNT_MOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning("%s mounting timed out. Killing.", u->id);
+                        log_warning_unit(u->id,
+                                         "%s mounting timed out. Killing.", u->id);
                         mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning("%s mounting timed out. Skipping SIGKILL. Ignoring.", u->id);
+                        log_warning_unit(u->id,
+                                         "%s mounting timed out. Skipping SIGKILL. Ignoring.",
+                                         u->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1345,10 +1424,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
 
         case MOUNT_REMOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning("%s remounting timed out. Killing.", u->id);
+                        log_warning_unit(u->id,
+                                         "%s remounting timed out. Killing.", u->id);
                         mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning("%s remounting timed out. Skipping SIGKILL. Ignoring.", u->id);
+                        log_warning_unit(u->id,
+                                         "%s remounting timed out. Skipping SIGKILL. Ignoring.",
+                                         u->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1359,10 +1441,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
 
         case MOUNT_UNMOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning("%s unmounting timed out. Killing.", u->id);
+                        log_warning_unit(u->id,
+                                         "%s unmounting timed out. Killing.", u->id);
                         mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning("%s unmounting timed out. Skipping SIGKILL. Ignoring.", u->id);
+                        log_warning_unit(u->id,
+                                         "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
+                                         u->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1374,7 +1459,9 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
         case MOUNT_MOUNTING_SIGKILL:
         case MOUNT_REMOUNTING_SIGKILL:
         case MOUNT_UNMOUNTING_SIGKILL:
-                log_warning("%s mount process still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(u->id,
+                                 "%s mount process still around after SIGKILL. Ignoring.",
+                                 u->id);
 
                 if (m->from_proc_self_mountinfo)
                         mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1400,6 +1487,7 @@ static int mount_add_one(
         bool delete;
         char *e, *w = NULL, *o = NULL, *f = NULL;
         MountParameters *p;
+        bool load_extras = false;
 
         assert(m);
         assert(what);
@@ -1445,17 +1533,42 @@ static int mount_add_one(
                         goto fail;
                 }
 
+                u->source_path = strdup("/proc/self/mountinfo");
+                if (!u->source_path) {
+                        r = -ENOMEM;
+                        goto fail;
+                }
+
+                r = unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_LOCAL_FS_TARGET, NULL, true);
+                if (r < 0)
+                        goto fail;
+
+                if (!path_equal(where, "/")) {
+                        r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
+                        if (r < 0)
+                                goto fail;
+                }
+
                 unit_add_to_load_queue(u);
         } else {
                 delete = false;
                 free(e);
 
-                if (u->load_state == UNIT_ERROR) {
+                if (!MOUNT(u)->where) {
+                        MOUNT(u)->where = strdup(where);
+                        if (!MOUNT(u)->where) {
+                                r = -ENOMEM;
+                                goto fail;
+                        }
+                }
+
+                if (u->load_state == UNIT_NOT_FOUND) {
                         u->load_state = UNIT_LOADED;
                         u->load_error = 0;
-                        r = mount_add_extras(MOUNT(u));
-                        if (r < 0)
-                                goto fail;
+
+                        /* Load in the extras later on, after we
+                         * finished initialization of the unit */
+                        load_extras = true;
                 }
         }
 
@@ -1486,6 +1599,12 @@ static int mount_add_one(
 
         p->passno = passno;
 
+        if (load_extras) {
+                r = mount_add_extras(MOUNT(u));
+                if (r < 0)
+                        goto fail;
+        }
+
         unit_add_to_dbus_queue(u);
 
         return 0;
@@ -1591,25 +1710,27 @@ static void mount_shutdown(Manager *m) {
 
 static int mount_enumerate(Manager *m) {
         int r;
-        struct epoll_event ev;
         assert(m);
 
         if (!m->proc_self_mountinfo) {
-                if (!(m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re")))
+                struct epoll_event ev = {
+                        .events = EPOLLPRI,
+                        .data.ptr = &m->mount_watch,
+                };
+
+                m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
+                if (!m->proc_self_mountinfo)
                         return -errno;
 
                 m->mount_watch.type = WATCH_MOUNT;
                 m->mount_watch.fd = fileno(m->proc_self_mountinfo);
 
-                zero(ev);
-                ev.events = EPOLLPRI;
-                ev.data.ptr = &m->mount_watch;
-
                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
                         return -errno;
         }
 
-        if ((r = mount_load_proc_self_mountinfo(m, false)) < 0)
+        r = mount_load_proc_self_mountinfo(m, false);
+        if (r < 0)
                 goto fail;
 
         return 0;
@@ -1630,7 +1751,8 @@ void mount_fd_event(Manager *m, int events) {
          * /proc/self/mountinfo file, which informs us about mounting
          * table changes */
 
-        if ((r = mount_load_proc_self_mountinfo(m, true)) < 0) {
+        r = mount_load_proc_self_mountinfo(m, true);
+        if (r < 0) {
                 log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-r));
 
                 /* Reset flags, just in case, for later calls */
@@ -1709,53 +1831,7 @@ static void mount_reset_failed(Unit *u) {
 }
 
 static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
-        Mount *m = MOUNT(u);
-        int r = 0;
-        Set *pid_set = NULL;
-
-        assert(m);
-
-        if (who == KILL_MAIN) {
-                dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Mount units have no main processes");
-                return -ESRCH;
-        }
-
-        if (m->control_pid <= 0 && who == KILL_CONTROL) {
-                dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
-                return -ESRCH;
-        }
-
-        if (who == KILL_CONTROL || who == KILL_ALL)
-                if (m->control_pid > 0)
-                        if (kill(m->control_pid, signo) < 0)
-                                r = -errno;
-
-        if (who == KILL_ALL) {
-                int q;
-
-                pid_set = set_new(trivial_hash_func, trivial_compare_func);
-                if (!pid_set)
-                        return -ENOMEM;
-
-                /* Exclude the control pid from being killed via the cgroup */
-                if (m->control_pid > 0) {
-                        q = set_put(pid_set, LONG_TO_PTR(m->control_pid));
-                        if (q < 0) {
-                                r = q;
-                                goto finish;
-                        }
-                }
-
-                q = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, signo, false, false, pid_set, NULL);
-                if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
-                        r = q;
-        }
-
-finish:
-        if (pid_set)
-                set_free(pid_set);
-
-        return r;
+        return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
 }
 
 static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
@@ -1797,13 +1873,16 @@ DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
 
 const UnitVTable mount_vtable = {
         .object_size = sizeof(Mount),
-        .exec_context_offset = offsetof(Mount, exec_context),
 
         .sections =
                 "Unit\0"
                 "Mount\0"
                 "Install\0",
 
+        .private_section = "Mount",
+        .exec_context_offset = offsetof(Mount, exec_context),
+        .cgroup_context_offset = offsetof(Mount, cgroup_context),
+
         .no_alias = true,
         .no_instances = true,
 
@@ -1837,6 +1916,8 @@ const UnitVTable mount_vtable = {
         .bus_interface = "org.freedesktop.systemd1.Mount",
         .bus_message_handler = bus_mount_message_handler,
         .bus_invalidating_properties =  bus_mount_invalidating_properties,
+        .bus_set_property = bus_mount_set_property,
+        .bus_commit_properties = bus_mount_commit_properties,
 
         .enumerate = mount_enumerate,
         .shutdown = mount_shutdown,