]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add implicit ordering dep on blockdev@.target from all mount units
authorLennart Poettering <lennart@poettering.net>
Tue, 21 Jan 2020 17:19:08 +0000 (18:19 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 21 Jan 2020 19:23:44 +0000 (20:23 +0100)
This way we shuld be able to order mounts properly against their backing
services in case complex storage is used (i.e. LUKS), even if the device
path used for mounting the devices is different from the expected device
node of the backing service.

Specifically, if we have a LUKS device /dev/mapper/foo that is mounted
by this name all is trivial as the relationship can be established a
priori easily. But if it is mounted via a /dev/disk/by-uuid/ symlink or
similar we only can relate the device node generated to the one mounted
at the moment the device is actually established. That's because the
UUID of the fs is stored inside the encrypted volume and thus not
knowable until the volume is set up. This patch tries to improve on this
situation: a implicit After=blockdev@.target dependency is generated for
all mounts, based on the data from /proc/self/mountinfo, which should be
the actual device node, with all symlinks resolved. This means that as
soon as the mount is established the ordering via blockdev@.target will
work, and that means during shutdown it is honoured, which is what we
are looking for.

Note that specifying /etc/fstab entries via UUID= for LUKS devices still
sucks and shouldn't be done, because it means we cannot know which LUKS
device to activate to make an fs appear, and that means unless the
volume is set up at boot anyway we can't really handle things
automatically when putting together transactions that need the mount.

src/core/mount.c
src/core/swap.c
src/core/unit.c
src/core/unit.h

index 0964eb18642dae881459ac0f9fe83dba0dd27194..1c4aefd734f3e01664f419b0f0d7c5e3b41ccec8 100644 (file)
@@ -350,11 +350,10 @@ static int mount_add_device_dependencies(Mount *m) {
         if (path_equal(m->where, "/"))
                 return 0;
 
-        /* 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. */
+        /* 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;
 
         /* We always use 'what' from /proc/self/mountinfo if mounted */
@@ -364,7 +363,7 @@ static int mount_add_device_dependencies(Mount *m) {
         if (r < 0)
                 return r;
 
-        return 0;
+        return unit_add_blockdev_dependency(UNIT(m), p->what, mask);
 }
 
 static int mount_add_quota_dependencies(Mount *m) {
index 713d7856185d4ed8c9be2632bc360658cfc90014..fd2fa557dbf66b61b3331880518e52d962becb8a 100644 (file)
@@ -199,6 +199,7 @@ static SwapParameters* swap_get_parameters(Swap *s) {
 static int swap_add_device_dependencies(Swap *s) {
         UnitDependencyMask mask;
         SwapParameters *p;
+        int r;
 
         assert(s);
 
@@ -211,8 +212,13 @@ static int swap_add_device_dependencies(Swap *s) {
 
         mask = s->from_proc_swaps ? UNIT_DEPENDENCY_PROC_SWAP : UNIT_DEPENDENCY_FILE;
 
-        if (is_device_path(p->what))
-                return unit_add_node_dependency(UNIT(s), p->what, UNIT_REQUIRES, mask);
+        if (is_device_path(p->what)) {
+                r = unit_add_node_dependency(UNIT(s), p->what, UNIT_REQUIRES, mask);
+                if (r < 0)
+                        return r;
+
+                return unit_add_blockdev_dependency(UNIT(s), p->what, mask);
+        }
 
         /* File based swap devices need to be ordered after systemd-remount-fs.service, since they might need
          * a writable file system. */
index c629a1a9ce00eb226b2a2517eede9e32f0ce99ef..9e95857d9abd32851ce090dfdb2839e6d1583dc5 100644 (file)
@@ -3846,8 +3846,8 @@ int unit_deserialize_skip(FILE *f) {
 }
 
 int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) {
-        Unit *device;
         _cleanup_free_ char *e = NULL;
+        Unit *device;
         int r;
 
         assert(u);
@@ -3859,8 +3859,7 @@ int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, Unit
         if (!is_device_path(what))
                 return 0;
 
-        /* When device units aren't supported (such as in a
-         * container), don't create dependencies on them. */
+        /* When device units aren't supported (such as in a container), don't create dependencies on them. */
         if (!unit_type_supported(UNIT_DEVICE))
                 return 0;
 
@@ -3880,6 +3879,33 @@ int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, Unit
                                          device, true, mask);
 }
 
+int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask) {
+        _cleanup_free_ char *escaped = NULL, *target = NULL;
+        int r;
+
+        assert(u);
+
+        if (isempty(what))
+                return 0;
+
+        if (!path_startswith(what, "/dev/"))
+                return 0;
+
+        /* If we don't support devices, then also don't bother with blockdev@.target */
+        if (!unit_type_supported(UNIT_DEVICE))
+                return 0;
+
+        r = unit_name_path_escape(what, &escaped);
+        if (r < 0)
+                return r;
+
+        r = unit_name_build("blockdev", escaped, ".target", &target);
+        if (r < 0)
+                return r;
+
+        return unit_add_dependency_by_name(u, UNIT_AFTER, target, true, mask);
+}
+
 int unit_coldplug(Unit *u) {
         int r = 0, q;
         char **i;
index 68de900b0d523165ea86c1fbd44c869971e64122..38d681dfb86de30ebad091b39b755335ba52a356 100644 (file)
@@ -743,6 +743,7 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
 int unit_deserialize_skip(FILE *f);
 
 int unit_add_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask);
+int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask mask);
 
 int unit_coldplug(Unit *u);
 void unit_catchup(Unit *u);