]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/mount: allow disabling stop propagation from backing device
authorMike Yuan <me@yhndnzj.com>
Thu, 12 Oct 2023 10:38:15 +0000 (18:38 +0800)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 17 Oct 2023 10:23:36 +0000 (11:23 +0100)
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

man/systemd.mount.xml
src/core/mount.c

index 4cdd41c995f6c8b2aadddfc80eb4faf56c6a4c88..c2e470e7dcbe6f26952a1ab7608d6e2859dccee2 100644 (file)
        </varlistentry>
 
       <varlistentry>
-        <term><option>x-systemd.device-bound</option></term>
-
-        <listitem><para>The block device backed file system will be upgraded
-        to <varname>BindsTo=</varname> dependency. This option is only useful
-        when mounting file systems manually with
-        <citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-        as the default dependency in this case is <varname>Requires=</varname>.
-        This option is already implied by entries in <filename>/etc/fstab</filename>
-        or by mount units.
-        </para>
+        <term><option>x-systemd.device-bound=</option></term>
+
+        <listitem><para>Takes a boolean argument. If true or no argument, a <varname>BindsTo=</varname> 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 <filename>/etc/fstab</filename> by <citerefentry>
+        <refentrytitle>systemd-fstab-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry> or loaded from
+        a manually configured mount unit, a combination of <varname>Requires=</varname> and <varname>StopPropagatedFrom=</varname>
+        dependencies is set on the backing device. If doesn't, only <varname>Requires=</varname> is used.</para>
 
         <xi:include href="version-info.xml" xpointer="v233"/></listitem>
       </varlistentry>
index fe04b3d74c9d5dffed87fb9cf55c1c3fed76189f..b6b76c560254789327ce8b503099f717551a2355 100644 (file)
@@ -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;