chiark / gitweb /
core: move ManagerRunningAs to shared
[elogind.git] / src / core / mount.c
index 760ffcdbf6e983542828e876fc3a4a9ef1bd67ee..66ef0cd25c3714bee713c738d7bda7483c46b511 100644 (file)
@@ -32,6 +32,7 @@
 #include "log.h"
 #include "strv.h"
 #include "mkdir.h"
+#include "path-util.h"
 #include "mount-setup.h"
 #include "unit-name.h"
 #include "dbus-mount.h"
@@ -67,13 +68,19 @@ static void mount_init(Unit *u) {
 
         exec_context_init(&m->exec_context);
 
-        /* The stdio/kmsg bridge socket is on /, in order to avoid a
-         * dep loop, don't use kmsg logging for -.mount */
-        if (!unit_has_name(u, "-.mount")) {
+        if (unit_has_name(u, "-.mount")) {
+                /* Don't allow start/stop for root directory */
+                UNIT(m)->refuse_manual_start = true;
+                UNIT(m)->refuse_manual_stop = true;
+        } else {
+                /* The stdio/kmsg bridge socket is on /, in order to avoid a
+                 * dep loop, don't use kmsg logging for -.mount */
                 m->exec_context.std_output = u->manager->default_std_output;
                 m->exec_context.std_error = u->manager->default_std_error;
         }
 
+        kill_context_init(&m->kill_context);
+
         /* We need to make sure that /bin/mount is always called in
          * the same process group as us, so that the autofs kernel
          * side doesn't send us another mount request while we are
@@ -115,7 +122,6 @@ static void mount_done(Unit *u) {
         free(m->where);
         m->where = NULL;
 
-        mount_parameters_done(&m->parameters_etc_fstab);
         mount_parameters_done(&m->parameters_proc_self_mountinfo);
         mount_parameters_done(&m->parameters_fragment);
 
@@ -128,13 +134,11 @@ static void mount_done(Unit *u) {
         unit_unwatch_timer(u, &m->timer_watch);
 }
 
-static MountParameters* get_mount_parameters_configured(Mount *m) {
+static MountParameters* get_mount_parameters_fragment(Mount *m) {
         assert(m);
 
         if (m->from_fragment)
                 return &m->parameters_fragment;
-        else if (m->from_etc_fstab)
-                return &m->parameters_etc_fstab;
 
         return NULL;
 }
@@ -145,7 +149,7 @@ static MountParameters* get_mount_parameters(Mount *m) {
         if (m->from_proc_self_mountinfo)
                 return &m->parameters_proc_self_mountinfo;
 
-        return get_mount_parameters_configured(m);
+        return get_mount_parameters_fragment(m);
 }
 
 static int mount_add_mount_links(Mount *m) {
@@ -155,7 +159,7 @@ static int mount_add_mount_links(Mount *m) {
 
         assert(m);
 
-        pm = get_mount_parameters_configured(m);
+        pm = get_mount_parameters_fragment(m);
 
         /* Adds in links to other mount points that might lie below or
          * above us in the hierarchy */
@@ -170,7 +174,7 @@ static int mount_add_mount_links(Mount *m) {
                 if (UNIT(n)->load_state != UNIT_LOADED)
                         continue;
 
-                pn = get_mount_parameters_configured(n);
+                pn = get_mount_parameters_fragment(n);
 
                 if (path_startswith(m->where, n->where)) {
 
@@ -263,6 +267,21 @@ static int mount_add_socket_links(Mount *m) {
         return 0;
 }
 
+static int mount_add_requires_mounts_links(Mount *m) {
+        Unit *other;
+        int r;
+
+        assert(m);
+
+        LIST_FOREACH(has_requires_mounts_for, other, UNIT(m)->manager->has_requires_mounts_for) {
+                r = unit_add_one_mount_link(other, m);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
 static char* mount_test_option(const char *haystack, const char *needle) {
         struct mntent me;
 
@@ -320,165 +339,113 @@ static bool needs_quota(MountParameters *p) {
                 mount_test_option(p->options, "grpjquota");
 }
 
-static int mount_add_fstab_links(Mount *m) {
-        const char *target, *after, *tu_wants = NULL;
-        MountParameters *p;
-        Unit *tu;
-        int r;
-        bool noauto, nofail, handle, automount;
-
-        assert(m);
-
-        if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
-                return 0;
-
-        if (!(p = get_mount_parameters_configured(m)))
-                return 0;
-
-        if (p != &m->parameters_etc_fstab)
-                return 0;
-
-        noauto = !!mount_test_option(p->options, "noauto");
-        nofail = !!mount_test_option(p->options, "nofail");
-        automount =
-                mount_test_option(p->options, "comment=systemd.automount") ||
-                mount_test_option(p->options, "x-systemd-automount");
-        handle =
-                automount ||
-                mount_test_option(p->options, "comment=systemd.mount") ||
-                mount_test_option(p->options, "x-systemd-mount") ||
-                UNIT(m)->manager->mount_auto;
-
-        if (mount_is_network(p)) {
-                target = SPECIAL_REMOTE_FS_TARGET;
-                after = tu_wants = SPECIAL_REMOTE_FS_PRE_TARGET;
-        } else {
-                target = SPECIAL_LOCAL_FS_TARGET;
-                after = SPECIAL_LOCAL_FS_PRE_TARGET;
-        }
-
-        r = manager_load_unit(UNIT(m)->manager, target, NULL, NULL, &tu);
-        if (r < 0)
-                return r;
-
-        if (tu_wants) {
-                r = unit_add_dependency_by_name(tu, UNIT_WANTS, tu_wants, NULL, true);
-                if (r < 0)
-                        return r;
-        }
-
-        if (after) {
-                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
-                if (r < 0)
-                        return r;
-        }
-
-        if (automount) {
-                Unit *am;
-
-                if ((r = unit_load_related_unit(UNIT(m), ".automount", &am)) < 0)
-                        return r;
-
-                /* If auto is configured as well also pull in the
-                 * mount right-away, but don't rely on it. */
-                if (!noauto) /* automount + auto */
-                        if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0)
-                                return r;
-
-                /* Install automount unit */
-                if (!nofail) /* automount + fail */
-                        return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_REQUIRES, am, true);
-                else /* automount + nofail */
-                        return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_WANTS, am, true);
-
-        } else if (handle && !noauto) {
-
-                /* Automatically add mount points that aren't natively
-                 * configured to local-fs.target */
-
-                if (!nofail) /* auto + fail */
-                        return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
-                else /* auto + nofail */
-                        return unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true);
-        }
-
-        return 0;
-}
-
 static int mount_add_device_links(Mount *m) {
         MountParameters *p;
         int r;
 
         assert(m);
 
-        if (!(p = get_mount_parameters_configured(m)))
+        p = get_mount_parameters_fragment(m);
+        if (!p)
                 return 0;
 
         if (!p->what)
                 return 0;
 
         if (!mount_is_bind(p) &&
-            !path_equal(m->where, "/") &&
-            p == &m->parameters_etc_fstab) {
-                bool nofail, noauto;
-
-                noauto = !!mount_test_option(p->options, "noauto");
-                nofail = !!mount_test_option(p->options, "nofail");
-
-                if ((r = unit_add_node_link(UNIT(m), p->what,
-                                            !noauto && nofail &&
-                                            UNIT(m)->manager->running_as == MANAGER_SYSTEM)) < 0)
+            !path_equal(m->where, "/")) {
+                r = unit_add_node_link(UNIT(m), p->what, false);
+                if (r < 0)
                         return r;
         }
 
         if (p->passno > 0 &&
             !mount_is_bind(p) &&
-            UNIT(m)->manager->running_as == MANAGER_SYSTEM &&
-            !path_equal(m->where, "/")) {
+            !path_equal(m->where, "/") &&
+            UNIT(m)->manager->running_as == SYSTEMD_SYSTEM) {
                 char *name;
                 Unit *fsck;
                 /* Let's add in the fsck service */
 
                 /* aka SPECIAL_FSCK_SERVICE */
-                if (!(name = unit_name_from_path_instance("fsck", p->what, ".service")))
+                name = unit_name_from_path_instance("systemd-fsck", p->what, ".service");
+                if (!name)
                         return -ENOMEM;
 
-                if ((r = manager_load_unit_prepare(UNIT(m)->manager, name, NULL, NULL, &fsck)) < 0) {
+                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));
                         free(name);
                         return r;
                 }
-
                 free(name);
 
                 SERVICE(fsck)->fsck_passno = p->passno;
 
-                if ((r = unit_add_two_dependencies(UNIT(m), UNIT_AFTER, UNIT_REQUIRES, fsck, true)) < 0)
+                r = unit_add_two_dependencies(UNIT(m), UNIT_AFTER, UNIT_REQUIRES, fsck, true);
+                if (r < 0)
                         return r;
         }
 
         return 0;
 }
 
+static int mount_add_quota_links(Mount *m) {
+        int r;
+        MountParameters *p;
+
+        assert(m);
+
+        if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
+                return 0;
+
+        p = get_mount_parameters_fragment(m);
+        if (!p)
+                return 0;
+
+        if (!needs_quota(p))
+                return 0;
+
+        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true);
+        if (r < 0)
+                return r;
+
+        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 static int mount_add_default_dependencies(Mount *m) {
         int r;
         MountParameters *p;
+        const char *after;
 
         assert(m);
 
-        if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
+        if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
                 return 0;
 
-        p = get_mount_parameters_configured(m);
-        if (p && needs_quota(p)) {
-                if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true)) < 0 ||
-                    (r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true)) < 0)
-                        return r;
-        }
+        p = get_mount_parameters_fragment(m);
+        if (!p)
+                return 0;
 
