]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/mount.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / core / mount.c
index 6e42176c09583c85efb3b217cbf2bb5ee0cfb2d9..c96c137d297b754db3100bd05206547f16cd8925 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <errno.h>
 #include <signal.h>
@@ -66,6 +66,14 @@ static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
                       MOUNT_CLEANING);
 }
 
+static bool mount_is_automount(const MountParameters *p) {
+        assert(p);
+
+        return fstab_test_option(p->options,
+                                 "comment=systemd.automount\0"
+                                 "x-systemd.automount\0");
+}
+
 static bool mount_is_network(const MountParameters *p) {
         assert(p);
 
@@ -78,6 +86,15 @@ static bool mount_is_network(const MountParameters *p) {
         return false;
 }
 
+static bool mount_is_nofail(const Mount *m) {
+        assert(m);
+
+        if (!m->from_fragment)
+                return false;
+
+        return fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0");
+}
+
 static bool mount_is_loop(const MountParameters *p) {
         assert(p);
 
@@ -217,7 +234,7 @@ static void mount_done(Unit *u) {
         m->timer_event_source = sd_event_source_unref(m->timer_event_source);
 }
 
-_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
+static MountParameters* get_mount_parameters_fragment(Mount *m) {
         assert(m);
 
         if (m->from_fragment)
@@ -226,7 +243,7 @@ _pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
         return NULL;
 }
 
-_pure_ static MountParameters* get_mount_parameters(Mount *m) {
+static MountParameters* get_mount_parameters(Mount *m) {
         assert(m);
 
         if (m->from_proc_self_mountinfo)
@@ -264,7 +281,6 @@ static int update_parameters_proc_self_mountinfo(
 static int mount_add_mount_dependencies(Mount *m) {
         MountParameters *pm;
         Unit *other;
-        Iterator i;
         Set *s;
         int r;
 
@@ -298,7 +314,7 @@ static int mount_add_mount_dependencies(Mount *m) {
 
         /* Adds in dependencies to other units that use this path or paths further down in the hierarchy */
         s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
-        SET_FOREACH(other, s, i) {
+        SET_FOREACH(other, s) {
 
                 if (other->load_state != UNIT_LOADED)
                         continue;
@@ -342,20 +358,18 @@ static int mount_add_device_dependencies(Mount *m) {
         if (!is_device_path(p->what))
                 return 0;
 
-        /* /dev/root is a really weird thing, it's not a real device,
-         * but just a path the kernel exports for the root file system
-         * specified on the kernel command line. Ignore it here. */
-        if (path_equal(p->what, "/dev/root"))
+        /* /dev/root is a really weird thing, it's not a real device, but just a path the kernel exports for
+         * the root file system specified on the kernel command line. Ignore it here. */
+        if (PATH_IN_SET(p->what, "/dev/root", "/dev/nfs"))
                 return 0;
 
         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 */
@@ -365,7 +379,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) {
@@ -402,38 +416,72 @@ static bool mount_is_extrinsic(Mount *m) {
         MountParameters *p;
         assert(m);
 
-        /* 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;
+        /* 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 (PATH_IN_SET(m->where,  /* Don't bother with the OS data itself */
-                        "/",
-                        "/usr"))
+        /* We only automatically manage mounts if we are in system mode */
+        if (!MANAGER_IS_SYSTEM(UNIT(m)->manager))
                 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 … */
+        if (UNIT(m)->perpetual) /* All perpetual units never change state */
                 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())
+        if (p && fstab_is_extrinsic(m->where, p->options))
                 return true;
 
         return false;
 }
 
+static int mount_add_default_ordering_dependencies(
+                Mount *m,
+                MountParameters *p,
+                UnitDependencyMask mask) {
+
+        const char *after, *before, *e;
+        int r;
+
+        assert(m);
+
+        e = path_startswith(m->where, "/sysroot");
+        if (e && in_initrd()) {
+                /* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW,
+                 * it's not technically part of the basic initrd filesystem itself, and so
+                 * shouldn't inherit the default Before=local-fs.target dependency. */
+
+                after = NULL;
+                before = isempty(e) ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_INITRD_FS_TARGET;
+
+        } else if (mount_is_network(p)) {
+                after = SPECIAL_REMOTE_FS_PRE_TARGET;
+                before = SPECIAL_REMOTE_FS_TARGET;
+
+        } else {
+                after = SPECIAL_LOCAL_FS_PRE_TARGET;
+                before = SPECIAL_LOCAL_FS_TARGET;
+        }
+
+        if (!mount_is_nofail(m) && !mount_is_automount(p)) {
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
+                if (r < 0)
+                        return r;
+        }
+
+        if (after) {
+                r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
+                if (r < 0)
+                        return r;
+        }
+
+        return unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS,
+                                                 SPECIAL_UMOUNT_TARGET, true, mask);
+}
+
 static int mount_add_default_dependencies(Mount *m) {
-        const char *after, *before;
         UnitDependencyMask mask;
         MountParameters *p;
-        bool nofail;
         int r;
 
         assert(m);
@@ -441,9 +489,10 @@ static int mount_add_default_dependencies(Mount *m) {
         if (!UNIT(m)->default_dependencies)
                 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. */
+        /* 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;
 
@@ -452,51 +501,31 @@ static int mount_add_default_dependencies(Mount *m) {
                 return 0;
 
         mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
-        nofail = m->from_fragment ? fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0") : false;
+
+        r = mount_add_default_ordering_dependencies(m, p, mask);
+        if (r < 0)
+                return r;
 
         if (mount_is_network(p)) {
-                /* We order ourselves after network.target. This is
-                 * primarily useful at shutdown: services that take
-                 * down the network should order themselves before
-                 * network.target, so that they are shut down only
-                 * after this mount unit is stopped. */
+                /* We order ourselves after network.target. This is primarily useful at shutdown:
+                 * services that take down the network should order themselves before
+                 * 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);
                 if (r < 0)
                         return r;
 
-                /* We pull in network-online.target, and order
-                 * ourselves after it. This is useful at start-up to
-                 * actively pull in tools that want to be started
-                 * before we start mounting network file systems, and
-                 * whose purpose it is to delay this until the network
-                 * is "up". */
+                /* We pull in network-online.target, and order ourselves after it. This is useful
+                 * at start-up to actively pull in tools that want to be started before we start
+                 * 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);
                 if (r < 0)
                         return r;
-
-                after = SPECIAL_REMOTE_FS_PRE_TARGET;
-                before = SPECIAL_REMOTE_FS_TARGET;
-        } else {
-                after = SPECIAL_LOCAL_FS_PRE_TARGET;
-                before = SPECIAL_LOCAL_FS_TARGET;
-        }
-
-        if (!nofail) {
-                r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
-                if (r < 0)
-                        return r;
         }
 
-        r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
-        if (r < 0)
-                return r;
-
-        r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, mask);
-        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);
@@ -533,10 +562,9 @@ static int mount_verify(Mount *m) {
         }
 
         p = get_mount_parameters_fragment(m);
-        if (p && !p->what) {
-                log_unit_error(UNIT(m), "What= setting is missing. Refusing.");
-                return -ENOEXEC;
-        }
+        if (p && !p->what && !UNIT(m)->perpetual)
+                return log_unit_error_errno(UNIT(m), SYNTHETIC_ERRNO(ENOEXEC),
+                                            "What= setting is missing. Refusing.");
 
         if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) {
                 log_unit_error(UNIT(m), "Unit has PAM enabled. Kill mode must be set to control-group'. Refusing.");
@@ -546,6 +574,32 @@ static int mount_verify(Mount *m) {
         return 0;
 }
 
+static int mount_add_non_exec_dependencies(Mount *m) {
+        int r;
+        assert(m);
+
+        /* Adds in all dependencies directly responsible for ordering the mount, as opposed to dependencies
+         * resulting from the ExecContext and such. */
+
+        r = mount_add_device_dependencies(m);
+        if (r < 0)
+                return r;
+
+        r = mount_add_mount_dependencies(m);
+        if (r < 0)
+                return r;
+
+        r = mount_add_quota_dependencies(m);
+        if (r < 0)
+                return r;
+
+        r = mount_add_default_dependencies(m);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 static int mount_add_extras(Mount *m) {
         Unit *u = UNIT(m);
         int r;
@@ -573,18 +627,6 @@ static int mount_add_extras(Mount *m) {
                         return r;
         }
 
-        r = mount_add_device_dependencies(m);
-        if (r < 0)
-                return r;
-
-        r = mount_add_mount_dependencies(m);
-        if (r < 0)
-                return r;
-
-        r = mount_add_quota_dependencies(m);
-        if (r < 0)
-                return r;
-
         r = unit_patch_contexts(u);
         if (r < 0)
                 return r;
@@ -597,7 +639,7 @@ static int mount_add_extras(Mount *m) {
         if (r < 0)
                 return r;
 
-        r = mount_add_default_dependencies(m);
+        r = mount_add_non_exec_dependencies(m);
         if (r < 0)
                 return r;
 
@@ -737,6 +779,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
                 "%sSloppyOptions: %s\n"
                 "%sLazyUnmount: %s\n"
                 "%sForceUnmount: %s\n"
+                "%sReadWriteOnly: %s\n"
                 "%sTimeoutSec: %s\n",
                 prefix, mount_state_to_string(m->state),
                 prefix, mount_result_to_string(m->result),
@@ -752,6 +795,7 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) {
                 prefix, yes_no(m->sloppy_options),
                 prefix, yes_no(m->lazy_unmount),
                 prefix, yes_no(m->force_unmount),
+                prefix, yes_no(m->read_write_only),
                 prefix, format_timespan(buf, sizeof(buf), m->timeout_usec, USEC_PER_SEC));
 
         if (m->control_pid > 0)
@@ -818,11 +862,13 @@ static void mount_enter_dead(Mount *m, MountResult f) {
                 m->result = f;
 
         unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result));
+        unit_warn_leftover_processes(UNIT(m), unit_log_leftover_process_stop);
+
         mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
 
         m->exec_runtime = exec_runtime_unref(m->exec_runtime, true);
 
-        unit_destroy_runtime_directory(UNIT(m), &m->exec_context);
+        unit_destroy_runtime_data(UNIT(m), &m->exec_context);
 
         unit_unref_uid_gid(UNIT(m), true);
 
@@ -963,15 +1009,18 @@ static void mount_enter_mounting(Mount *m) {
         (void) mkdir_p_label(m->where, m->directory_mode);
 
         unit_warn_if_dir_nonempty(UNIT(m), m->where);
-        unit_warn_leftover_processes(UNIT(m));
+        unit_warn_leftover_processes(UNIT(m), unit_log_leftover_process_start);
 
         m->control_command_id = MOUNT_EXEC_MOUNT;
         m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
 
         /* Create the source directory for bind-mounts if needed */
         p = get_mount_parameters_fragment(m);
-        if (p && mount_is_bind(p))
-                (void) mkdir_p_label(p->what, m->directory_mode);
+        if (p && mount_is_bind(p)) {
+                r = mkdir_p_label(p->what, m->directory_mode);
+                if (r < 0)
+                        log_unit_error_errno(UNIT(m), r, "Failed to make bind mount source '%s': %m", p->what);
+        }
 
         if (p) {
                 _cleanup_free_ char *opts = NULL;
@@ -983,6 +1032,8 @@ static void mount_enter_mounting(Mount *m) {
                 r = exec_command_set(m->control_command, MOUNT_PATH, p->what, m->where, NULL);
                 if (r >= 0 && m->sloppy_options)
                         r = exec_command_append(m->control_command, "-s", NULL);
+                if (r >= 0 && m->read_write_only)
+                        r = exec_command_append(m->control_command, "-w", NULL);
                 if (r >= 0 && p->fstype)
                         r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
                 if (r >= 0 && !isempty(opts))
@@ -1043,6 +1094,8 @@ static void mount_enter_remounting(Mount *m) {
                                      "-o", o, NULL);
                 if (r >= 0 && m->sloppy_options)
                         r = exec_command_append(m->control_command, "-s", NULL);
+                if (r >= 0 && m->read_write_only)
+                        r = exec_command_append(m->control_command, "-w", NULL);
                 if (r >= 0 && p->fstype)
                         r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
         } else
@@ -1532,11 +1585,10 @@ static int mount_setup_existing_unit(
                 const char *fstype,
                 MountProcFlags *ret_flags) {
 
-        MountProcFlags flags = MOUNT_PROC_IS_MOUNTED;
         int r;
 
         assert(u);
-        assert(flags);
+        assert(ret_flags);
 
         if (!MOUNT(u)->where) {
                 MOUNT(u)->where = strdup(where);
@@ -1544,13 +1596,27 @@ static int mount_setup_existing_unit(
                         return -ENOMEM;
         }
 
+        /* In case we have multiple mounts established on the same mount point, let's merge flags set already
+         * for the current unit. Note that the flags field is reset on each iteration of reading
+         * /proc/self/mountinfo, hence we know for sure anything already set here is from the current
+         * iteration and thus worthy of taking into account. */
+        MountProcFlags flags =
+                MOUNT(u)->proc_flags | MOUNT_PROC_IS_MOUNTED;
+
         r = update_parameters_proc_self_mountinfo(MOUNT(u), what, options, fstype);
         if (r < 0)
                 return r;
         if (r > 0)
                 flags |= MOUNT_PROC_JUST_CHANGED;
 
-        if (!MOUNT(u)->from_proc_self_mountinfo || FLAGS_SET(MOUNT(u)->proc_flags, MOUNT_PROC_JUST_MOUNTED))
+        /* There are two conditions when we consider a mount point just mounted: when we haven't seen it in
+         * /proc/self/mountinfo before or when MOUNT_MOUNTING is our current state. Why bother with the
+         * latter? Shouldn't that be covered by the former? No, during reload it is not because we might then
+         * encounter a new /proc/self/mountinfo in combination with an old mount unit state (since it stems
+         * from the serialized state), and need to catch up. Since we know that the MOUNT_MOUNTING state is
+         * reached when we wait for the mount to appear we hence can assume that if we are in it, we are
+         * actually seeing it established for the first time. */
+        if (!MOUNT(u)->from_proc_self_mountinfo || MOUNT(u)->state == MOUNT_MOUNTING)
                 flags |= MOUNT_PROC_JUST_MOUNTED;
 
         MOUNT(u)->from_proc_self_mountinfo = true;
@@ -1570,7 +1636,7 @@ static int mount_setup_existing_unit(
 
                 unit_remove_dependencies(u, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT);
 
-                r = mount_add_extras(MOUNT(u));
+                r = mount_add_non_exec_dependencies(MOUNT(u));
                 if (r < 0)
                         return r;
         }
@@ -1610,9 +1676,30 @@ static int mount_setup_unit(
         if (!is_path(where))
                 return 0;
 
+        /* Mount unit names have to be (like all other unit names) short enough to fit into file names. This
+         * means there's a good chance that overly long mount point paths after mangling them to look like a
+         * unit name would result in unit names we don't actually consider valid. This should be OK however
+         * as such long mount point paths should not happen on regular systems — and if they appear
+         * nonetheless they are generally synthesized by software, and thus managed by that other
+         * software. Having such long names just means you cannot use systemd to manage those specific mount
+         * points, which should be an OK restriction to make. After all we don't have to be able to manage
+         * all mount points in the world — as long as we don't choke on them when we encounter them. */
         r = unit_name_from_path(where, ".mount", &e);
-        if (r < 0)
-                return log_error_errno(r, "Failed to generate unit name from path '%s': %m", where);
+        if (r < 0) {
+                static RateLimit rate_limit = { /* Let's log about this at warning level at most once every
+                                                 * 5s. Given that we generate this whenever we read the file
+                                                 * otherwise we probably shouldn't flood the logs with
+                                                 * this */
+                        .interval = 5 * USEC_PER_SEC,
+                        .burst = 1,
+                };
+
+                return log_struct_errno(
+                                ratelimit_below(&rate_limit) ? LOG_WARNING : LOG_DEBUG, r,
+                                "MESSAGE_ID=" SD_MESSAGE_MOUNT_POINT_PATH_NOT_SUITABLE_STR,
+                                "MOUNT_POINT=%s", where,
+                                LOG_MESSAGE("Failed to generate valid unit name from path '%s', ignoring mount point: %m", where));
+        }
 
         u = manager_get_unit(m, e);
         if (u)
@@ -1622,7 +1709,7 @@ static int mount_setup_unit(
                  * by the sysadmin having called mount(8) directly. */
                 r = mount_setup_new_unit(m, e, what, where, options, fstype, &flags, &u);
         if (r < 0)
-                return log_warning_errno(r, "Failed to set up mount unit: %m");
+                return log_warning_errno(r, "Failed to set up mount unit for '%s': %m", where);
 
         /* If the mount changed properties or state, let's notify our clients */
         if (flags & (MOUNT_PROC_JUST_CHANGED|MOUNT_PROC_JUST_MOUNTED))
@@ -1815,7 +1902,6 @@ static int drain_libmount(Manager *m) {
 static int mount_process_proc_self_mountinfo(Manager *m) {
         _cleanup_set_free_free_ Set *around = NULL, *gone = NULL;
         const char *what;
-        Iterator i;
         Unit *u;
         int r;
 
@@ -1850,7 +1936,7 @@ static int mount_process_proc_self_mountinfo(Manager *m) {
 
                                 /* Remember that this device might just have disappeared */
                                 if (set_ensure_allocated(&gone, &path_hash_ops) < 0 ||
-                                    set_put_strdup(gone, mount->parameters_proc_self_mountinfo.what) < 0)
+                                    set_put_strdup(&gone, mount->parameters_proc_self_mountinfo.what) < 0)
                                         log_oom(); /* we don't care too much about OOM here... */
                         }
 
@@ -1905,7 +1991,7 @@ static int mount_process_proc_self_mountinfo(Manager *m) {
                         /* Track devices currently used */
 
                         if (set_ensure_allocated(&around, &path_hash_ops) < 0 ||
-                            set_put_strdup(around, mount->parameters_proc_self_mountinfo.what) < 0)
+                            set_put_strdup(&around, mount->parameters_proc_self_mountinfo.what) < 0)
                                 log_oom();
                 }
 
@@ -1913,7 +1999,7 @@ static int mount_process_proc_self_mountinfo(Manager *m) {
                 mount->proc_flags = 0;
         }
 
-        SET_FOREACH(what, gone, i) {
+        SET_FOREACH(what, gone) {
                 if (set_contains(around, what))
                         continue;
 
@@ -2047,6 +2133,9 @@ const UnitVTable mount_vtable = {
                 "Install\0",
         .private_section = "Mount",
 
+        .can_transient = true,
+        .can_fail = true,
+
         .init = mount_init,
         .load = mount_load,
         .done = mount_done,
@@ -2079,14 +2168,11 @@ const UnitVTable mount_vtable = {
 
         .control_pid = mount_control_pid,
 
-        .bus_vtable = bus_mount_vtable,
         .bus_set_property = bus_mount_set_property,
         .bus_commit_properties = bus_mount_commit_properties,
 
         .get_timeout = mount_get_timeout,
 
-        .can_transient = true,
-
         .enumerate_perpetual = mount_enumerate_perpetual,
         .enumerate = mount_enumerate,
         .shutdown = mount_shutdown,