]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/mount: make device deps from /proc/self/mountinfo and .mount unit file exclusive
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 14 May 2022 21:31:17 +0000 (06:31 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 4 Aug 2022 16:35:38 +0000 (01:35 +0900)
Before this commit, when a .mount unit file is loaded, the device
dependencies from the unit file are automatically added. If a device
that is different from which specified in .mount unit file is mounted
on the path, then the device dependencies about the device are also added.
Hence, the unit has device dependencies about two (or more) different
devices. Hence, if one of the devices are unplugged, even if another one
is mounted on the path, then the path is unmounted.

This commit makes device dependencies from two different sources
exclusive, and always regenerate the dependencies when one of the
information is updated.

Fixes #19983 and #23552.

src/core/mount.c
src/core/unit-serialize.c
src/core/unit.h

index 71da69cbb5f4dd4b3188ade6eec5111b7aae08a2..9dc04cd07e97228eb7aec877534b787225706cb0 100644 (file)
@@ -347,7 +347,6 @@ static int mount_add_mount_dependencies(Mount *m) {
 }
 
 static int mount_add_device_dependencies(Mount *m) {
-        UnitDependencyMask mask;
         MountParameters *p;
         UnitDependency dep;
         int r;
@@ -396,17 +395,14 @@ static int mount_add_device_dependencies(Mount *m) {
          * suddenly. */
         dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES;
 
-        /* We always use 'what' from /proc/self/mountinfo if mounted */
-        mask = m->from_proc_self_mountinfo ? UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT : UNIT_DEPENDENCY_FILE;
-
-        r = unit_add_node_dependency(UNIT(m), p->what, dep, mask);
+        r = unit_add_node_dependency(UNIT(m), p->what, dep, UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
         if (r < 0)
                 return r;
         if (r > 0)
                 log_unit_trace(UNIT(m), "Added %s dependency on %s", unit_dependency_to_string(dep), p->what);
 
         if (mount_propagate_stop(m)) {
-                r = unit_add_node_dependency(UNIT(m), p->what, UNIT_STOP_PROPAGATED_FROM, mask);
+                r = unit_add_node_dependency(UNIT(m), p->what, UNIT_STOP_PROPAGATED_FROM, UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
                 if (r < 0)
                         return r;
                 if (r > 0)
@@ -414,11 +410,11 @@ static int mount_add_device_dependencies(Mount *m) {
                                        unit_dependency_to_string(UNIT_STOP_PROPAGATED_FROM), p->what);
         }
 
-        r = unit_add_blockdev_dependency(UNIT(m), p->what, mask);
+        r = unit_add_blockdev_dependency(UNIT(m), p->what, UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
         if (r > 0)
                 log_unit_trace(UNIT(m), "Added %s dependency on %s", unit_dependency_to_string(UNIT_AFTER), p->what);
 
-        return r;
+        return 0;
 }
 
 static int mount_add_quota_dependencies(Mount *m) {
@@ -474,8 +470,7 @@ static bool mount_is_extrinsic(Unit *u) {
 
 static int mount_add_default_ordering_dependencies(
                 Mount *m,
-                MountParameters *p,
-                UnitDependencyMask mask) {
+                MountParameters *p) {
 
         const char *after, *before, *e;
         int r;
@@ -501,23 +496,25 @@ static int mount_add_default_ordering_dependencies(
         }
 
         if (!mount_is_nofail(m)) {
-                r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true,
+                                                UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
                 if (r < 0)
                         return r;
         }
 
         if (after) {
-                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true,
+                                                UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
                 if (r < 0)
                         return r;
         }
 
         return unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS,
-                                                 SPECIAL_UMOUNT_TARGET, true, mask);
+                                                 SPECIAL_UMOUNT_TARGET, true,
+                                                 UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
 }
 
 static int mount_add_default_dependencies(Mount *m) {
-        UnitDependencyMask mask;
         MountParameters *p;
         int r;
 
@@ -537,9 +534,7 @@ static int mount_add_default_dependencies(Mount *m) {
         if (!p)
                 return 0;
 
-        mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
-
-        r = mount_add_default_ordering_dependencies(m, p, mask);
+        r = mount_add_default_ordering_dependencies(m, p);
         if (r < 0)
                 return r;
 
@@ -549,7 +544,8 @@ 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, true, mask);
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, true,
+                                                UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
                 if (r < 0)
                         return r;
 
@@ -558,14 +554,17 @@ static int mount_add_default_dependencies(Mount *m) {
                  * mounting network file systems, and 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, true, mask);
+                r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER,
+                                                      SPECIAL_NETWORK_ONLINE_TARGET, true,
+                                                      UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
                 if (r < 0)
                         return r;
         }
 
         /* 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, true, mask);
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, true,
+                                                UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
                 if (r < 0)
                         return r;
         }
@@ -607,8 +606,18 @@ static int mount_verify(Mount *m) {
 
 static int mount_add_non_exec_dependencies(Mount *m) {
         int r;
+
         assert(m);
 
+        /* Any dependencies based on /proc/self/mountinfo may be now stale. */
+        unit_remove_dependencies(UNIT(m),
+                                 UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT |
+                                 UNIT_DEPENDENCY_MOUNTINFO_DEFAULT |
+                                 UNIT_DEPENDENCY_MOUNTINFO_OR_FILE);
+
+        if (!m->where)
+                return 0;
+
         /* Adds in all dependencies directly responsible for ordering the mount, as opposed to dependencies
          * resulting from the ExecContext and such. */
 
@@ -908,8 +917,9 @@ static void mount_enter_dead(Mount *m, MountResult f) {
 
         dynamic_creds_destroy(&m->dynamic_creds);
 
-        /* Any dependencies based on /proc/self/mountinfo are now stale */
-        unit_remove_dependencies(UNIT(m), UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT | UNIT_DEPENDENCY_MOUNTINFO_DEFAULT);
+        /* Any dependencies based on /proc/self/mountinfo are now stale. Let's re-generate dependencies from
+         * .mount unit. */
+        (void) mount_add_non_exec_dependencies(m);
 }
 
 static void mount_enter_mounted(Mount *m, MountResult f) {
@@ -1674,9 +1684,6 @@ static int mount_setup_existing_unit(
         if (FLAGS_SET(flags, MOUNT_PROC_JUST_CHANGED)) {
                 /* If things changed, then make sure that all deps are regenerated. Let's
                  * first remove all automatic deps, and then add in the new ones. */
-
-                unit_remove_dependencies(u, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT | UNIT_DEPENDENCY_MOUNTINFO_DEFAULT);
-
                 r = mount_add_non_exec_dependencies(MOUNT(u));
                 if (r < 0)
                         return r;
index 3897bdee7c4215681bcd0c19be7524bb0c82500b..797bf6c5ce92248e2c66b850ee89605431a197fa 100644 (file)
@@ -592,6 +592,7 @@ static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependency
                 { UNIT_DEPENDENCY_PATH,               "path"               },
                 { UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT, "mountinfo-implicit" },
                 { UNIT_DEPENDENCY_MOUNTINFO_DEFAULT,  "mountinfo-default"  },
+                { UNIT_DEPENDENCY_MOUNTINFO_OR_FILE,  "mountinfo-or-file"  },
                 { UNIT_DEPENDENCY_PROC_SWAP,          "proc-swap"          },
                 { UNIT_DEPENDENCY_SLICE_PROPERTY,     "slice-property"     },
         };
index 33884fc9916ec556879a42fdd4df1ef311fc83ed..4dabbb9a3c93fcd94243759b88bc1d60d8acaa8a 100644 (file)
@@ -86,13 +86,17 @@ typedef enum UnitDependencyMask {
          * DefaultDependencies= and thus also involving configuration from UNIT_DEPENDENCY_FILE sources */
         UNIT_DEPENDENCY_MOUNTINFO_DEFAULT  = 1 << 6,
 
+        /* A dependency created because of data read from /proc/self/mountinfo, but fallback to unit configuration
+         * sources */
+        UNIT_DEPENDENCY_MOUNTINFO_OR_FILE  = 1 << 7,
+
         /* A dependency created because of data read from /proc/swaps and no other configuration source */
-        UNIT_DEPENDENCY_PROC_SWAP          = 1 << 7,
+        UNIT_DEPENDENCY_PROC_SWAP          = 1 << 8,
 
         /* A dependency for units in slices assigned by directly setting Slice= */
-        UNIT_DEPENDENCY_SLICE_PROPERTY     = 1 << 8,
+        UNIT_DEPENDENCY_SLICE_PROPERTY     = 1 << 9,
 
-        _UNIT_DEPENDENCY_MASK_FULL         = (1 << 9) - 1,
+        _UNIT_DEPENDENCY_MASK_FULL         = (1 << 10) - 1,
 } UnitDependencyMask;
 
 /* The Unit's dependencies[] hashmaps use this structure as value. It has the same size as a void pointer, and thus can