-        if (!path_equal(m->where, "/"))
-                if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
-                        return r;
+        if (path_equal(m->where, "/"))
+                return 0;
+
+        if (mount_is_network(p))
+                after = SPECIAL_REMOTE_FS_PRE_TARGET;
+        else
+                after = SPECIAL_LOCAL_FS_PRE_TARGET;
+
+        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, after, 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;
 
         return 0;
 }
@@ -494,7 +461,8 @@ static int mount_fix_timeouts(Mount *m) {
 
         assert(m);
 
-        if (!(p = get_mount_parameters_configured(m)))
+        p = get_mount_parameters_fragment(m);
+        if (!p)
                 return 0;
 
         /* Allow configuration how long we wait for a device that
@@ -504,7 +472,7 @@ static int mount_fix_timeouts(Mount *m) {
 
         if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout")))
                 timeout += 31;
-        else if ((timeout = mount_test_option(p->options, "x-systemd-device-timeout")))
+        else if ((timeout = mount_test_option(p->options, "x-systemd.device-timeout")))
                 timeout += 25;
         else
                 return 0;
@@ -539,7 +507,7 @@ static int mount_verify(Mount *m) {
         if (UNIT(m)->load_state != UNIT_LOADED)
                 return 0;
 
-        if (!m->from_etc_fstab && !m->from_fragment && !m->from_proc_self_mountinfo)
+        if (!m->from_fragment && !m->from_proc_self_mountinfo)
                 return -ENOENT;
 
         if (!(e = unit_name_from_path(m->where, ".mount")))
@@ -563,7 +531,7 @@ static int mount_verify(Mount *m) {
                 return -EBADMSG;
         }
 
-        if (m->exec_context.pam_name && m->exec_context.kill_mode != KILL_CONTROL_GROUP) {
+        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);
                 return -EINVAL;
         }
@@ -571,68 +539,104 @@ static int mount_verify(Mount *m) {
         return 0;
 }
 
-static int mount_load(Unit *u) {
-        Mount *m = MOUNT(u);
+static int mount_add_extras(Mount *m) {
+        Unit *u = UNIT(m);
         int r;
 
-        assert(u);
-        assert(u->load_state == UNIT_STUB);
-
-        if ((r = unit_load_fragment_and_dropin_optional(u)) < 0)
+        r = unit_add_exec_dependencies(u, &m->exec_context);
+        if (r < 0)
                 return r;
 
-        /* This is a new unit? Then let's add in some extras */
-        if (u->load_state == UNIT_LOADED) {
-                if ((r = unit_add_exec_dependencies(u, &m->exec_context)) < 0)
+        if (UNIT(m)->fragment_path)
+                m->from_fragment = true;
+
+        if (!m->where) {
+                m->where = unit_name_to_path(u->id);
+                if (!m->where)
+                        return -ENOMEM;
+        }
+
+        path_kill_slashes(m->where);
+
+        if (!UNIT(m)->description) {
+                r = unit_set_description(u, m->where);
+                if (r < 0)
                         return r;
+        }
 
-                if (UNIT(m)->fragment_path)
-                        m->from_fragment = true;
-                else if (m->from_etc_fstab)
-                        /* We always add several default dependencies to fstab mounts,
-                         * but we do not want the implicit complementing of Wants= with After=
-                         * in the target unit that this mount unit will be hooked into. */
-                        UNIT(m)->default_dependencies = false;
+        r = mount_add_device_links(m);
+        if (r < 0)
+                return r;
 
-                if (!m->where)
-                        if (!(m->where = unit_name_to_path(u->id)))
-                                return -ENOMEM;
+        r = mount_add_mount_links(m);
+        if (r < 0)
+                return r;
 
-                path_kill_slashes(m->where);
+        r = mount_add_socket_links(m);
+        if (r < 0)
+                return r;
 
-                if (!UNIT(m)->description)
-                        if ((r = unit_set_description(u, m->where)) < 0)
-                                return r;
+        r = mount_add_swap_links(m);
+        if (r < 0)
+                return r;
 
-                if ((r = mount_add_device_links(m)) < 0)
-                        return r;
+        r = mount_add_path_links(m);
+        if (r < 0)
+                return r;
 
-                if ((r = mount_add_mount_links(m)) < 0)
-                        return r;
+        r = mount_add_requires_mounts_links(m);
+        if (r < 0)
+                return r;
 
-                if ((r = mount_add_socket_links(m)) < 0)
-                        return r;
+        r = mount_add_automount_links(m);
+        if (r < 0)
+                return r;
 
-                if ((r = mount_add_swap_links(m)) < 0)
-                        return r;
+        r = mount_add_quota_links(m);
+        if (r < 0)
+                return r;
 
-                if ((r = mount_add_path_links(m)) < 0)
+        if (UNIT(m)->default_dependencies) {
+                r = mount_add_default_dependencies(m);
+                if (r < 0)
                         return r;
+        }
 
-                if ((r = mount_add_automount_links(m)) < 0)
-                        return r;
+        r = unit_add_default_cgroups(u);
+        if (r < 0)
+                return r;
 
-                if ((r = mount_add_fstab_links(m)) < 0)
-                        return r;
+        r = mount_fix_timeouts(m);
+        if (r < 0)
+                return r;
 
-                if (UNIT(m)->default_dependencies || m->from_etc_fstab)
-                        if ((r = mount_add_default_dependencies(m)) < 0)
-                                return r;
+        return 0;
+}
 
-                if ((r = unit_add_default_cgroups(u)) < 0)
+static int mount_load(Unit *u) {
+        Mount *m = MOUNT(u);
+        int r;
+
+        assert(u);
+        assert(u->load_state == UNIT_STUB);
+
+        if (m->from_proc_self_mountinfo)
+                r = unit_load_fragment_and_dropin_optional(u);
+        else
+                r = unit_load_fragment_and_dropin(u);
+
+        if (r < 0)
+                return r;
+
+        /* This is a new unit? Then let's add in some extras */
+        if (u->load_state == UNIT_LOADED) {
+                r = mount_add_extras(m);
+                if (r < 0)
                         return r;
 
-                mount_fix_timeouts(m);
+                r = unit_exec_context_defaults(u, &m->exec_context);
+                if (r < 0)
+                        return r;
         }
 
         return mount_verify(m);
@@ -689,8 +693,10 @@ static void mount_set_state(Mount *m, MountState state) {
                  state == MOUNT_REMOUNTING_SIGKILL ||
                  state == MOUNT_UNMOUNTING_SIGTERM ||
                  state == MOUNT_UNMOUNTING_SIGKILL ||
-                 state == MOUNT_FAILED)
-                mount_notify_automount(m, -ENODEV);
+                 state == MOUNT_FAILED) {
+               if (state != old_state)
+                       mount_notify_automount(m, -ENODEV);
+       }
 
         if (state != old_state)
                 log_debug("%s changed %s -> %s",
@@ -760,7 +766,6 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
                 "%sWhat: %s\n"
                 "%sFile System Type: %s\n"
                 "%sOptions: %s\n"
-                "%sFrom /etc/fstab: %s\n"
                 "%sFrom /proc/self/mountinfo: %s\n"
                 "%sFrom fragment: %s\n"
                 "%sDirectoryMode: %04o\n",
@@ -770,7 +775,6 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, strna(p->what),
                 prefix, strna(p->fstype),
                 prefix, strna(p->options),
-                prefix, yes_no(m->from_etc_fstab),
                 prefix, yes_no(m->from_proc_self_mountinfo),
                 prefix, yes_no(m->from_fragment),
                 prefix, m->directory_mode);
@@ -781,6 +785,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
                         prefix, (unsigned long) m->control_pid);
 
         exec_context_dump(&m->exec_context, f, prefix);
