From: Mike Yuan Date: Thu, 12 Oct 2023 10:38:15 +0000 (+0800) Subject: core/mount: allow disabling stop propagation from backing device X-Git-Tag: v255-rc1~223 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=707ecf1423ba8797ccc3ced016cc9e0f23635838;p=thirdparty%2Fsystemd.git core/mount: allow disabling stop propagation from backing device With file systems that have volume management functionalities or volume managers like LVM, it's fine for the backing device of a mount to disappear after mounted. Currently, we enforce BindsTo= or StopPropagatedFrom= on the backing device, thus prohibiting such cases. Instead, let's make this configurable through x-systemd.device-bound. Closes #16801 Closes #29543 --- diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml index 4cdd41c995f..c2e470e7dcb 100644 --- a/man/systemd.mount.xml +++ b/man/systemd.mount.xml @@ -269,16 +269,15 @@ - - - The block device backed file system will be upgraded - to BindsTo= dependency. This option is only useful - when mounting file systems manually with - mount8 - as the default dependency in this case is Requires=. - This option is already implied by entries in /etc/fstab - or by mount units. - + + + Takes a boolean argument. If true or no argument, a BindsTo= dependency + on the backing device is set. If false, the mount unit is not stopped no matter whether the backing device + is still present. This is useful when the file system is backed by volume managers. If not set, and the mount + comes from unit fragments, i.e. generated from /etc/fstab by + systemd-fstab-generator8 or loaded from + a manually configured mount unit, a combination of Requires= and StopPropagatedFrom= + dependencies is set on the backing device. If doesn't, only Requires= is used. diff --git a/src/core/mount.c b/src/core/mount.c index fe04b3d74c9..b6b76c56025 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -125,13 +125,15 @@ static bool mount_is_bind(const MountParameters *p) { return fstab_is_bind(p->options, p->fstype); } -static bool mount_is_bound_to_device(Mount *m) { +static int mount_is_bound_to_device(Mount *m) { + _cleanup_free_ char *value = NULL; const MountParameters *p; + int r; assert(m); /* Determines whether to place a Requires= or BindsTo= dependency on the backing device unit. We do - * this by checking for the x-systemd.device-bound mount option. Iff it is set we use BindsTo=, + * this by checking for the x-systemd.device-bound= mount option. If it is enabled we use BindsTo=, * otherwise Requires=. But note that we might combine the latter with StopPropagatedFrom=, see * below. */ @@ -139,14 +141,30 @@ static bool mount_is_bound_to_device(Mount *m) { if (!p) return false; - return fstab_test_option(p->options, "x-systemd.device-bound\0"); + r = fstab_filter_options(p->options, "x-systemd.device-bound\0", NULL, &value, NULL, NULL); + if (r < 0) + return r; + if (r == 0) + return -EIDRM; /* If unspecified at all, return recognizable error */ + + if (isempty(value)) + return true; + + return parse_boolean(value); } static bool mount_propagate_stop(Mount *m) { + int r; + assert(m); - if (mount_is_bound_to_device(m)) /* If we are using BindsTo= the stop propagation is implicit, no need to bother */ + r = mount_is_bound_to_device(m); + if (r >= 0) + /* If x-systemd.device-bound=no is explicitly requested by user, don't try to set StopPropagatedFrom=. + * Also don't bother if true, since with BindsTo= the stop propagation is implicit. */ return false; + if (r != -EIDRM) + log_debug_errno(r, "Failed to get x-systemd.device-bound= option, ignoring: %m"); return m->from_fragment; /* let's propagate stop whenever this is an explicitly configured unit, * otherwise let's not bother. */ @@ -367,7 +385,7 @@ static int mount_add_device_dependencies(Mount *m) { * maintain. The user can still force this to be a BindsTo= dependency 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; + dep = mount_is_bound_to_device(m) > 0 ? UNIT_BINDS_TO : UNIT_REQUIRES; /* We always use 'what' from /proc/self/mountinfo if mounted */ mask = m->from_proc_self_mountinfo ? UNIT_DEPENDENCY_MOUNTINFO : UNIT_DEPENDENCY_MOUNT_FILE;