]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/mount.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / core / mount.c
index 1c2be28d55d81d1bc343aaf307bf29f1f37d20fb..79a6e1626c6a2b998c1b0b1ec7252a5f2743deab 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -58,8 +59,6 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_MOUNTED] = UNIT_ACTIVE,
         [MOUNT_REMOUNTING] = UNIT_RELOADING,
         [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
-        [MOUNT_MOUNTING_SIGTERM] = UNIT_DEACTIVATING,
-        [MOUNT_MOUNTING_SIGKILL] = UNIT_DEACTIVATING,
         [MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
         [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
         [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
@@ -70,6 +69,18 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
 static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
 static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
 
+static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
+        return IN_SET(state,
+                      MOUNT_MOUNTING,
+                      MOUNT_MOUNTING_DONE,
+                      MOUNT_REMOUNTING,
+                      MOUNT_REMOUNTING_SIGTERM,
+                      MOUNT_REMOUNTING_SIGKILL,
+                      MOUNT_UNMOUNTING,
+                      MOUNT_UNMOUNTING_SIGTERM,
+                      MOUNT_UNMOUNTING_SIGKILL);
+}
+
 static bool mount_needs_network(const char *options, const char *fstype) {
         if (fstab_test_option(options, "_netdev\0"))
                 return true;
@@ -121,18 +132,14 @@ static bool mount_is_automount(const MountParameters *p) {
                                  "x-systemd.automount\0");
 }
 
-static bool mount_state_active(MountState state) {
-        return IN_SET(state,
-                      MOUNT_MOUNTING,
-                      MOUNT_MOUNTING_DONE,
-                      MOUNT_REMOUNTING,
-                      MOUNT_UNMOUNTING,
-                      MOUNT_MOUNTING_SIGTERM,
-                      MOUNT_MOUNTING_SIGKILL,
-                      MOUNT_UNMOUNTING_SIGTERM,
-                      MOUNT_UNMOUNTING_SIGKILL,
-                      MOUNT_REMOUNTING_SIGTERM,
-                      MOUNT_REMOUNTING_SIGKILL);
+static bool mount_is_bound_to_device(const Mount *m) {
+        const MountParameters *p;
+
+        if (m->from_fragment)
+                return true;
+
+        p = &m->parameters_proc_self_mountinfo;
+        return fstab_test_option(p->options, "x-systemd.device-bound\0");
 }
 
 static bool needs_quota(const MountParameters *p) {
@@ -259,8 +266,7 @@ _pure_ static MountParameters* get_mount_parameters(Mount *m) {
         return get_mount_parameters_fragment(m);
 }
 
-static int mount_add_mount_links(Mount *m) {
-        _cleanup_free_ char *parent = NULL;
+static int mount_add_mount_dependencies(Mount *m) {
         MountParameters *pm;
         Unit *other;
         Iterator i;
@@ -270,33 +276,32 @@ static int mount_add_mount_links(Mount *m) {
         assert(m);
 
         if (!path_equal(m->where, "/")) {
-                /* Adds in links to other mount points that might lie further
-                 * up in the hierarchy */
+                _cleanup_free_ char *parent = NULL;
+
+                /* Adds in links to other mount points that might lie further up in the hierarchy */
 
                 parent = dirname_malloc(m->where);
                 if (!parent)
                         return -ENOMEM;
 
-                r = unit_require_mounts_for(UNIT(m), parent);
+                r = unit_require_mounts_for(UNIT(m), parent, UNIT_DEPENDENCY_IMPLICIT);
                 if (r < 0)
                         return r;
         }
 
-        /* Adds in links to other mount points that might be needed
-         * for the source path (if this is a bind mount or a loop mount) to be
-         * available. */
+        /* Adds in dependencies to other mount points that might be needed for the source path (if this is a bind mount
+         * or a loop mount) to be available. */
         pm = get_mount_parameters_fragment(m);
         if (pm && pm->what &&
             path_is_absolute(pm->what) &&
             (mount_is_bind(pm) || mount_is_loop(pm) || !mount_is_network(pm))) {
 
-                r = unit_require_mounts_for(UNIT(m), pm->what);
+                r = unit_require_mounts_for(UNIT(m), pm->what, UNIT_DEPENDENCY_FILE);
                 if (r < 0)
                         return r;
         }
 
-        /* Adds in links to other units that use this path or paths
-         * further down in the hierarchy */
+        /* Adds in dependencies to other units that use this path or paths further down in the hierarchy */
         s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
         SET_FOREACH(other, s, i) {
 
@@ -306,13 +311,13 @@ static int mount_add_mount_links(Mount *m) {
                 if (other == UNIT(m))
                         continue;
 
-                r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true);
+                r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true, UNIT_DEPENDENCY_PATH);
                 if (r < 0)
                         return r;
 
                 if (UNIT(m)->fragment_path) {
                         /* If we have fragment configuration, then make this dependency required */
-                        r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true);
+                        r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true, UNIT_DEPENDENCY_PATH);
                         if (r < 0)
                                 return r;
                 }
@@ -321,9 +326,11 @@ static int mount_add_mount_links(Mount *m) {
         return 0;
 }
 
-static int mount_add_device_links(Mount *m) {
-        MountParameters *p;
+static int mount_add_device_dependencies(Mount *m) {
         bool device_wants_mount = false;
+        UnitDependencyMask mask;
+        MountParameters *p;
+        UnitDependency dep;
         int r;
 
         assert(m);
@@ -353,16 +360,26 @@ static int mount_add_device_links(Mount *m) {
         if (mount_is_auto(p) && !mount_is_automount(p) && MANAGER_IS_SYSTEM(UNIT(m)->manager))
                 device_wants_mount = true;
 
-        r = unit_add_node_link(UNIT(m), p->what, device_wants_mount, m->from_fragment ? UNIT_BINDS_TO : UNIT_REQUIRES);
+        /* Mount units from /proc/self/mountinfo are not bound to devices
+         * by default since they're subject to races when devices are
+         * unplugged. But the user can still force this dep with an
+         * appropriate option (or udev property) so the mount units are
+         * automatically stopped when the device disappears suddenly. */
+        dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
+
+        mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
+
+        r = unit_add_node_dependency(UNIT(m), p->what, device_wants_mount, dep, mask);
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-static int mount_add_quota_links(Mount *m) {
-        int r;
+static int mount_add_quota_dependencies(Mount *m) {
+        UnitDependencyMask mask;
         MountParameters *p;
+        int r;
 
         assert(m);
 
@@ -376,62 +393,73 @@ static int mount_add_quota_links(Mount *m) {
         if (!needs_quota(p))
                 return 0;
 
-        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true);
+        mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT;
+
+        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true, mask);
         if (r < 0)
                 return r;
 
-        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true);
+        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true, mask);
         if (r < 0)
                 return r;
 
         return 0;
 }
 
-static bool should_umount(Mount *m) {
+static bool mount_is_extrinsic(Mount *m) {
         MountParameters *p;
+        assert(m);
 
-        if (PATH_IN_SET(m->where, "/", "/usr") ||
-            path_startswith(m->where, "/run/initramfs"))
-                return false;
+        /* Returns true for all units that are "magic" and should be excluded from the usual start-up and shutdown
+         * dependencies. We call them "extrinsic" here, as they are generally mounted outside of the systemd dependency
+         * logic. We shouldn't attempt to manage them ourselves but it's fine if the user operates on them with us. */
+
+        if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) /* We only automatically manage mounts if we are in system mode */
+                return true;
 
+        if (PATH_IN_SET(m->where,  /* Don't bother with the OS data itself */
+                        "/",
+                        "/usr"))
+                return true;
+
+        if (PATH_STARTSWITH_SET(m->where,
+                                "/run/initramfs",    /* This should stay around from before we boot until after we shutdown */
+                                "/proc",             /* All of this is API VFS */
+                                "/sys",              /* … dito … */
+                                "/dev"))             /* … dito … */
+                return true;
+
+        /* If this is an initrd mount, and we are not in the initrd, then leave this around forever, too. */
         p = get_mount_parameters(m);
-        if (p && fstab_test_option(p->options, "x-initrd.mount\0") &&
-            !in_initrd())
-                return false;
+        if (p && fstab_test_option(p->options, "x-initrd.mount\0") && !in_initrd())
+                return true;
 
-        return true;
+        return false;
 }
 
 static int mount_add_default_dependencies(Mount *m) {
+        UnitDependencyMask mask;
+        int r;
         MountParameters *p;
         const char *after;
-        int r;
 
         assert(m);
 
         if (!UNIT(m)->default_dependencies)
                 return 0;
 
-        if (!MANAGER_IS_SYSTEM(UNIT(m)->manager))
-                return 0;
-
-        /* We do not add any default dependencies to /, /usr or
-         * /run/initramfs/, since they are guaranteed to stay
-         * mounted the whole time, since our system is on it.
-         * Also, don't bother with anything mounted below virtual
-         * file systems, it's also going to be virtual, and hence
-         * not worth the effort. */
-        if (PATH_IN_SET(m->where, "/", "/usr") ||
-            path_startswith(m->where, "/run/initramfs") ||
-            path_startswith(m->where, "/proc") ||
-            path_startswith(m->where, "/sys") ||
-            path_startswith(m->where, "/dev"))
+        /* We do not add any default dependencies to /, /usr or /run/initramfs/, since they are guaranteed to stay
+         * mounted the whole time, since our system is on it.  Also, don't bother with anything mounted below virtual
+         * file systems, it's also going to be virtual, and hence not worth the effort. */
+        if (mount_is_extrinsic(m))
                 return 0;
 
         p = get_mount_parameters(m);
         if (!p)
                 return 0;
 
+        mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
+
         if (mount_is_network(p)) {
                 /* We order ourselves after network.target. This is
                  * primarily useful at shutdown: services that take
@@ -439,7 +467,7 @@ static int mount_add_default_dependencies(Mount *m) {
                  * network.target, so that they are shut down only
                  * after this mount unit is stopped. */
 
-                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, NULL, true);
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, NULL, true, mask);
                 if (r < 0)
                         return r;
 
@@ -450,7 +478,7 @@ static int mount_add_default_dependencies(Mount *m) {
                  * whose purpose it is to delay this until the network
                  * is "up". */
 
-                r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, NULL, true);
+                r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, NULL, true, mask);
                 if (r < 0)
                         return r;
 
@@ -458,12 +486,17 @@ static int mount_add_default_dependencies(Mount *m) {
         } else
                 after = SPECIAL_LOCAL_FS_PRE_TARGET;
 
-        r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
+        r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true, mask);
+        if (r < 0)
+                return r;
+
+        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, mask);
         if (r < 0)
                 return r;
 
-        if (should_umount(m)) {
-                r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
+        /* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */
+        if (streq_ptr(p->fstype, "tmpfs")) {
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, NULL, true, mask);
                 if (r < 0)
                         return r;
         }
@@ -481,7 +514,7 @@ static int mount_verify(Mount *m) {
         if (UNIT(m)->load_state != UNIT_LOADED)
                 return 0;
 
-        if (!m->from_fragment && !m->from_proc_self_mountinfo)
+        if (!m->from_fragment && !m->from_proc_self_mountinfo && !UNIT(m)->perpetual)
                 return -ENOENT;
 
         r = unit_name_from_path(m->where, ".mount", &e);
@@ -535,15 +568,15 @@ static int mount_add_extras(Mount *m) {
                         return r;
         }
 
-        r = mount_add_device_links(m);
+        r = mount_add_device_dependencies(m);
         if (r < 0)
                 return r;
 
-        r = mount_add_mount_links(m);
+        r = mount_add_mount_dependencies(m);
         if (r < 0)
                 return r;
 
-        r = mount_add_quota_links(m);
+        r = mount_add_quota_dependencies(m);
         if (r < 0)
                 return r;
 
@@ -620,7 +653,7 @@ static void mount_set_state(Mount *m, MountState state) {
         old_state = m->state;
         m->state = state;
 
-        if (!mount_state_active(state)) {
+        if (!MOUNT_STATE_WITH_PROCESS(state)) {
                 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
                 mount_unwatch_control_pid(m);
                 m->control_command = NULL;
@@ -631,7 +664,6 @@ static void mount_set_state(Mount *m, MountState state) {
                 log_unit_debug(UNIT(m), "Changed %s -> %s", 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;
 }
 
 static int mount_coldplug(Unit *u) {
@@ -652,7 +684,7 @@ static int mount_coldplug(Unit *u) {
 
         if (m->control_pid > 0 &&
             pid_is_unwaited(m->control_pid) &&
-            mount_state_active(new_state)) {
+            MOUNT_STATE_WITH_PROCESS(new_state)) {
 
                 r = unit_watch_pid(UNIT(m), m->control_pid);
                 if (r < 0)
@@ -688,6 +720,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
                 "%sOptions: %s\n"
                 "%sFrom /proc/self/mountinfo: %s\n"
                 "%sFrom fragment: %s\n"
+                "%sExtrinsic: %s\n"
                 "%sDirectoryMode: %04o\n"
                 "%sSloppyOptions: %s\n"
                 "%sLazyUnmount: %s\n"
@@ -700,6 +733,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, p ? strna(p->options) : "n/a",
                 prefix, yes_no(m->from_proc_self_mountinfo),
                 prefix, yes_no(m->from_fragment),
+                prefix, yes_no(mount_is_extrinsic(m)),
                 prefix, m->directory_mode,
                 prefix, yes_no(m->sloppy_options),
                 prefix, yes_no(m->lazy_unmount),
@@ -712,13 +746,14 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
 
         exec_context_dump(&m->exec_context, f, prefix);
         kill_context_dump(&m->kill_context, f, prefix);
+        cgroup_context_dump(&m->cgroup_context, f, prefix);
 }
 
 static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
         pid_t pid;
         int r;
         ExecParameters exec_params = {
-                .flags      = EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
+                .flags      = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN,
                 .stdin_fd   = -1,
                 .stdout_fd  = -1,
                 .stderr_fd  = -1,
@@ -729,11 +764,14 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
         assert(_pid);
 
         (void) unit_realize_cgroup(UNIT(m));
-        if (m->reset_cpu_usage) {
-                (void) unit_reset_cpu_usage(UNIT(m));
-                m->reset_cpu_usage = false;
+        if (m->reset_accounting) {
+                (void) unit_reset_cpu_accounting(UNIT(m));
+                (void) unit_reset_ip_accounting(UNIT(m));
+                m->reset_accounting = false;
         }
 
+        unit_export_state_files(UNIT(m));
+
         r = unit_setup_exec_runtime(UNIT(m));
         if (r < 0)
                 return r;
@@ -746,12 +784,8 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
         if (r < 0)
                 return r;
 
-        exec_params.environment = UNIT(m)->manager->environment;
-        exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(m)->manager);
-        exec_params.cgroup_supported = UNIT(m)->manager->cgroup_supported;
-        exec_params.cgroup_path = UNIT(m)->cgroup_path;
-        exec_params.cgroup_delegate = m->cgroup_context.delegate;
-        exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(m)->manager);
+        manager_set_exec_params(UNIT(m)->manager, &exec_params);
+        unit_set_exec_params(UNIT(m), &exec_params);
 
         r = exec_spawn(UNIT(m),
                        c,
@@ -779,12 +813,15 @@ static void mount_enter_dead(Mount *m, MountResult f) {
         if (m->result == MOUNT_SUCCESS)
                 m->result = f;
 
+        if (m->result != MOUNT_SUCCESS)
+                log_unit_warning(UNIT(m), "Failed with result '%s'.", mount_result_to_string(m->result));
+
         mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
 
         exec_runtime_destroy(m->exec_runtime);
         m->exec_runtime = exec_runtime_unref(m->exec_runtime);
 
-        exec_context_destroy_runtime_directory(&m->exec_context, manager_get_runtime_prefix(UNIT(m)->manager));
+        exec_context_destroy_runtime_directory(&m->exec_context, UNIT(m)->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
 
         unit_unref_uid_gid(UNIT(m), true);
 
@@ -800,6 +837,35 @@ static void mount_enter_mounted(Mount *m, MountResult f) {
         mount_set_state(m, MOUNT_MOUNTED);
 }
 
+static void mount_enter_dead_or_mounted(Mount *m, MountResult f) {
+        assert(m);
+
+        /* Enter DEAD or MOUNTED state, depending on what the kernel currently says about the mount point. We use this
+         * whenever we executed an operation, so that our internal state reflects what the kernel says again, after all
+         * ultimately we just mirror the kernel's internal state on this. */
+
+        if (m->from_proc_self_mountinfo)
+                mount_enter_mounted(m, f);
+        else
+                mount_enter_dead(m, f);
+}
+
+static int state_to_kill_operation(MountState state) {
+        switch (state) {
+
+        case MOUNT_REMOUNTING_SIGTERM:
+        case MOUNT_UNMOUNTING_SIGTERM:
+                return KILL_TERMINATE;
+
+        case MOUNT_REMOUNTING_SIGKILL:
+        case MOUNT_UNMOUNTING_SIGKILL:
+                return KILL_KILL;
+
+        default:
+                return _KILL_OPERATION_INVALID;
+        }
+}
+
 static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
         int r;
 
@@ -811,8 +877,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
         r = unit_kill_context(
                         UNIT(m),
                         &m->kill_context,
-                        (state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM) ?
-                        KILL_KILL : KILL_TERMINATE,
+                        state_to_kill_operation(state),
                         -1,
                         m->control_pid,
                         false);
@@ -825,26 +890,20 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
                         goto fail;
 
                 mount_set_state(m, state);
-        } else if (state == MOUNT_REMOUNTING_SIGTERM)
+        } else if (state == MOUNT_REMOUNTING_SIGTERM && m->kill_context.send_sigkill)
                 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
-        else if (state == MOUNT_REMOUNTING_SIGKILL)
+        else if (IN_SET(state, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL))
                 mount_enter_mounted(m, MOUNT_SUCCESS);
-        else if (state == MOUNT_MOUNTING_SIGTERM)
-                mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_SUCCESS);
-        else if (state == MOUNT_UNMOUNTING_SIGTERM)
+        else if (state == MOUNT_UNMOUNTING_SIGTERM && m->kill_context.send_sigkill)
                 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS);
         else
-                mount_enter_dead(m, MOUNT_SUCCESS);
+                mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
 
         return;
 
 fail:
         log_unit_warning_errno(UNIT(m), r, "Failed to kill processes: %m");
-
-        if (IN_SET(state, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL))
-                mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
-        else
-                mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
+        mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
 }
 
 static void mount_enter_unmounting(Mount *m) {
@@ -862,7 +921,7 @@ static void mount_enter_unmounting(Mount *m) {
         m->control_command_id = MOUNT_EXEC_UNMOUNT;
         m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
 
-        r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, NULL);
+        r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, "-c", NULL);
         if (r >= 0 && m->lazy_unmount)
                 r = exec_command_append(m->control_command, "-l", NULL);
         if (r >= 0 && m->force_unmount)
@@ -882,7 +941,7 @@ static void mount_enter_unmounting(Mount *m) {
 
 fail:
         log_unit_warning_errno(UNIT(m), r, "Failed to run 'umount' task: %m");
-        mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
+        mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
 }
 
 static void mount_enter_mounting(Mount *m) {
@@ -923,7 +982,6 @@ static void mount_enter_mounting(Mount *m) {
                         r = exec_command_append(m->control_command, "-o", opts, NULL);
         } else
                 r = -ENOENT;
-
         if (r < 0)
                 goto fail;
 
@@ -939,7 +997,17 @@ static void mount_enter_mounting(Mount *m) {
 
 fail:
         log_unit_warning_errno(UNIT(m), r, "Failed to run 'mount' task: %m");
-        mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
+        mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
+}
+
+static void mount_set_reload_result(Mount *m, MountResult result) {
+        assert(m);
+
+        /* Only store the first error we encounter */
+        if (m->reload_result != MOUNT_SUCCESS)
+                return;
+
+        m->reload_result = result;
 }
 
 static void mount_enter_remounting(Mount *m) {
@@ -948,6 +1016,9 @@ static void mount_enter_remounting(Mount *m) {
 
         assert(m);
 
+        /* Reset reload result when we are about to start a new remount operation */
+        m->reload_result = MOUNT_SUCCESS;
+
         m->control_command_id = MOUNT_EXEC_REMOUNT;
         m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
 
@@ -969,7 +1040,6 @@ static void mount_enter_remounting(Mount *m) {
                         r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
         } else
                 r = -ENOENT;
-
         if (r < 0)
                 goto fail;
 
@@ -985,8 +1055,8 @@ static void mount_enter_remounting(Mount *m) {
 
 fail:
         log_unit_warning_errno(UNIT(m), r, "Failed to run 'remount' task: %m");
-        m->reload_result = MOUNT_FAILURE_RESOURCES;
-        mount_enter_mounted(m, MOUNT_SUCCESS);
+        mount_set_reload_result(m, MOUNT_FAILURE_RESOURCES);
+        mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
 }
 
 static int mount_start(Unit *u) {
@@ -1000,9 +1070,7 @@ static int mount_start(Unit *u) {
         if (IN_SET(m->state,
                    MOUNT_UNMOUNTING,
                    MOUNT_UNMOUNTING_SIGTERM,
-                   MOUNT_UNMOUNTING_SIGKILL,
-                   MOUNT_MOUNTING_SIGTERM,
-                   MOUNT_MOUNTING_SIGKILL))
+                   MOUNT_UNMOUNTING_SIGKILL))
                 return -EAGAIN;
 
         /* Already on it! */
@@ -1023,7 +1091,7 @@ static int mount_start(Unit *u) {
 
         m->result = MOUNT_SUCCESS;
         m->reload_result = MOUNT_SUCCESS;
-        m->reset_cpu_usage = true;
+        m->reset_accounting = true;
 
         mount_enter_mounting(m);
         return 1;
@@ -1034,25 +1102,38 @@ static int mount_stop(Unit *u) {
 
         assert(m);
 
-        /* Already on it */
-        if (IN_SET(m->state,
-                   MOUNT_UNMOUNTING,
-                   MOUNT_UNMOUNTING_SIGKILL,
-                   MOUNT_UNMOUNTING_SIGTERM,
-                   MOUNT_MOUNTING_SIGTERM,
-                   MOUNT_MOUNTING_SIGKILL))
+        switch (m->state) {
+
+        case MOUNT_UNMOUNTING:
+        case MOUNT_UNMOUNTING_SIGKILL:
+        case MOUNT_UNMOUNTING_SIGTERM:
+                /* Already on it */
                 return 0;
 
-        assert(IN_SET(m->state,
-                      MOUNT_MOUNTING,
-                      MOUNT_MOUNTING_DONE,
-                      MOUNT_MOUNTED,
-                      MOUNT_REMOUNTING,
-                      MOUNT_REMOUNTING_SIGTERM,
-                      MOUNT_REMOUNTING_SIGKILL));
+        case MOUNT_MOUNTING:
+        case MOUNT_MOUNTING_DONE:
+        case MOUNT_REMOUNTING:
+                /* If we are still waiting for /bin/mount, we go directly into kill mode. */
+                mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_SUCCESS);
+                return 0;
 
-        mount_enter_unmounting(m);
-        return 1;
+        case MOUNT_REMOUNTING_SIGTERM:
+                /* If we are already waiting for a hung remount, convert this to the matching unmounting state */
+                mount_set_state(m, MOUNT_UNMOUNTING_SIGTERM);
+                return 0;
+
+        case MOUNT_REMOUNTING_SIGKILL:
+                /* as above */
+                mount_set_state(m, MOUNT_UNMOUNTING_SIGKILL);
+                return 0;
+
+        case MOUNT_MOUNTED:
+                mount_enter_unmounting(m);
+                return 1;
+
+        default:
+                assert_not_reached("Unexpected state.");
+        }
 }
 
 static int mount_reload(Unit *u) {
@@ -1060,12 +1141,13 @@ static int mount_reload(Unit *u) {
 
         assert(m);
 
-        if (m->state == MOUNT_MOUNTING_DONE)
+        if (m->state == MOUNT_MOUNTING_DONE) /* not yet ready to reload, try again */
                 return -EAGAIN;
 
         assert(m->state == MOUNT_MOUNTED);
 
         mount_enter_remounting(m);
+
         return 1;
 }
 
@@ -1188,7 +1270,9 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         else
                 assert_not_reached("Unknown code");
 
-        if (m->result == MOUNT_SUCCESS)
+        if (IN_SET(m->state, MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGKILL, MOUNT_REMOUNTING_SIGTERM))
+                mount_set_reload_result(m, f);
+        else if (m->result == MOUNT_SUCCESS)
                 m->result = f;
 
         if (m->control_command) {
@@ -1201,23 +1285,19 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         log_unit_full(u, f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,
                       "Mount process exited, code=%s status=%i", 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
-         * operation succeed we assume the kernel will follow soon too
-         * and already change into the resulting state.  If it fails
-         * we check if the kernel still knows about the mount. and
-         * change state accordingly. */
+        /* Note that mount(8) returning and the kernel sending us a mount table change event might happen
+         * out-of-order. If an operation succeed we assume the kernel will follow soon too and already change into the
+         * resulting state.  If it fails we check if the kernel still knows about the mount. and change state
+         * accordingly. */
 
         switch (m->state) {
 
         case MOUNT_MOUNTING:
         case MOUNT_MOUNTING_DONE:
-        case MOUNT_MOUNTING_SIGKILL:
-        case MOUNT_MOUNTING_SIGTERM:
 
                 if (f == MOUNT_SUCCESS || m->from_proc_self_mountinfo)
                         /* If /bin/mount returned success, or if we see the mount point in /proc/self/mountinfo we are
-                         * happy. If we see the first condition first, we should see the the second condition
+                         * happy. If we see the first condition first, we should see the second condition
                          * immediately after – or /bin/mount lies to us and is broken. */
                         mount_enter_mounted(m, f);
                 else
@@ -1225,49 +1305,32 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                 break;
 
         case MOUNT_REMOUNTING:
-        case MOUNT_REMOUNTING_SIGKILL:
         case MOUNT_REMOUNTING_SIGTERM:
-
-                m->reload_result = f;
-                if (m->from_proc_self_mountinfo)
-                        mount_enter_mounted(m, MOUNT_SUCCESS);
-                else
-                        mount_enter_dead(m, MOUNT_SUCCESS);
-
+        case MOUNT_REMOUNTING_SIGKILL:
+                mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
                 break;
 
         case MOUNT_UNMOUNTING:
         case MOUNT_UNMOUNTING_SIGKILL:
         case MOUNT_UNMOUNTING_SIGTERM:
 
-                if (f == MOUNT_SUCCESS) {
-
-                        if (m->from_proc_self_mountinfo) {
-
-                                /* Still a mount point? If so, let's
-                                 * try again. Most likely there were
-                                 * multiple mount points stacked on
-                                 * top of each other. Note that due to
-                                 * the io event priority logic we can
-                                 * be sure the new mountinfo is loaded
-                                 * before we process the SIGCHLD for
-                                 * the mount command. */
-
-                                if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
-                                        log_unit_debug(u, "Mount still present, trying again.");
-                                        m->n_retry_umount++;
-                                        mount_enter_unmounting(m);
-                                } else {
-                                        log_unit_debug(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount);
-                                        mount_enter_mounted(m, f);
-                                }
-                        } else
-                                mount_enter_dead(m, f);
-
-                } else if (m->from_proc_self_mountinfo)
-                        mount_enter_mounted(m, f);
-                else
+                if (m->from_proc_self_mountinfo) {
+
+                        /* Still a mount point? If so, let's try again. Most likely there were multiple mount points
+                         * stacked on top of each other. Note that due to the io event priority logic we can be sure
+                         * the new mountinfo is loaded before we process the SIGCHLD for the mount command. */
+
+                        if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
+                                log_unit_debug(u, "Mount still present, trying again.");
+                                m->n_retry_umount++;
+                                mount_enter_unmounting(m);
+                        } else {
+                                log_unit_debug(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount);
+                                mount_enter_mounted(m, f);
+                        }
+                } else
                         mount_enter_dead(m, f);
+
                 break;
 
         default:
@@ -1288,72 +1351,53 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
 
         case MOUNT_MOUNTING:
         case MOUNT_MOUNTING_DONE:
-                log_unit_warning(UNIT(m), "Mounting timed out. Stopping.");
-                mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
+                log_unit_warning(UNIT(m), "Mounting timed out. Terminating.");
+                mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         case MOUNT_REMOUNTING:
-                log_unit_warning(UNIT(m), "Remounting timed out. Stopping.");
-                m->reload_result = MOUNT_FAILURE_TIMEOUT;
-                mount_enter_mounted(m, MOUNT_SUCCESS);
+                log_unit_warning(UNIT(m), "Remounting timed out. Terminating remount process.");
+                mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
+                mount_enter_signal(m, MOUNT_REMOUNTING_SIGTERM, MOUNT_SUCCESS);
                 break;
 
-        case MOUNT_UNMOUNTING:
-                log_unit_warning(UNIT(m), "Unmounting timed out. Stopping.");
-                mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
-                break;
+        case MOUNT_REMOUNTING_SIGTERM:
+                mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
 
-        case MOUNT_MOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_unit_warning(UNIT(m), "Mounting timed out. Killing.");
-                        mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
+                        log_unit_warning(UNIT(m), "Remounting timed out. Killing.");
+                        mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
                 } else {
-                        log_unit_warning(UNIT(m), "Mounting timed out. Skipping SIGKILL. Ignoring.");
-
-                        if (m->from_proc_self_mountinfo)
-                                mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
-                        else
-                                mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
+                        log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring.");
+                        mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
                 }
                 break;
 
-        case MOUNT_REMOUNTING_SIGTERM:
-                if (m->kill_context.send_sigkill) {
-                        log_unit_warning(UNIT(m), "Remounting timed out. Killing.");
-                        mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
-                } else {
-                        log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring.");
+        case MOUNT_REMOUNTING_SIGKILL:
+                mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
 
-                        if (m->from_proc_self_mountinfo)
-                                mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
-                        else
-                                mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
-                }
+                log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
+                mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
+                break;
+
+        case MOUNT_UNMOUNTING:
+                log_unit_warning(UNIT(m), "Unmounting timed out. Terminating.");
+                mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         case MOUNT_UNMOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_unit_warning(UNIT(m), "Unmounting timed out. Killing.");
+                        log_unit_warning(UNIT(m), "Mount process timed out. Killing.");
                         mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_unit_warning(UNIT(m), "Unmounting timed out. Skipping SIGKILL. Ignoring.");
-
-                        if (m->from_proc_self_mountinfo)
-                                mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
-                        else
-                                mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
+                        log_unit_warning(UNIT(m), "Mount process timed out. Skipping SIGKILL. Ignoring.");
+                        mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
                 }
                 break;
 
-        case MOUNT_MOUNTING_SIGKILL:
-        case MOUNT_REMOUNTING_SIGKILL:
         case MOUNT_UNMOUNTING_SIGKILL:
-                log_unit_warning(UNIT(m),"Mount process still around after SIGKILL. Ignoring.");
-
-                if (m->from_proc_self_mountinfo)
-                        mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
-                else
-                        mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
+                log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
+                mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         default:
@@ -1363,6 +1407,129 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
         return 0;
 }
 
+typedef struct {
+        bool is_mounted;
+        bool just_mounted;
+        bool just_changed;
+} MountSetupFlags;
+
+static int mount_setup_new_unit(
+                Unit *u,
+                const char *what,
+                const char *where,
+                const char *options,
+                const char *fstype,
+                MountSetupFlags *flags) {
+
+        MountParameters *p;
+
+        assert(u);
+        assert(flags);
+
+        u->source_path = strdup("/proc/self/mountinfo");
+        MOUNT(u)->where = strdup(where);
+        if (!u->source_path || !MOUNT(u)->where)
+                return -ENOMEM;
+
+        /* Make sure to initialize those fields before mount_is_extrinsic(). */
+        MOUNT(u)->from_proc_self_mountinfo = true;
+        p = &MOUNT(u)->parameters_proc_self_mountinfo;
+
+        p->what = strdup(what);
+        p->options = strdup(options);
+        p->fstype = strdup(fstype);
+        if (!p->what || !p->options || !p->fstype)
+                return -ENOMEM;
+
+        if (!mount_is_extrinsic(MOUNT(u))) {
+                const char *target;
+                int r;
+
+                target = mount_is_network(p) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
+                r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
+                if (r < 0)
+                        return r;
+
+                r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
+                if (r < 0)
+                        return r;
+        }
+
+        unit_add_to_load_queue(u);
+        flags->is_mounted = true;
+        flags->just_mounted = true;
+        flags->just_changed = true;
+
+        return 0;
+}
+
+static int mount_setup_existing_unit(
+                Unit *u,
+                const char *what,
+                const char *where,
+                const char *options,
+                const char *fstype,
+                MountSetupFlags *flags) {
+
+        MountParameters *p;
+        bool load_extras = false;
+        int r1, r2, r3;
+
+        assert(u);
+        assert(flags);
+
+        if (!MOUNT(u)->where) {
+                MOUNT(u)->where = strdup(where);
+                if (!MOUNT(u)->where)
+                        return -ENOMEM;
+        }
+
+        /* Make sure to initialize those fields before mount_is_extrinsic(). */
+        p = &MOUNT(u)->parameters_proc_self_mountinfo;
+
+        r1 = free_and_strdup(&p->what, what);
+        r2 = free_and_strdup(&p->options, options);
+        r3 = free_and_strdup(&p->fstype, fstype);
+        if (r1 < 0 || r2 < 0 || r3 < 0)
+                return -ENOMEM;
+
+        flags->just_changed = r1 > 0 || r2 > 0 || r3 > 0;
+        flags->is_mounted = true;
+        flags->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
+
+        MOUNT(u)->from_proc_self_mountinfo = true;
+
+        if (!mount_is_extrinsic(MOUNT(u)) && mount_is_network(p)) {
+                /* _netdev option may have shown up late, or on a
+                 * remount. Add remote-fs dependencies, even though
+                 * local-fs ones may already be there.
+                 *
+                 * Note: due to a current limitation (we don't track
+                 * in the dependency "Set*" objects who created a
+                 * dependency), we can only add deps, never lose them,
+                 * until the next full daemon-reload. */
+                unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, NULL, true, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
+                load_extras = true;
+        }
+
+        if (u->load_state == UNIT_NOT_FOUND) {
+                u->load_state = UNIT_LOADED;
+                u->load_error = 0;
+
+                /* Load in the extras later on, after we
+                 * finished initialization of the unit */
+
+                /* FIXME: since we're going to load the unit later on, why setting load_extras=true ? */
+                load_extras = true;
+                flags->just_changed = true;
+        }
+
+        if (load_extras)
+                return mount_add_extras(MOUNT(u));
+
+        return 0;
+}
+
 static int mount_setup_unit(
                 Manager *m,
                 const char *what,
@@ -1371,10 +1538,8 @@ static int mount_setup_unit(
                 const char *fstype,
                 bool set_flags) {
 
-        _cleanup_free_ char *e = NULL, *w = NULL, *o = NULL, *f = NULL;
-        bool load_extras = false;
-        MountParameters *p;
-        bool delete, changed = false;
+        _cleanup_free_ char *e = NULL;
+        MountSetupFlags flags;
         Unit *u;
         int r;
 
@@ -1402,116 +1567,34 @@ static int mount_setup_unit(
 
         u = manager_get_unit(m, e);
         if (!u) {
-                delete = true;
-
+                /* First time we see this mount point meaning that it's
+                 * not been initiated by a mount unit but rather by the
+                 * sysadmin having called mount(8) directly. */
                 r = unit_new_for_name(m, sizeof(Mount), e, &u);
                 if (r < 0)
                         goto fail;
 
-                MOUNT(u)->where = strdup(where);
-                if (!MOUNT(u)->where) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
-
-                u->source_path = strdup("/proc/self/mountinfo");
-                if (!u->source_path) {
-                        r = -ENOMEM;
-                        goto fail;
-                }
-
-                if (MANAGER_IS_SYSTEM(m)) {
-                        const char* target;
-
-                        target = mount_needs_network(options, fstype) ?  SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
-                        r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true);
-                        if (r < 0)
-                                goto fail;
-
-                        if (should_umount(MOUNT(u))) {
-                                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);
-                changed = true;
-        } else {
-                delete = false;
-
-                if (!MOUNT(u)->where) {
-                        MOUNT(u)->where = strdup(where);
-                        if (!MOUNT(u)->where) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
-                }
-
-                if (MANAGER_IS_SYSTEM(m) &&
-                    mount_needs_network(options, fstype)) {
-                        /* _netdev option may have shown up late, or on a
-                         * remount. Add remote-fs dependencies, even though
-                         * local-fs ones may already be there. */
-                        unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, NULL, true);
-                        load_extras = true;
-                }
-
-                if (u->load_state == UNIT_NOT_FOUND) {
-                        u->load_state = UNIT_LOADED;
-                        u->load_error = 0;
-
-                        /* Load in the extras later on, after we
-                         * finished initialization of the unit */
-                        load_extras = true;
-                        changed = true;
-                }
-        }
+                r = mount_setup_new_unit(u, what, where, options, fstype, &flags);
+                if (r < 0)
+                        unit_free(u);
+        } else
+                r = mount_setup_existing_unit(u, what, where, options, fstype, &flags);
 
-        w = strdup(what);
-        o = strdup(options);
-        f = strdup(fstype);
-        if (!w || !o || !f) {
-                r = -ENOMEM;
+        if (r < 0)
                 goto fail;
-        }
-
-        p = &MOUNT(u)->parameters_proc_self_mountinfo;
-
-        changed = changed ||
-                !streq_ptr(p->options, options) ||
-                !streq_ptr(p->what, what) ||
-                !streq_ptr(p->fstype, fstype);
 
         if (set_flags) {
-                MOUNT(u)->is_mounted = true;
-                MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
-                MOUNT(u)->just_changed = changed;
+                MOUNT(u)->is_mounted = flags.is_mounted;
+                MOUNT(u)->just_mounted = flags.just_mounted;
+                MOUNT(u)->just_changed = flags.just_changed;
         }
 
-        MOUNT(u)->from_proc_self_mountinfo = true;
-
-        free_and_replace(p->what, w);
-        free_and_replace(p->options, o);
-        free_and_replace(p->fstype, f);
-
-        if (load_extras) {
-                r = mount_add_extras(MOUNT(u));
-                if (r < 0)
-                        goto fail;
-        }
-
-        if (changed)
+        if (flags.just_changed)
                 unit_add_to_dbus_queue(u);
 
         return 0;
-
 fail:
         log_warning_errno(r, "Failed to set up mount unit: %m");
-
-        if (delete && u)
-                unit_free(u);
-
         return r;
 }
 
@@ -1572,7 +1655,6 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
 }
 
 static void mount_shutdown(Manager *m) {
-
         assert(m);
 
         m->mount_event_source = sd_event_source_unref(m->mount_event_source);
@@ -1843,6 +1925,10 @@ static void mount_reset_failed(Unit *u) {
 }
 
 static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
+        Mount *m = MOUNT(u);
+
+        assert(m);
+
         return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
 }