+        kill_context_dump(&m->kill_context, f, prefix);
 }
 
 static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
@@ -806,6 +811,8 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
                             UNIT(m)->cgroup_bondings,
                             UNIT(m)->cgroup_attributes,
                             NULL,
+                            UNIT(m)->id,
+                            NULL,
                             &pid)) < 0)
                 goto fail;
 
@@ -851,10 +858,10 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
         if (f != MOUNT_SUCCESS)
                 m->result = f;
 
-        if (m->exec_context.kill_mode != KILL_NONE) {
+        if (m->kill_context.kill_mode != KILL_NONE) {
                 int sig = (state == MOUNT_MOUNTING_SIGTERM ||
                            state == MOUNT_UNMOUNTING_SIGTERM ||
-                           state == MOUNT_REMOUNTING_SIGTERM) ? m->exec_context.kill_signal : SIGKILL;
+                           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)
@@ -864,7 +871,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
                                 wait_for_exit = true;
                 }
 
-                if (m->exec_context.kill_mode == KILL_CONTROL_GROUP) {
+                if (m->kill_context.kill_mode == KILL_CONTROL_GROUP) {
 
                         if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
                                 r = -ENOMEM;
@@ -876,7 +883,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
                                 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, pid_set, NULL);
+                        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));
@@ -950,12 +957,15 @@ static void mount_enter_mounting(Mount *m) {
         m->control_command_id = MOUNT_EXEC_MOUNT;
         m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
 
-        mkdir_p(m->where, m->directory_mode);
+        mkdir_p_label(m->where, m->directory_mode);
+
+        if (dir_is_empty(m->where) <= 0)
+                log_notice("%s: Directory %s to mount over is not empty, ignoring. (To see the over-mounted files, please manually mount the underlying file system to a secondary location.)", m->meta.id, m->where);
 
         /* Create the source directory for bind-mounts if needed */
-        p = get_mount_parameters_configured(m);
+        p = get_mount_parameters_fragment(m);
         if (p && mount_is_bind(p))
-                mkdir_p(p->what, m->directory_mode);
+                mkdir_p_label(p->what, m->directory_mode);
 
         if (m->from_fragment)
                 r = exec_command_set(
@@ -966,12 +976,6 @@ static void mount_enter_mounting(Mount *m) {
                                 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
                                 m->parameters_fragment.options ? "-o" : NULL, m->parameters_fragment.options,
                                 NULL);
-        else if (m->from_etc_fstab)
-                r = exec_command_set(
-                                m->control_command,
-                                "/bin/mount",
-                                m->where,
-                                NULL);
         else
                 r = -ENOENT;
 
@@ -980,7 +984,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);
@@ -1030,14 +1035,7 @@ static void mount_enter_remounting(Mount *m) {
                                 NULL);
 
                 free(buf);
-        } else if (m->from_etc_fstab)
-                r = exec_command_set(
-                                m->control_command,
-                                "/bin/mount",
-                                m->where,
-                                "-o", "remount",
-                                NULL);
-        else
+        } else
                 r = -ENOENT;
 
         if (r < 0)
