1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/epoll.h>
31 #include "load-fragment.h"
32 #include "load-dropin.h"
34 #include "sd-messages.h"
37 #include "path-util.h"
38 #include "mount-setup.h"
39 #include "unit-name.h"
40 #include "dbus-mount.h"
42 #include "bus-errors.h"
43 #include "exit-status.h"
46 static const UnitActiveState state_translation_table
[_MOUNT_STATE_MAX
] = {
47 [MOUNT_DEAD
] = UNIT_INACTIVE
,
48 [MOUNT_MOUNTING
] = UNIT_ACTIVATING
,
49 [MOUNT_MOUNTING_DONE
] = UNIT_ACTIVE
,
50 [MOUNT_MOUNTED
] = UNIT_ACTIVE
,
51 [MOUNT_REMOUNTING
] = UNIT_RELOADING
,
52 [MOUNT_UNMOUNTING
] = UNIT_DEACTIVATING
,
53 [MOUNT_MOUNTING_SIGTERM
] = UNIT_DEACTIVATING
,
54 [MOUNT_MOUNTING_SIGKILL
] = UNIT_DEACTIVATING
,
55 [MOUNT_REMOUNTING_SIGTERM
] = UNIT_RELOADING
,
56 [MOUNT_REMOUNTING_SIGKILL
] = UNIT_RELOADING
,
57 [MOUNT_UNMOUNTING_SIGTERM
] = UNIT_DEACTIVATING
,
58 [MOUNT_UNMOUNTING_SIGKILL
] = UNIT_DEACTIVATING
,
59 [MOUNT_FAILED
] = UNIT_FAILED
62 static void mount_init(Unit
*u
) {
66 assert(u
->load_state
== UNIT_STUB
);
68 m
->timeout_usec
= DEFAULT_TIMEOUT_USEC
;
69 m
->directory_mode
= 0755;
71 exec_context_init(&m
->exec_context
);
73 if (unit_has_name(u
, "-.mount")) {
74 /* Don't allow start/stop for root directory */
75 UNIT(m
)->refuse_manual_start
= true;
76 UNIT(m
)->refuse_manual_stop
= true;
78 /* The stdio/kmsg bridge socket is on /, in order to avoid a
79 * dep loop, don't use kmsg logging for -.mount */
80 m
->exec_context
.std_output
= u
->manager
->default_std_output
;
81 m
->exec_context
.std_error
= u
->manager
->default_std_error
;
84 kill_context_init(&m
->kill_context
);
86 /* We need to make sure that /bin/mount is always called in
87 * the same process group as us, so that the autofs kernel
88 * side doesn't send us another mount request while we are
89 * already trying to comply its last one. */
90 m
->exec_context
.same_pgrp
= true;
92 m
->timer_watch
.type
= WATCH_INVALID
;
94 m
->control_command_id
= _MOUNT_EXEC_COMMAND_INVALID
;
96 UNIT(m
)->ignore_on_isolate
= true;
99 static void mount_unwatch_control_pid(Mount
*m
) {
102 if (m
->control_pid
<= 0)
105 unit_unwatch_pid(UNIT(m
), m
->control_pid
);
109 static void mount_parameters_done(MountParameters
*p
) {
116 p
->what
= p
->options
= p
->fstype
= NULL
;
119 static void mount_done(Unit
*u
) {
127 mount_parameters_done(&m
->parameters_proc_self_mountinfo
);
128 mount_parameters_done(&m
->parameters_fragment
);
130 exec_context_done(&m
->exec_context
, manager_is_reloading_or_reexecuting(u
->manager
));
131 exec_command_done_array(m
->exec_command
, _MOUNT_EXEC_COMMAND_MAX
);
132 m
->control_command
= NULL
;
134 mount_unwatch_control_pid(m
);
136 unit_unwatch_timer(u
, &m
->timer_watch
);
139 static MountParameters
* get_mount_parameters_fragment(Mount
*m
) {
142 if (m
->from_fragment
)
143 return &m
->parameters_fragment
;
148 static MountParameters
* get_mount_parameters(Mount
*m
) {
151 if (m
->from_proc_self_mountinfo
)
152 return &m
->parameters_proc_self_mountinfo
;
154 return get_mount_parameters_fragment(m
);
157 static int mount_add_mount_links(Mount
*m
) {
164 pm
= get_mount_parameters_fragment(m
);
166 /* Adds in links to other mount points that might lie below or
167 * above us in the hierarchy */
169 LIST_FOREACH(units_by_type
, other
, UNIT(m
)->manager
->units_by_type
[UNIT_MOUNT
]) {
170 Mount
*n
= MOUNT(other
);
176 if (UNIT(n
)->load_state
!= UNIT_LOADED
)
179 pn
= get_mount_parameters_fragment(n
);
181 if (path_startswith(m
->where
, n
->where
)) {
183 if ((r
= unit_add_dependency(UNIT(m
), UNIT_AFTER
, UNIT(n
), true)) < 0)
187 if ((r
= unit_add_dependency(UNIT(m
), UNIT_REQUIRES
, UNIT(n
), true)) < 0)
190 } else if (path_startswith(n
->where
, m
->where
)) {
192 if ((r
= unit_add_dependency(UNIT(n
), UNIT_AFTER
, UNIT(m
), true)) < 0)
196 if ((r
= unit_add_dependency(UNIT(n
), UNIT_REQUIRES
, UNIT(m
), true)) < 0)
199 } else if (pm
&& pm
->what
&& path_startswith(pm
->what
, n
->where
)) {
201 if ((r
= unit_add_dependency(UNIT(m
), UNIT_AFTER
, UNIT(n
), true)) < 0)
204 if ((r
= unit_add_dependency(UNIT(m
), UNIT_REQUIRES
, UNIT(n
), true)) < 0)
207 } else if (pn
&& pn
->what
&& path_startswith(pn
->what
, m
->where
)) {
209 if ((r
= unit_add_dependency(UNIT(n
), UNIT_AFTER
, UNIT(m
), true)) < 0)
212 if ((r
= unit_add_dependency(UNIT(n
), UNIT_REQUIRES
, UNIT(m
), true)) < 0)
220 static int mount_add_swap_links(Mount
*m
) {
226 LIST_FOREACH(units_by_type
, other
, UNIT(m
)->manager
->units_by_type
[UNIT_SWAP
]) {
227 r
= swap_add_one_mount_link(SWAP(other
), m
);
235 static int mount_add_path_links(Mount
*m
) {
241 LIST_FOREACH(units_by_type
, other
, UNIT(m
)->manager
->units_by_type
[UNIT_PATH
]) {
242 r
= path_add_one_mount_link(PATH(other
), m
);
250 static int mount_add_automount_links(Mount
*m
) {
256 LIST_FOREACH(units_by_type
, other
, UNIT(m
)->manager
->units_by_type
[UNIT_AUTOMOUNT
]) {
257 r
= automount_add_one_mount_link(AUTOMOUNT(other
), m
);
265 static int mount_add_socket_links(Mount
*m
) {
271 LIST_FOREACH(units_by_type
, other
, UNIT(m
)->manager
->units_by_type
[UNIT_SOCKET
]) {
272 r
= socket_add_one_mount_link(SOCKET(other
), m
);
280 static int mount_add_requires_mounts_links(Mount
*m
) {
286 LIST_FOREACH(has_requires_mounts_for
, other
, UNIT(m
)->manager
->has_requires_mounts_for
) {
287 r
= unit_add_one_mount_link(other
, m
);
295 static char* mount_test_option(const char *haystack
, const char *needle
) {
300 /* Like glibc's hasmntopt(), but works on a string, not a
307 me
.mnt_opts
= (char*) haystack
;
309 return hasmntopt(&me
, needle
);
312 static bool mount_is_network(MountParameters
*p
) {
315 if (mount_test_option(p
->options
, "_netdev"))
318 if (p
->fstype
&& fstype_is_network(p
->fstype
))
324 static bool mount_is_bind(MountParameters
*p
) {
327 if (mount_test_option(p
->options
, "bind"))
330 if (p
->fstype
&& streq(p
->fstype
, "bind"))
333 if (mount_test_option(p
->options
, "rbind"))
336 if (p
->fstype
&& streq(p
->fstype
, "rbind"))
342 static bool needs_quota(MountParameters
*p
) {
345 if (mount_is_network(p
))
348 if (mount_is_bind(p
))
351 return mount_test_option(p
->options
, "usrquota") ||
352 mount_test_option(p
->options
, "grpquota") ||
353 mount_test_option(p
->options
, "quota") ||
354 mount_test_option(p
->options
, "usrjquota") ||
355 mount_test_option(p
->options
, "grpjquota");
358 static int mount_add_device_links(Mount
*m
) {
364 p
= get_mount_parameters_fragment(m
);
371 if (mount_is_bind(p
))
374 if (!is_device_path(p
->what
))
377 if (path_equal(m
->where
, "/"))
380 r
= unit_add_node_link(UNIT(m
), p
->what
, false);
385 UNIT(m
)->manager
->running_as
== SYSTEMD_SYSTEM
) {
388 /* Let's add in the fsck service */
390 /* aka SPECIAL_FSCK_SERVICE */
391 name
= unit_name_from_path_instance("systemd-fsck", p
->what
, ".service");
395 r
= manager_load_unit_prepare(UNIT(m
)->manager
, name
, NULL
, NULL
, &fsck
);
397 log_warning_unit(name
,
398 "Failed to prepare unit %s: %s", name
, strerror(-r
));
404 SERVICE(fsck
)->fsck_passno
= p
->passno
;
406 r
= unit_add_two_dependencies(UNIT(m
), UNIT_AFTER
, UNIT_REQUIRES
, fsck
, true);
414 static int mount_add_quota_links(Mount
*m
) {
420 if (UNIT(m
)->manager
->running_as
!= SYSTEMD_SYSTEM
)
423 p
= get_mount_parameters_fragment(m
);
430 r
= unit_add_two_dependencies_by_name(UNIT(m
), UNIT_BEFORE
, UNIT_WANTS
, SPECIAL_QUOTACHECK_SERVICE
, NULL
, true);
434 r
= unit_add_two_dependencies_by_name(UNIT(m
), UNIT_BEFORE
, UNIT_WANTS
, SPECIAL_QUOTAON_SERVICE
, NULL
, true);
441 static int mount_add_default_dependencies(Mount
*m
) {
442 const char *after
, *after2
, *online
;
448 if (UNIT(m
)->manager
->running_as
!= SYSTEMD_SYSTEM
)
451 p
= get_mount_parameters(m
);
456 if (path_equal(m
->where
, "/"))
459 if (mount_is_network(p
)) {
460 after
= SPECIAL_REMOTE_FS_PRE_TARGET
;
461 after2
= SPECIAL_NETWORK_TARGET
;
462 online
= SPECIAL_NETWORK_ONLINE_TARGET
;
464 after
= SPECIAL_LOCAL_FS_PRE_TARGET
;
469 r
= unit_add_dependency_by_name(UNIT(m
), UNIT_AFTER
, after
, NULL
, true);
474 r
= unit_add_dependency_by_name(UNIT(m
), UNIT_AFTER
, after2
, NULL
, true);
480 r
= unit_add_two_dependencies_by_name(UNIT(m
), UNIT_WANTS
, UNIT_AFTER
, online
, NULL
, true);
485 r
= unit_add_two_dependencies_by_name(UNIT(m
), UNIT_BEFORE
, UNIT_CONFLICTS
, SPECIAL_UMOUNT_TARGET
, NULL
, true);
492 static int mount_fix_timeouts(Mount
*m
) {
494 const char *timeout
= NULL
;
503 p
= get_mount_parameters_fragment(m
);
507 /* Allow configuration how long we wait for a device that
508 * backs a mount point to show up. This is useful to support
509 * endless device timeouts for devices that show up only after
510 * user input, like crypto devices. */
512 if ((timeout
= mount_test_option(p
->options
, "comment=systemd.device-timeout")))
514 else if ((timeout
= mount_test_option(p
->options
, "x-systemd.device-timeout")))
519 t
= strndup(timeout
, strcspn(timeout
, ",;" WHITESPACE
));
523 r
= parse_usec(t
, &u
);
527 log_warning_unit(UNIT(m
)->id
,
528 "Failed to parse timeout for %s, ignoring: %s",
533 SET_FOREACH(other
, UNIT(m
)->dependencies
[UNIT_AFTER
], i
) {
534 if (other
->type
!= UNIT_DEVICE
)
537 other
->job_timeout
= u
;
543 static int mount_verify(Mount
*m
) {
548 if (UNIT(m
)->load_state
!= UNIT_LOADED
)
551 if (!m
->from_fragment
&& !m
->from_proc_self_mountinfo
)
554 if (!(e
= unit_name_from_path(m
->where
, ".mount")))
557 b
= unit_has_name(UNIT(m
), e
);
561 log_error_unit(UNIT(m
)->id
,
562 "%s's Where setting doesn't match unit name. Refusing.",
567 if (mount_point_is_api(m
->where
) || mount_point_ignore(m
->where
)) {
568 log_error_unit(UNIT(m
)->id
,
569 "Cannot create mount unit for API file system %s. Refusing.",
574 if (UNIT(m
)->fragment_path
&& !m
->parameters_fragment
.what
) {
575 log_error_unit(UNIT(m
)->id
,
576 "%s's What setting is missing. Refusing.", UNIT(m
)->id
);
580 if (m
->exec_context
.pam_name
&& m
->kill_context
.kill_mode
!= KILL_CONTROL_GROUP
) {
581 log_error_unit(UNIT(m
)->id
,
582 "%s has PAM enabled. Kill mode must be set to control-group'. Refusing.",
590 static int mount_add_extras(Mount
*m
) {
594 if (UNIT(m
)->fragment_path
)
595 m
->from_fragment
= true;
598 m
->where
= unit_name_to_path(u
->id
);
603 path_kill_slashes(m
->where
);
605 r
= unit_add_exec_dependencies(u
, &m
->exec_context
);
609 if (!UNIT(m
)->description
) {
610 r
= unit_set_description(u
, m
->where
);
615 r
= mount_add_device_links(m
);
619 r
= mount_add_mount_links(m
);
623 r
= mount_add_socket_links(m
);
627 r
= mount_add_swap_links(m
);
631 r
= mount_add_path_links(m
);
635 r
= mount_add_requires_mounts_links(m
);
639 r
= mount_add_automount_links(m
);
643 r
= mount_add_quota_links(m
);
647 if (UNIT(m
)->default_dependencies
) {
648 r
= mount_add_default_dependencies(m
);
653 r
= unit_add_default_cgroups(u
);
657 r
= mount_fix_timeouts(m
);
664 static int mount_load(Unit
*u
) {
669 assert(u
->load_state
== UNIT_STUB
);
671 if (m
->from_proc_self_mountinfo
)
672 r
= unit_load_fragment_and_dropin_optional(u
);
674 r
= unit_load_fragment_and_dropin(u
);
679 /* This is a new unit? Then let's add in some extras */
680 if (u
->load_state
== UNIT_LOADED
) {
681 r
= mount_add_extras(m
);
685 r
= unit_exec_context_defaults(u
, &m
->exec_context
);
690 return mount_verify(m
);
693 static int mount_notify_automount(Mount
*m
, int status
) {
700 SET_FOREACH(p
, UNIT(m
)->dependencies
[UNIT_TRIGGERED_BY
], i
)
701 if (p
->type
== UNIT_AUTOMOUNT
) {
702 r
= automount_send_ready(AUTOMOUNT(p
), status
);
710 static void mount_set_state(Mount
*m
, MountState state
) {
711 MountState old_state
;
714 old_state
= m
->state
;
717 if (state
!= MOUNT_MOUNTING
&&
718 state
!= MOUNT_MOUNTING_DONE
&&
719 state
!= MOUNT_REMOUNTING
&&
720 state
!= MOUNT_UNMOUNTING
&&
721 state
!= MOUNT_MOUNTING_SIGTERM
&&
722 state
!= MOUNT_MOUNTING_SIGKILL
&&
723 state
!= MOUNT_UNMOUNTING_SIGTERM
&&
724 state
!= MOUNT_UNMOUNTING_SIGKILL
&&
725 state
!= MOUNT_REMOUNTING_SIGTERM
&&
726 state
!= MOUNT_REMOUNTING_SIGKILL
) {
727 unit_unwatch_timer(UNIT(m
), &m
->timer_watch
);
728 mount_unwatch_control_pid(m
);
729 m
->control_command
= NULL
;
730 m
->control_command_id
= _MOUNT_EXEC_COMMAND_INVALID
;
733 if (state
== MOUNT_MOUNTED
||
734 state
== MOUNT_REMOUNTING
)
735 mount_notify_automount(m
, 0);
736 else if (state
== MOUNT_DEAD
||
737 state
== MOUNT_UNMOUNTING
||
738 state
== MOUNT_MOUNTING_SIGTERM
||
739 state
== MOUNT_MOUNTING_SIGKILL
||
740 state
== MOUNT_REMOUNTING_SIGTERM
||
741 state
== MOUNT_REMOUNTING_SIGKILL
||
742 state
== MOUNT_UNMOUNTING_SIGTERM
||
743 state
== MOUNT_UNMOUNTING_SIGKILL
||
744 state
== MOUNT_FAILED
) {
745 if (state
!= old_state
)
746 mount_notify_automount(m
, -ENODEV
);
749 if (state
!= old_state
)
750 log_debug_unit(UNIT(m
)->id
,
751 "%s changed %s -> %s",
753 mount_state_to_string(old_state
),
754 mount_state_to_string(state
));
756 unit_notify(UNIT(m
), state_translation_table
[old_state
], state_translation_table
[state
], m
->reload_result
== MOUNT_SUCCESS
);
757 m
->reload_result
= MOUNT_SUCCESS
;
760 static int mount_coldplug(Unit
*u
) {
762 MountState new_state
= MOUNT_DEAD
;
766 assert(m
->state
== MOUNT_DEAD
);
768 if (m
->deserialized_state
!= m
->state
)
769 new_state
= m
->deserialized_state
;
770 else if (m
->from_proc_self_mountinfo
)
771 new_state
= MOUNT_MOUNTED
;
773 if (new_state
!= m
->state
) {
775 if (new_state
== MOUNT_MOUNTING
||
776 new_state
== MOUNT_MOUNTING_DONE
||
777 new_state
== MOUNT_REMOUNTING
||
778 new_state
== MOUNT_UNMOUNTING
||
779 new_state
== MOUNT_MOUNTING_SIGTERM
||
780 new_state
== MOUNT_MOUNTING_SIGKILL
||
781 new_state
== MOUNT_UNMOUNTING_SIGTERM
||
782 new_state
== MOUNT_UNMOUNTING_SIGKILL
||
783 new_state
== MOUNT_REMOUNTING_SIGTERM
||
784 new_state
== MOUNT_REMOUNTING_SIGKILL
) {
786 if (m
->control_pid
<= 0)
789 r
= unit_watch_pid(UNIT(m
), m
->control_pid
);
793 r
= unit_watch_timer(UNIT(m
), CLOCK_MONOTONIC
, true, m
->timeout_usec
, &m
->timer_watch
);
798 mount_set_state(m
, new_state
);
804 static void mount_dump(Unit
*u
, FILE *f
, const char *prefix
) {
811 p
= get_mount_parameters(m
);
814 "%sMount State: %s\n"
818 "%sFile System Type: %s\n"
820 "%sFrom /proc/self/mountinfo: %s\n"
821 "%sFrom fragment: %s\n"
822 "%sDirectoryMode: %04o\n",
823 prefix
, mount_state_to_string(m
->state
),
824 prefix
, mount_result_to_string(m
->result
),
826 prefix
, strna(p
->what
),
827 prefix
, strna(p
->fstype
),
828 prefix
, strna(p
->options
),
829 prefix
, yes_no(m
->from_proc_self_mountinfo
),
830 prefix
, yes_no(m
->from_fragment
),
831 prefix
, m
->directory_mode
);
833 if (m
->control_pid
> 0)
835 "%sControl PID: %lu\n",
836 prefix
, (unsigned long) m
->control_pid
);
838 exec_context_dump(&m
->exec_context
, f
, prefix
);
839 kill_context_dump(&m
->kill_context
, f
, prefix
);
842 static int mount_spawn(Mount
*m
, ExecCommand
*c
, pid_t
*_pid
) {
850 r
= unit_watch_timer(UNIT(m
), CLOCK_MONOTONIC
, true, m
->timeout_usec
, &m
->timer_watch
);
854 if ((r
= exec_spawn(c
,
858 UNIT(m
)->manager
->environment
,
862 UNIT(m
)->manager
->confirm_spawn
,
863 UNIT(m
)->cgroup_bondings
,
864 UNIT(m
)->cgroup_attributes
,
871 if ((r
= unit_watch_pid(UNIT(m
), pid
)) < 0)
872 /* FIXME: we need to do something here */
880 unit_unwatch_timer(UNIT(m
), &m
->timer_watch
);
885 static void mount_enter_dead(Mount
*m
, MountResult f
) {
888 if (f
!= MOUNT_SUCCESS
)
891 exec_context_tmp_dirs_done(&m
->exec_context
);
892 mount_set_state(m
, m
->result
!= MOUNT_SUCCESS
? MOUNT_FAILED
: MOUNT_DEAD
);
895 static void mount_enter_mounted(Mount
*m
, MountResult f
) {
898 if (f
!= MOUNT_SUCCESS
)
901 mount_set_state(m
, MOUNT_MOUNTED
);
904 static void mount_enter_signal(Mount
*m
, MountState state
, MountResult f
) {
909 if (f
!= MOUNT_SUCCESS
)
912 r
= unit_kill_context(
915 state
!= MOUNT_MOUNTING_SIGTERM
&& state
!= MOUNT_UNMOUNTING_SIGTERM
&& state
!= MOUNT_REMOUNTING_SIGTERM
,
923 r
= unit_watch_timer(UNIT(m
), CLOCK_MONOTONIC
, true, m
->timeout_usec
, &m
->timer_watch
);
927 mount_set_state(m
, state
);
928 } else if (state
== MOUNT_REMOUNTING_SIGTERM
|| state
== MOUNT_REMOUNTING_SIGKILL
)
929 mount_enter_mounted(m
, MOUNT_SUCCESS
);
931 mount_enter_dead(m
, MOUNT_SUCCESS
);
936 log_warning_unit(UNIT(m
)->id
,
937 "%s failed to kill processes: %s", UNIT(m
)->id
, strerror(-r
));
939 if (state
== MOUNT_REMOUNTING_SIGTERM
|| state
== MOUNT_REMOUNTING_SIGKILL
)
940 mount_enter_mounted(m
, MOUNT_FAILURE_RESOURCES
);
942 mount_enter_dead(m
, MOUNT_FAILURE_RESOURCES
);
945 void warn_if_dir_nonempty(const char *unit
, const char* where
) {
949 if (dir_is_empty(where
) > 0)
952 log_struct_unit(LOG_NOTICE
,
954 "MESSAGE=%s: Directory %s to mount over is not empty, mounting anyway.",
957 MESSAGE_ID(SD_MESSAGE_OVERMOUNTING
),
961 static void mount_enter_unmounting(Mount
*m
) {
966 m
->control_command_id
= MOUNT_EXEC_UNMOUNT
;
967 m
->control_command
= m
->exec_command
+ MOUNT_EXEC_UNMOUNT
;
969 if ((r
= exec_command_set(
976 mount_unwatch_control_pid(m
);
978 if ((r
= mount_spawn(m
, m
->control_command
, &m
->control_pid
)) < 0)
981 mount_set_state(m
, MOUNT_UNMOUNTING
);
986 log_warning_unit(UNIT(m
)->id
,
987 "%s failed to run 'umount' task: %s",
988 UNIT(m
)->id
, strerror(-r
));
989 mount_enter_mounted(m
, MOUNT_FAILURE_RESOURCES
);
992 static void mount_enter_mounting(Mount
*m
) {
998 m
->control_command_id
= MOUNT_EXEC_MOUNT
;
999 m
->control_command
= m
->exec_command
+ MOUNT_EXEC_MOUNT
;
1001 mkdir_p_label(m
->where
, m
->directory_mode
);
1003 warn_if_dir_nonempty(m
->meta
.id
, m
->where
);
1005 /* Create the source directory for bind-mounts if needed */
1006 p
= get_mount_parameters_fragment(m
);
1007 if (p
&& mount_is_bind(p
))
1008 mkdir_p_label(p
->what
, m
->directory_mode
);
1010 if (m
->from_fragment
)
1011 r
= exec_command_set(
1014 m
->parameters_fragment
.what
,
1016 "-t", m
->parameters_fragment
.fstype
? m
->parameters_fragment
.fstype
: "auto",
1017 m
->parameters_fragment
.options
? "-o" : NULL
, m
->parameters_fragment
.options
,
1025 mount_unwatch_control_pid(m
);
1027 r
= mount_spawn(m
, m
->control_command
, &m
->control_pid
);
1031 mount_set_state(m
, MOUNT_MOUNTING
);
1036 log_warning_unit(UNIT(m
)->id
,
1037 "%s failed to run 'mount' task: %s",
1038 UNIT(m
)->id
, strerror(-r
));
1039 mount_enter_dead(m
, MOUNT_FAILURE_RESOURCES
);
1042 static void mount_enter_mounting_done(Mount
*m
) {
1045 mount_set_state(m
, MOUNT_MOUNTING_DONE
);
1048 static void mount_enter_remounting(Mount
*m
) {
1053 m
->control_command_id
= MOUNT_EXEC_REMOUNT
;
1054 m
->control_command
= m
->exec_command
+ MOUNT_EXEC_REMOUNT
;
1056 if (m
->from_fragment
) {
1060 if (m
->parameters_fragment
.options
) {
1061 if (!(buf
= strappend("remount,", m
->parameters_fragment
.options
))) {
1070 r
= exec_command_set(
1073 m
->parameters_fragment
.what
,
1075 "-t", m
->parameters_fragment
.fstype
? m
->parameters_fragment
.fstype
: "auto",
1086 mount_unwatch_control_pid(m
);
1088 if ((r
= mount_spawn(m
, m
->control_command
, &m
->control_pid
)) < 0)
1091 mount_set_state(m
, MOUNT_REMOUNTING
);
1096 log_warning_unit(UNIT(m
)->id
,
1097 "%s failed to run 'remount' task: %s",
1098 UNIT(m
)->id
, strerror(-r
));
1099 m
->reload_result
= MOUNT_FAILURE_RESOURCES
;
1100 mount_enter_mounted(m
, MOUNT_SUCCESS
);
1103 static int mount_start(Unit
*u
) {
1104 Mount
*m
= MOUNT(u
);
1108 /* We cannot fulfill this request right now, try again later
1110 if (m
->state
== MOUNT_UNMOUNTING
||
1111 m
->state
== MOUNT_UNMOUNTING_SIGTERM
||
1112 m
->state
== MOUNT_UNMOUNTING_SIGKILL
||
1113 m
->state
== MOUNT_MOUNTING_SIGTERM
||
1114 m
->state
== MOUNT_MOUNTING_SIGKILL
)
1117 /* Already on it! */
1118 if (m
->state
== MOUNT_MOUNTING
)
1121 assert(m
->state
== MOUNT_DEAD
|| m
->state
== MOUNT_FAILED
);
1123 m
->result
= MOUNT_SUCCESS
;
1124 m
->reload_result
= MOUNT_SUCCESS
;
1126 mount_enter_mounting(m
);
1130 static int mount_stop(Unit
*u
) {
1131 Mount
*m
= MOUNT(u
);
1136 if (m
->state
== MOUNT_UNMOUNTING
||
1137 m
->state
== MOUNT_UNMOUNTING_SIGKILL
||
1138 m
->state
== MOUNT_UNMOUNTING_SIGTERM
||
1139 m
->state
== MOUNT_MOUNTING_SIGTERM
||
1140 m
->state
== MOUNT_MOUNTING_SIGKILL
)
1143 assert(m
->state
== MOUNT_MOUNTING
||
1144 m
->state
== MOUNT_MOUNTING_DONE
||
1145 m
->state
== MOUNT_MOUNTED
||
1146 m
->state
== MOUNT_REMOUNTING
||
1147 m
->state
== MOUNT_REMOUNTING_SIGTERM
||
1148 m
->state
== MOUNT_REMOUNTING_SIGKILL
);
1150 mount_enter_unmounting(m
);
1154 static int mount_reload(Unit
*u
) {
1155 Mount
*m
= MOUNT(u
);
1159 if (m
->state
== MOUNT_MOUNTING_DONE
)
1162 assert(m
->state
== MOUNT_MOUNTED
);
1164 mount_enter_remounting(m
);
1168 static int mount_serialize(Unit
*u
, FILE *f
, FDSet
*fds
) {
1169 Mount
*m
= MOUNT(u
);
1175 unit_serialize_item(u
, f
, "state", mount_state_to_string(m
->state
));
1176 unit_serialize_item(u
, f
, "result", mount_result_to_string(m
->result
));
1177 unit_serialize_item(u
, f
, "reload-result", mount_result_to_string(m
->reload_result
));
1179 if (m
->control_pid
> 0)
1180 unit_serialize_item_format(u
, f
, "control-pid", "%lu", (unsigned long) m
->control_pid
);
1182 if (m
->control_command_id
>= 0)
1183 unit_serialize_item(u
, f
, "control-command", mount_exec_command_to_string(m
->control_command_id
));
1185 exec_context_serialize(&m
->exec_context
, UNIT(m
), f
);
1190 static int mount_deserialize_item(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
1191 Mount
*m
= MOUNT(u
);
1198 if (streq(key
, "state")) {
1201 if ((state
= mount_state_from_string(value
)) < 0)
1202 log_debug_unit(u
->id
, "Failed to parse state value %s", value
);
1204 m
->deserialized_state
= state
;
1205 } else if (streq(key
, "result")) {
1208 f
= mount_result_from_string(value
);
1210 log_debug_unit(UNIT(m
)->id
,
1211 "Failed to parse result value %s", value
);
1212 else if (f
!= MOUNT_SUCCESS
)
1215 } else if (streq(key
, "reload-result")) {
1218 f
= mount_result_from_string(value
);
1220 log_debug_unit(UNIT(m
)->id
,
1221 "Failed to parse reload result value %s", value
);
1222 else if (f
!= MOUNT_SUCCESS
)
1223 m
->reload_result
= f
;
1225 } else if (streq(key
, "control-pid")) {
1228 if (parse_pid(value
, &pid
) < 0)
1229 log_debug_unit(UNIT(m
)->id
,
1230 "Failed to parse control-pid value %s", value
);
1232 m
->control_pid
= pid
;
1233 } else if (streq(key
, "control-command")) {
1234 MountExecCommand id
;
1236 if ((id
= mount_exec_command_from_string(value
)) < 0)
1237 log_debug_unit(UNIT(m
)->id
,
1238 "Failed to parse exec-command value %s", value
);
1240 m
->control_command_id
= id
;
1241 m
->control_command
= m
->exec_command
+ id
;
1243 } else if (streq(key
, "tmp-dir")) {
1250 m
->exec_context
.tmp_dir
= t
;
1251 } else if (streq(key
, "var-tmp-dir")) {
1258 m
->exec_context
.var_tmp_dir
= t
;
1260 log_debug_unit(UNIT(m
)->id
,
1261 "Unknown serialization key '%s'", key
);
1266 static UnitActiveState
mount_active_state(Unit
*u
) {
1269 return state_translation_table
[MOUNT(u
)->state
];
1272 static const char *mount_sub_state_to_string(Unit
*u
) {
1275 return mount_state_to_string(MOUNT(u
)->state
);
1278 static bool mount_check_gc(Unit
*u
) {
1279 Mount
*m
= MOUNT(u
);
1283 return m
->from_proc_self_mountinfo
;
1286 static void mount_sigchld_event(Unit
*u
, pid_t pid
, int code
, int status
) {
1287 Mount
*m
= MOUNT(u
);
1293 if (pid
!= m
->control_pid
)
1298 if (is_clean_exit(code
, status
, NULL
))
1300 else if (code
== CLD_EXITED
)
1301 f
= MOUNT_FAILURE_EXIT_CODE
;
1302 else if (code
== CLD_KILLED
)
1303 f
= MOUNT_FAILURE_SIGNAL
;
1304 else if (code
== CLD_DUMPED
)
1305 f
= MOUNT_FAILURE_CORE_DUMP
;
1307 assert_not_reached("Unknown code");
1309 if (f
!= MOUNT_SUCCESS
)
1312 if (m
->control_command
) {
1313 exec_status_exit(&m
->control_command
->exec_status
, &m
->exec_context
, pid
, code
, status
);
1315 m
->control_command
= NULL
;
1316 m
->control_command_id
= _MOUNT_EXEC_COMMAND_INVALID
;
1319 log_full_unit(f
== MOUNT_SUCCESS
? LOG_DEBUG
: LOG_NOTICE
, u
->id
,
1320 "%s mount process exited, code=%s status=%i",
1321 u
->id
, sigchld_code_to_string(code
), status
);
1323 /* Note that mount(8) returning and the kernel sending us a
1324 * mount table change event might happen out-of-order. If an
1325 * operation succeed we assume the kernel will follow soon too
1326 * and already change into the resulting state. If it fails
1327 * we check if the kernel still knows about the mount. and
1328 * change state accordingly. */
1332 case MOUNT_MOUNTING
:
1333 case MOUNT_MOUNTING_DONE
:
1334 case MOUNT_MOUNTING_SIGKILL
:
1335 case MOUNT_MOUNTING_SIGTERM
:
1337 if (f
== MOUNT_SUCCESS
)
1338 mount_enter_mounted(m
, f
);
1339 else if (m
->from_proc_self_mountinfo
)
1340 mount_enter_mounted(m
, f
);
1342 mount_enter_dead(m
, f
);
1345 case MOUNT_REMOUNTING
:
1346 case MOUNT_REMOUNTING_SIGKILL
:
1347 case MOUNT_REMOUNTING_SIGTERM
:
1349 m
->reload_result
= f
;
1350 if (m
->from_proc_self_mountinfo
)
1351 mount_enter_mounted(m
, MOUNT_SUCCESS
);
1353 mount_enter_dead(m
, MOUNT_SUCCESS
);
1357 case MOUNT_UNMOUNTING
:
1358 case MOUNT_UNMOUNTING_SIGKILL
:
1359 case MOUNT_UNMOUNTING_SIGTERM
:
1361 if (f
== MOUNT_SUCCESS
)
1362 mount_enter_dead(m
, f
);
1363 else if (m
->from_proc_self_mountinfo
)
1364 mount_enter_mounted(m
, f
);
1366 mount_enter_dead(m
, f
);
1370 assert_not_reached("Uh, control process died at wrong time.");
1373 /* Notify clients about changed exit status */
1374 unit_add_to_dbus_queue(u
);
1377 static void mount_timer_event(Unit
*u
, uint64_t elapsed
, Watch
*w
) {
1378 Mount
*m
= MOUNT(u
);
1381 assert(elapsed
== 1);
1382 assert(w
== &m
->timer_watch
);
1386 case MOUNT_MOUNTING
:
1387 case MOUNT_MOUNTING_DONE
:
1388 log_warning_unit(u
->id
,
1389 "%s mounting timed out. Stopping.", u
->id
);
1390 mount_enter_signal(m
, MOUNT_MOUNTING_SIGTERM
, MOUNT_FAILURE_TIMEOUT
);
1393 case MOUNT_REMOUNTING
:
1394 log_warning_unit(u
->id
,
1395 "%s remounting timed out. Stopping.", u
->id
);
1396 m
->reload_result
= MOUNT_FAILURE_TIMEOUT
;
1397 mount_enter_mounted(m
, MOUNT_SUCCESS
);
1400 case MOUNT_UNMOUNTING
:
1401 log_warning_unit(u
->id
,
1402 "%s unmounting timed out. Stopping.", u
->id
);
1403 mount_enter_signal(m
, MOUNT_UNMOUNTING_SIGTERM
, MOUNT_FAILURE_TIMEOUT
);
1406 case MOUNT_MOUNTING_SIGTERM
:
1407 if (m
->kill_context
.send_sigkill
) {
1408 log_warning_unit(u
->id
,
1409 "%s mounting timed out. Killing.", u
->id
);
1410 mount_enter_signal(m
, MOUNT_MOUNTING_SIGKILL
, MOUNT_FAILURE_TIMEOUT
);
1412 log_warning_unit(u
->id
,
1413 "%s mounting timed out. Skipping SIGKILL. Ignoring.",
1416 if (m
->from_proc_self_mountinfo
)
1417 mount_enter_mounted(m
, MOUNT_FAILURE_TIMEOUT
);
1419 mount_enter_dead(m
, MOUNT_FAILURE_TIMEOUT
);
1423 case MOUNT_REMOUNTING_SIGTERM
:
1424 if (m
->kill_context
.send_sigkill
) {
1425 log_warning_unit(u
->id
,
1426 "%s remounting timed out. Killing.", u
->id
);
1427 mount_enter_signal(m
, MOUNT_REMOUNTING_SIGKILL
, MOUNT_FAILURE_TIMEOUT
);
1429 log_warning_unit(u
->id
,
1430 "%s remounting timed out. Skipping SIGKILL. Ignoring.",
1433 if (m
->from_proc_self_mountinfo
)
1434 mount_enter_mounted(m
, MOUNT_FAILURE_TIMEOUT
);
1436 mount_enter_dead(m
, MOUNT_FAILURE_TIMEOUT
);
1440 case MOUNT_UNMOUNTING_SIGTERM
:
1441 if (m
->kill_context
.send_sigkill
) {
1442 log_warning_unit(u
->id
,
1443 "%s unmounting timed out. Killing.", u
->id
);
1444 mount_enter_signal(m
, MOUNT_UNMOUNTING_SIGKILL
, MOUNT_FAILURE_TIMEOUT
);
1446 log_warning_unit(u
->id
,
1447 "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
1450 if (m
->from_proc_self_mountinfo
)
1451 mount_enter_mounted(m
, MOUNT_FAILURE_TIMEOUT
);
1453 mount_enter_dead(m
, MOUNT_FAILURE_TIMEOUT
);
1457 case MOUNT_MOUNTING_SIGKILL
:
1458 case MOUNT_REMOUNTING_SIGKILL
:
1459 case MOUNT_UNMOUNTING_SIGKILL
:
1460 log_warning_unit(u
->id
,
1461 "%s mount process still around after SIGKILL. Ignoring.",
1464 if (m
->from_proc_self_mountinfo
)
1465 mount_enter_mounted(m
, MOUNT_FAILURE_TIMEOUT
);
1467 mount_enter_dead(m
, MOUNT_FAILURE_TIMEOUT
);
1471 assert_not_reached("Timeout at wrong time.");
1475 static int mount_add_one(
1479 const char *options
,
1486 char *e
, *w
= NULL
, *o
= NULL
, *f
= NULL
;
1488 bool load_extras
= false;
1496 /* Ignore API mount points. They should never be referenced in
1497 * dependencies ever. */
1498 if (mount_point_is_api(where
) || mount_point_ignore(where
))
1501 if (streq(fstype
, "autofs"))
1504 /* probably some kind of swap, ignore */
1505 if (!is_path(where
))
1508 e
= unit_name_from_path(where
, ".mount");
1512 u
= manager_get_unit(m
, e
);
1516 u
= unit_new(m
, sizeof(Mount
));
1522 r
= unit_add_name(u
, e
);
1528 MOUNT(u
)->where
= strdup(where
);
1529 if (!MOUNT(u
)->where
) {
1534 u
->source_path
= strdup("/proc/self/mountinfo");
1535 if (!u
->source_path
) {
1540 r
= unit_add_dependency_by_name(u
, UNIT_BEFORE
, SPECIAL_LOCAL_FS_TARGET
, NULL
, true);
1544 r
= unit_add_dependency_by_name(u
, UNIT_CONFLICTS
, SPECIAL_UMOUNT_TARGET
, NULL
, true);
1548 unit_add_to_load_queue(u
);
1553 if (!MOUNT(u
)->where
) {
1554 MOUNT(u
)->where
= strdup(where
);
1555 if (!MOUNT(u
)->where
) {
1561 if (u
->load_state
== UNIT_ERROR
) {
1562 u
->load_state
= UNIT_LOADED
;
1565 /* Load in the extras later on, after we
1566 * finished initialization of the unit */
1571 if (!(w
= strdup(what
)) ||
1572 !(o
= strdup(options
)) ||
1573 !(f
= strdup(fstype
))) {
1578 p
= &MOUNT(u
)->parameters_proc_self_mountinfo
;
1580 MOUNT(u
)->is_mounted
= true;
1581 MOUNT(u
)->just_mounted
= !MOUNT(u
)->from_proc_self_mountinfo
;
1582 MOUNT(u
)->just_changed
= !streq_ptr(p
->options
, o
);
1585 MOUNT(u
)->from_proc_self_mountinfo
= true;
1599 r
= mount_add_extras(MOUNT(u
));
1604 unit_add_to_dbus_queue(u
);
1619 static int mount_load_proc_self_mountinfo(Manager
*m
, bool set_flags
) {
1622 char *device
, *path
, *options
, *options2
, *fstype
, *d
, *p
, *o
;
1626 rewind(m
->proc_self_mountinfo
);
1631 device
= path
= options
= options2
= fstype
= d
= p
= o
= NULL
;
1633 if ((k
= fscanf(m
->proc_self_mountinfo
,
1634 "%*s " /* (1) mount id */
1635 "%*s " /* (2) parent id */
1636 "%*s " /* (3) major:minor */
1637 "%*s " /* (4) root */
1638 "%ms " /* (5) mount point */
1639 "%ms" /* (6) mount options */
1640 "%*[^-]" /* (7) optional fields */
1641 "- " /* (8) separator */
1642 "%ms " /* (9) file system type */
1643 "%ms" /* (10) mount source */
1644 "%ms" /* (11) mount options 2 */
1645 "%*[^\n]", /* some rubbish at the end */
1655 log_warning("Failed to parse /proc/self/mountinfo:%u.", i
);
1659 o
= strjoin(options
, ",", options2
, NULL
);
1665 if (!(d
= cunescape(device
)) ||
1666 !(p
= cunescape(path
))) {
1671 if ((k
= mount_add_one(m
, d
, p
, o
, fstype
, 0, set_flags
)) < 0)
1698 static void mount_shutdown(Manager
*m
) {
1701 if (m
->proc_self_mountinfo
) {
1702 fclose(m
->proc_self_mountinfo
);
1703 m
->proc_self_mountinfo
= NULL
;
1707 static int mount_enumerate(Manager
*m
) {
1709 struct epoll_event ev
;
1712 if (!m
->proc_self_mountinfo
) {
1713 if (!(m
->proc_self_mountinfo
= fopen("/proc/self/mountinfo", "re")))
1716 m
->mount_watch
.type
= WATCH_MOUNT
;
1717 m
->mount_watch
.fd
= fileno(m
->proc_self_mountinfo
);
1720 ev
.events
= EPOLLPRI
;
1721 ev
.data
.ptr
= &m
->mount_watch
;
1723 if (epoll_ctl(m
->epoll_fd
, EPOLL_CTL_ADD
, m
->mount_watch
.fd
, &ev
) < 0)
1727 if ((r
= mount_load_proc_self_mountinfo(m
, false)) < 0)
1737 void mount_fd_event(Manager
*m
, int events
) {
1742 assert(events
& EPOLLPRI
);
1744 /* The manager calls this for every fd event happening on the
1745 * /proc/self/mountinfo file, which informs us about mounting
1748 r
= mount_load_proc_self_mountinfo(m
, true);
1750 log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-r
));
1752 /* Reset flags, just in case, for later calls */
1753 LIST_FOREACH(units_by_type
, u
, m
->units_by_type
[UNIT_MOUNT
]) {
1754 Mount
*mount
= MOUNT(u
);
1756 mount
->is_mounted
= mount
->just_mounted
= mount
->just_changed
= false;
1762 manager_dispatch_load_queue(m
);
1764 LIST_FOREACH(units_by_type
, u
, m
->units_by_type
[UNIT_MOUNT
]) {
1765 Mount
*mount
= MOUNT(u
);
1767 if (!mount
->is_mounted
) {
1768 /* This has just been unmounted. */
1770 mount
->from_proc_self_mountinfo
= false;
1772 switch (mount
->state
) {
1775 mount_enter_dead(mount
, MOUNT_SUCCESS
);
1779 mount_set_state(mount
, mount
->state
);
1784 } else if (mount
->just_mounted
|| mount
->just_changed
) {
1786 /* New or changed mount entry */
1788 switch (mount
->state
) {
1792 mount_enter_mounted(mount
, MOUNT_SUCCESS
);
1795 case MOUNT_MOUNTING
:
1796 mount_enter_mounting_done(mount
);
1800 /* Nothing really changed, but let's
1801 * issue an notification call
1802 * nonetheless, in case somebody is
1803 * waiting for this. (e.g. file system
1804 * ro/rw remounts.) */
1805 mount_set_state(mount
, mount
->state
);
1810 /* Reset the flags for later calls */
1811 mount
->is_mounted
= mount
->just_mounted
= mount
->just_changed
= false;
1815 static void mount_reset_failed(Unit
*u
) {
1816 Mount
*m
= MOUNT(u
);
1820 if (m
->state
== MOUNT_FAILED
)
1821 mount_set_state(m
, MOUNT_DEAD
);
1823 m
->result
= MOUNT_SUCCESS
;
1824 m
->reload_result
= MOUNT_SUCCESS
;
1827 static int mount_kill(Unit
*u
, KillWho who
, int signo
, DBusError
*error
) {
1828 return unit_kill_common(u
, who
, signo
, -1, MOUNT(u
)->control_pid
, error
);
1831 static const char* const mount_state_table
[_MOUNT_STATE_MAX
] = {
1832 [MOUNT_DEAD
] = "dead",
1833 [MOUNT_MOUNTING
] = "mounting",
1834 [MOUNT_MOUNTING_DONE
] = "mounting-done",
1835 [MOUNT_MOUNTED
] = "mounted",
1836 [MOUNT_REMOUNTING
] = "remounting",
1837 [MOUNT_UNMOUNTING
] = "unmounting",
1838 [MOUNT_MOUNTING_SIGTERM
] = "mounting-sigterm",
1839 [MOUNT_MOUNTING_SIGKILL
] = "mounting-sigkill",
1840 [MOUNT_REMOUNTING_SIGTERM
] = "remounting-sigterm",
1841 [MOUNT_REMOUNTING_SIGKILL
] = "remounting-sigkill",
1842 [MOUNT_UNMOUNTING_SIGTERM
] = "unmounting-sigterm",
1843 [MOUNT_UNMOUNTING_SIGKILL
] = "unmounting-sigkill",
1844 [MOUNT_FAILED
] = "failed"
1847 DEFINE_STRING_TABLE_LOOKUP(mount_state
, MountState
);
1849 static const char* const mount_exec_command_table
[_MOUNT_EXEC_COMMAND_MAX
] = {
1850 [MOUNT_EXEC_MOUNT
] = "ExecMount",
1851 [MOUNT_EXEC_UNMOUNT
] = "ExecUnmount",
1852 [MOUNT_EXEC_REMOUNT
] = "ExecRemount",
1855 DEFINE_STRING_TABLE_LOOKUP(mount_exec_command
, MountExecCommand
);
1857 static const char* const mount_result_table
[_MOUNT_RESULT_MAX
] = {
1858 [MOUNT_SUCCESS
] = "success",
1859 [MOUNT_FAILURE_RESOURCES
] = "resources",
1860 [MOUNT_FAILURE_TIMEOUT
] = "timeout",
1861 [MOUNT_FAILURE_EXIT_CODE
] = "exit-code",
1862 [MOUNT_FAILURE_SIGNAL
] = "signal",
1863 [MOUNT_FAILURE_CORE_DUMP
] = "core-dump"
1866 DEFINE_STRING_TABLE_LOOKUP(mount_result
, MountResult
);
1868 const UnitVTable mount_vtable
= {
1869 .object_size
= sizeof(Mount
),
1876 .exec_context_offset
= offsetof(Mount
, exec_context
),
1877 .exec_section
= "Mount",
1880 .no_instances
= true,
1886 .coldplug
= mount_coldplug
,
1890 .start
= mount_start
,
1892 .reload
= mount_reload
,
1896 .serialize
= mount_serialize
,
1897 .deserialize_item
= mount_deserialize_item
,
1899 .active_state
= mount_active_state
,
1900 .sub_state_to_string
= mount_sub_state_to_string
,
1902 .check_gc
= mount_check_gc
,
1904 .sigchld_event
= mount_sigchld_event
,
1905 .timer_event
= mount_timer_event
,
1907 .reset_failed
= mount_reset_failed
,
1909 .bus_interface
= "org.freedesktop.systemd1.Mount",
1910 .bus_message_handler
= bus_mount_message_handler
,
1911 .bus_invalidating_properties
= bus_mount_invalidating_properties
,
1913 .enumerate
= mount_enumerate
,
1914 .shutdown
= mount_shutdown
,
1916 .status_message_formats
= {
1917 .starting_stopping
= {
1918 [0] = "Mounting %s...",
1919 [1] = "Unmounting %s...",
1921 .finished_start_job
= {
1922 [JOB_DONE
] = "Mounted %s.",
1923 [JOB_FAILED
] = "Failed to mount %s.",
1924 [JOB_DEPENDENCY
] = "Dependency failed for %s.",
1925 [JOB_TIMEOUT
] = "Timed out mounting %s.",
1927 .finished_stop_job
= {
1928 [JOB_DONE
] = "Unmounted %s.",
1929 [JOB_FAILED
] = "Failed unmounting %s.",
1930 [JOB_TIMEOUT
] = "Timed out unmounting %s.",