]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: rework logic to determine when we decide to add automatic deps for mounts
authorLennart Poettering <lennart@poettering.net>
Tue, 29 Nov 2016 21:50:21 +0000 (22:50 +0100)
committerMartin Pitt <martin.pitt@ubuntu.com>
Wed, 14 Dec 2016 09:13:52 +0000 (10:13 +0100)
This adds a concept of "extrinsic" mounts. If mounts are extrinsic we consider
them managed by something else and do not add automatic ordering against
umount.target, local-fs.target, remote-fs.target.

Extrinsic mounts are considered:

- All mounts if we are running in --user mode

- API mounts such as everything below /proc, /sys, /dev, which exist from
  earliest boot to latest shutdown.

- All mounts marked as initrd mounts, if we run on the host

- The initrd's private directory /run/initrams that should survive until last
  reboot.

This primarily merges a couple of different exclusion lists into a single
concept.

src/basic/path-util.h
src/core/mount.c

index d548f0c3453dce776e5ea0ffe36a969a5b337c5b..349cdac7d6c223921a0b8d3dfac50a3846feb381 100644 (file)
@@ -66,6 +66,18 @@ static inline bool path_equal_ptr(const char *a, const char *b) {
                 _found;                                         \
         })
 
+#define PATH_STARTSWITH_SET(p, ...)                             \
+        ({                                                      \
+                char **s;                                       \
+                bool _found = false;                            \
+                STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__))         \
+                        if (path_startswith(p, *s)) {           \
+                               _found = true;                   \
+                               break;                           \
+                        }                                       \
+                _found;                                         \
+        })
+
 int path_strv_make_absolute_cwd(char **l);
 char** path_strv_resolve(char **l, const char *root);
 char** path_strv_resolve_uniq(char **l, const char *root);
index 0c4d061c276b9e5e656f3ec9799073942c4da8e3..997dbe383757c929fe629c96cc0160ddcd396b57 100644 (file)
@@ -387,19 +387,35 @@ static int mount_add_quota_links(Mount *m) {
         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) {
@@ -412,20 +428,10 @@ static int mount_add_default_dependencies(Mount *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);
@@ -462,11 +468,9 @@ static int mount_add_default_dependencies(Mount *m) {
         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 (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;
 }
@@ -688,6 +692,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 +705,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),
@@ -1420,7 +1426,7 @@ static int mount_setup_unit(
                         goto fail;
                 }
 
-                if (MANAGER_IS_SYSTEM(m)) {
+                if (!mount_is_extrinsic(MOUNT(u))) {
                         const char* target;
 
                         target = mount_needs_network(options, fstype) ?  SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
@@ -1428,11 +1434,9 @@ static int mount_setup_unit(
                         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;
-                        }
+                        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);
@@ -1448,7 +1452,7 @@ static int mount_setup_unit(
                         }
                 }
 
-                if (MANAGER_IS_SYSTEM(m) &&
+                if (!mount_is_extrinsic(MOUNT(u)) &&
                     mount_needs_network(options, fstype)) {
                         /* _netdev option may have shown up late, or on a
                          * remount. Add remote-fs dependencies, even though