@@ -1216,7 +1214,7 @@ static bool mount_check_gc(Unit *u) {
 
         assert(m);
 
-        return m->from_etc_fstab || m->from_proc_self_mountinfo;
+        return m->from_proc_self_mountinfo;
 }
 
 static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
@@ -1231,7 +1229,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
         m->control_pid = 0;
 
-        if (is_clean_exit(code, status))
+        if (is_clean_exit(code, status, NULL))
                 f = MOUNT_SUCCESS;
         else if (code == CLD_EXITED)
                 f = MOUNT_FAILURE_EXIT_CODE;
@@ -1336,7 +1334,7 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
                 break;
 
         case MOUNT_MOUNTING_SIGTERM:
-                if (m->exec_context.send_sigkill) {
+                if (m->kill_context.send_sigkill) {
                         log_warning("%s mounting timed out. Killing.", u->id);
                         mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
@@ -1350,7 +1348,7 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
                 break;
 
         case MOUNT_REMOUNTING_SIGTERM:
-                if (m->exec_context.send_sigkill) {
+                if (m->kill_context.send_sigkill) {
                         log_warning("%s remounting timed out. Killing.", u->id);
                         mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
@@ -1364,7 +1362,7 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
                 break;
 
         case MOUNT_UNMOUNTING_SIGTERM:
-                if (m->exec_context.send_sigkill) {
+                if (m->kill_context.send_sigkill) {
                         log_warning("%s unmounting timed out. Killing.", u->id);
                         mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
@@ -1400,7 +1398,6 @@ static int mount_add_one(
                 const char *options,
                 const char *fstype,
                 int passno,
-                bool from_proc_self_mountinfo,
                 bool set_flags) {
         int r;
         Unit *u;
@@ -1414,8 +1411,6 @@ static int mount_add_one(
         assert(options);
         assert(fstype);
 
-        assert(!set_flags || from_proc_self_mountinfo);
-
         /* Ignore API mount points. They should never be referenced in
          * dependencies ever. */
         if (mount_point_is_api(where) || mount_point_ignore(where))
@@ -1458,6 +1453,14 @@ static int mount_add_one(
         } else {
                 delete = false;
                 free(e);
+
+                if (u->load_state == UNIT_ERROR) {
+                        u->load_state = UNIT_LOADED;
+                        u->load_error = 0;
+                        r = mount_add_extras(MOUNT(u));
+                        if (r < 0)
+                                goto fail;
+                }
         }
 
         if (!(w = strdup(what)) ||
@@ -1467,21 +1470,15 @@ static int mount_add_one(
                 goto fail;
         }
 
-        if (from_proc_self_mountinfo) {
-                p = &MOUNT(u)->parameters_proc_self_mountinfo;
-
-                if (set_flags) {
-                        MOUNT(u)->is_mounted = true;
-                        MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
-                        MOUNT(u)->just_changed = !streq_ptr(p->options, o);
-                }
-
-                MOUNT(u)->from_proc_self_mountinfo = true;
-        } else {
-                p = &MOUNT(u)->parameters_etc_fstab;
-                MOUNT(u)->from_etc_fstab = true;
+        p = &MOUNT(u)->parameters_proc_self_mountinfo;
+        if (set_flags) {
+                MOUNT(u)->is_mounted = true;
+                MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
+                MOUNT(u)->just_changed = !streq_ptr(p->options, o);
         }
 
+        MOUNT(u)->from_proc_self_mountinfo = true;
+
         free(p->what);
         p->what = w;
 
@@ -1508,89 +1505,6 @@ fail:
         return r;
 }
 
-static int mount_find_pri(char *options) {
-        char *end, *pri;
-        unsigned long r;
-
-        if (!(pri = mount_test_option(options, "pri")))
-                return 0;
-
-        pri += 4;
-
-        errno = 0;
-        r = strtoul(pri, &end, 10);
-
-        if (errno != 0)
-                return -errno;
-
-        if (end == pri || (*end != ',' && *end != 0))
-                return -EINVAL;
-
-        return (int) r;
-}
-
-static int mount_load_etc_fstab(Manager *m) {
-        FILE *f;
-        int r = 0;
-        struct mntent* me;
-
-        assert(m);
-
-        errno = 0;
-        if (!(f = setmntent("/etc/fstab", "r")))
-                return -errno;
-
-        while ((me = getmntent(f))) {
-                char *where, *what;
-                int k;
-
-                if (!(what = fstab_node_to_udev_node(me->mnt_fsname))) {
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
-                if (!(where = strdup(me->mnt_dir))) {
-                        free(what);
-                        r = -ENOMEM;
-                        goto finish;
-                }
-
-                if (what[0] == '/')
-                        path_kill_slashes(what);
-
-                if (where[0] == '/')
-                        path_kill_slashes(where);
-
-                if (streq(me->mnt_type, "swap")) {
-                        int pri;
-
-                        if ((pri = mount_find_pri(me->mnt_opts)) < 0)
-                                k = pri;
-                        else
-                                k = swap_add_one(m,
-                                                 what,
-                                                 NULL,
-                                                 pri,
-                                                 !!mount_test_option(me->mnt_opts, "noauto"),
-                                                 !!mount_test_option(me->mnt_opts, "nofail"),
-                                                 !!mount_test_option(me->mnt_opts, "comment=systemd.swapon"),
-                                                 false);
-                } else
-                        k = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, me->mnt_passno, false, false);
-
-                free(what);
-                free(where);
-
-                if (k < 0)
-                        r = k;
-        }
-
-finish:
-
-        endmntent(f);
-        return r;
-}
-
 static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
         int r = 0;
         unsigned i;
@@ -1631,7 +1545,8 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
                         goto clean_up;
                 }
 
-                if (asprintf(&o, "%s,%s", options, options2) < 0) {
+                o = strjoin(options, ",", options2, NULL);
+                if (!o) {
                         r = -ENOMEM;
                         goto finish;
                 }
@@ -1642,7 +1557,7 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
                         goto finish;
                 }
 
-                if ((k = mount_add_one(m, d, p, o, fstype, 0, true, set_flags)) < 0)
+                if ((k = mount_add_one(m, d, p, o, fstype, 0, set_flags)) < 0)
                         r = k;
 
 clean_up:
@@ -1698,9 +1613,6 @@ static int mount_enumerate(Manager *m) {
                         return -errno;
         }
 
-        if ((r = mount_load_etc_fstab(m)) < 0)
-                goto fail;
-
         if ((r = mount_load_proc_self_mountinfo(m, false)) < 0)
                 goto fail;
 
@@ -1800,7 +1712,7 @@ static void mount_reset_failed(Unit *u) {
         m->reload_result = MOUNT_SUCCESS;
 }
 
-static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *error) {
+static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
         Mount *m = MOUNT(u);
         int r = 0;
         Set *pid_set = NULL;
@@ -1822,23 +1734,25 @@ static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
                         if (kill(m->control_pid, signo) < 0)
                                 r = -errno;
 
-        if (who == KILL_ALL && mode == KILL_CONTROL_GROUP) {
+        if (who == KILL_ALL) {
                 int q;
 
-                if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func)))
+                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)
-                        if ((q = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0) {
+                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, pid_set, NULL);
-                if (q < 0)
-                        if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
-                                r = q;
+                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:
@@ -1886,8 +1800,9 @@ static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
 DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
 
 const UnitVTable mount_vtable = {
-        .suffix = ".mount",
         .object_size = sizeof(Mount),
+        .exec_context_offset = offsetof(Mount, exec_context),
+
         .sections =
                 "Unit\0"
                 "Mount\0"
@@ -1895,7 +1810,6 @@ const UnitVTable mount_vtable = {
 
         .no_alias = true,
         .no_instances = true,
-        .show_status = true,
 
         .init = mount_init,
         .load = mount_load,
@@ -1929,5 +1843,23 @@ const UnitVTable mount_vtable = {
         .bus_invalidating_properties =  bus_mount_invalidating_properties,
 
         .enumerate = mount_enumerate,
-        .shutdown = mount_shutdown
+        .shutdown = mount_shutdown,
+
+        .status_message_formats = {
+                .starting_stopping = {
+                        [0] = "Mounting %s...",
+                        [1] = "Unmounting %s...",
+                },
+                .finished_start_job = {
+                        [JOB_DONE]       = "Mounted %s.",
+                        [JOB_FAILED]     = "Failed to mount %s.",
+                        [JOB_DEPENDENCY] = "Dependency failed for %s.",
+                        [JOB_TIMEOUT]    = "Timed out mounting %s.",
+                },
+                .finished_stop_job = {
+                        [JOB_DONE]       = "Unmounted %s.",
+                        [JOB_FAILED]     = "Failed unmounting %s.",
+                        [JOB_TIMEOUT]    = "Timed out unmounting %s.",
+                },
+        },
 };