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 char* mount_test_option(const char *haystack, const char *needle) {
63 struct mntent me = { .mnt_opts = (char*) haystack };
67 /* Like glibc's hasmntopt(), but works on a string, not a
73 return hasmntopt(&me, needle);
76 static bool mount_is_network(MountParameters *p) {
79 if (mount_test_option(p->options, "_netdev"))
82 if (p->fstype && fstype_is_network(p->fstype))
88 static bool mount_is_bind(MountParameters *p) {
91 if (mount_test_option(p->options, "bind"))
94 if (p->fstype && streq(p->fstype, "bind"))
97 if (mount_test_option(p->options, "rbind"))
100 if (p->fstype && streq(p->fstype, "rbind"))
106 static bool mount_is_auto(MountParameters *p) {
109 return !mount_test_option(p->options, "noauto");
112 static bool needs_quota(MountParameters *p) {
115 if (mount_is_network(p))
118 if (mount_is_bind(p))
121 return mount_test_option(p->options, "usrquota") ||
122 mount_test_option(p->options, "grpquota") ||
123 mount_test_option(p->options, "quota") ||
124 mount_test_option(p->options, "usrjquota") ||
125 mount_test_option(p->options, "grpjquota");
128 static void mount_init(Unit *u) {
132 assert(u->load_state == UNIT_STUB);
134 m->timeout_usec = DEFAULT_TIMEOUT_USEC;
135 m->directory_mode = 0755;
137 exec_context_init(&m->exec_context);
139 if (unit_has_name(u, "-.mount")) {
140 /* Don't allow start/stop for root directory */
141 UNIT(m)->refuse_manual_start = true;
142 UNIT(m)->refuse_manual_stop = true;
144 /* The stdio/kmsg bridge socket is on /, in order to avoid a
145 * dep loop, don't use kmsg logging for -.mount */
146 m->exec_context.std_output = u->manager->default_std_output;
147 m->exec_context.std_error = u->manager->default_std_error;
150 kill_context_init(&m->kill_context);
151 cgroup_context_init(&m->cgroup_context);
153 /* We need to make sure that /bin/mount is always called in
154 * the same process group as us, so that the autofs kernel
155 * side doesn't send us another mount request while we are
156 * already trying to comply its last one. */
157 m->exec_context.same_pgrp = true;
159 m->timer_watch.type = WATCH_INVALID;
161 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
163 UNIT(m)->ignore_on_isolate = true;
166 static void mount_unwatch_control_pid(Mount *m) {
169 if (m->control_pid <= 0)
172 unit_unwatch_pid(UNIT(m), m->control_pid);
176 static void mount_parameters_done(MountParameters *p) {
183 p->what = p->options = p->fstype = NULL;
186 static void mount_done(Unit *u) {
194 mount_parameters_done(&m->parameters_proc_self_mountinfo);
195 mount_parameters_done(&m->parameters_fragment);
197 cgroup_context_done(&m->cgroup_context);
198 exec_context_done(&m->exec_context, manager_is_reloading_or_reexecuting(u->manager));
199 exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
200 m->control_command = NULL;
202 mount_unwatch_control_pid(m);
204 unit_unwatch_timer(u, &m->timer_watch);
207 _pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
210 if (m->from_fragment)
211 return &m->parameters_fragment;
216 _pure_ static MountParameters* get_mount_parameters(Mount *m) {
219 if (m->from_proc_self_mountinfo)
220 return &m->parameters_proc_self_mountinfo;
222 return get_mount_parameters_fragment(m);
225 static int mount_add_mount_links(Mount *m) {
226 _cleanup_free_ char *parent = NULL;
235 if (!path_equal(m->where, "/")) {
236 /* Adds in links to other mount points that might lie further
237 * up in the hierarchy */
238 r = path_get_parent(m->where, &parent);
242 r = unit_require_mounts_for(UNIT(m), parent);
247 /* Adds in links to other mount points that might be needed
248 * for the source path (if this is a bind mount) to be
250 pm = get_mount_parameters_fragment(m);
251 if (pm && pm->what &&
252 path_is_absolute(pm->what) &&
253 !mount_is_network(pm)) {
255 r = unit_require_mounts_for(UNIT(m), pm->what);
260 /* Adds in links to other units that use this path or paths
261 * further down in the hierarchy */
262 s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
263 SET_FOREACH(other, s, i) {
265 if (other->load_state != UNIT_LOADED)
268 if (other == UNIT(m))
271 r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true);
275 if (UNIT(m)->fragment_path) {
276 /* If we have fragment configuration, then make this dependency required */
277 r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true);
286 static int mount_add_device_links(Mount *m) {
288 bool device_wants_mount = false;
293 p = get_mount_parameters_fragment(m);
300 if (mount_is_bind(p))
303 if (!is_device_path(p->what))
306 if (path_equal(m->where, "/"))
309 if (mount_is_auto(p) && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
310 device_wants_mount = true;
312 r = unit_add_node_link(UNIT(m), p->what, device_wants_mount);
319 static int mount_add_quota_links(Mount *m) {
325 if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
328 p = get_mount_parameters_fragment(m);
335 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true);
339 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true);
346 static bool should_umount(Mount *m) {
349 if (path_equal(m->where, "/") ||
350 path_equal(m->where, "/usr"))
353 p = get_mount_parameters(m);
354 if (p && mount_test_option(p->options, "x-initrd.mount") &&
361 static int mount_add_default_dependencies(Mount *m) {
362 const char *after, *after2, *online;
368 if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
371 p = get_mount_parameters(m);
376 if (path_equal(m->where, "/"))
379 if (mount_is_network(p)) {
380 after = SPECIAL_REMOTE_FS_PRE_TARGET;
381 after2 = SPECIAL_NETWORK_TARGET;
382 online = SPECIAL_NETWORK_ONLINE_TARGET;
384 after = SPECIAL_LOCAL_FS_PRE_TARGET;
389 r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
394 r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after2, NULL, true);
400 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, online, NULL, true);
405 if (should_umount(m)) {
406 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
414 static int mount_fix_timeouts(Mount *m) {
416 const char *timeout = NULL;
425 p = get_mount_parameters_fragment(m);
429 /* Allow configuration how long we wait for a device that
430 * backs a mount point to show up. This is useful to support
431 * endless device timeouts for devices that show up only after
432 * user input, like crypto devices. */
434 if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout")))
436 else if ((timeout = mount_test_option(p->options, "x-systemd.device-timeout")))
441 t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE));
445 r = parse_sec(t, &u);
449 log_warning_unit(UNIT(m)->id,
450 "Failed to parse timeout for %s, ignoring: %s",
455 SET_FOREACH(other, UNIT(m)->dependencies[UNIT_AFTER], i) {
456 if (other->type != UNIT_DEVICE)
459 other->job_timeout = u;
465 static int mount_verify(Mount *m) {
466 _cleanup_free_ char *e = NULL;
471 if (UNIT(m)->load_state != UNIT_LOADED)
474 if (!m->from_fragment && !m->from_proc_self_mountinfo)
477 e = unit_name_from_path(m->where, ".mount");
481 b = unit_has_name(UNIT(m), e);
483 log_error_unit(UNIT(m)->id,
484 "%s's Where setting doesn't match unit name. Refusing.",
489 if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
490 log_error_unit(UNIT(m)->id,
491 "Cannot create mount unit for API file system %s. Refusing.",
496 if (UNIT(m)->fragment_path && !m->parameters_fragment.what) {
497 log_error_unit(UNIT(m)->id,
498 "%s's What setting is missing. Refusing.", UNIT(m)->id);
502 if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) {
503 log_error_unit(UNIT(m)->id,
504 "%s has PAM enabled. Kill mode must be set to control-group'. Refusing.",
512 static int mount_add_extras(Mount *m) {
516 if (UNIT(m)->fragment_path)
517 m->from_fragment = true;
520 m->where = unit_name_to_path(u->id);
525 path_kill_slashes(m->where);
527 r = unit_add_exec_dependencies(u, &m->exec_context);
531 if (!UNIT(m)->description) {
532 r = unit_set_description(u, m->where);
537 r = mount_add_device_links(m);
541 r = mount_add_mount_links(m);
545 r = mount_add_quota_links(m);
549 if (UNIT(m)->default_dependencies) {
550 r = mount_add_default_dependencies(m);
555 r = unit_add_default_slice(u);
559 r = mount_fix_timeouts(m);
566 static int mount_load(Unit *u) {
571 assert(u->load_state == UNIT_STUB);
573 if (m->from_proc_self_mountinfo)
574 r = unit_load_fragment_and_dropin_optional(u);
576 r = unit_load_fragment_and_dropin(u);
581 /* This is a new unit? Then let's add in some extras */
582 if (u->load_state == UNIT_LOADED) {
583 r = mount_add_extras(m);
587 r = unit_exec_context_defaults(u, &m->exec_context);
592 return mount_verify(m);
595 static int mount_notify_automount(Mount *m, int status) {
602 SET_FOREACH(p, UNIT(m)->dependencies[UNIT_TRIGGERED_BY], i)
603 if (p->type == UNIT_AUTOMOUNT) {
604 r = automount_send_ready(AUTOMOUNT(p), status);
612 static void mount_set_state(Mount *m, MountState state) {
613 MountState old_state;
616 old_state = m->state;
619 if (state != MOUNT_MOUNTING &&
620 state != MOUNT_MOUNTING_DONE &&
621 state != MOUNT_REMOUNTING &&
622 state != MOUNT_UNMOUNTING &&
623 state != MOUNT_MOUNTING_SIGTERM &&
624 state != MOUNT_MOUNTING_SIGKILL &&
625 state != MOUNT_UNMOUNTING_SIGTERM &&
626 state != MOUNT_UNMOUNTING_SIGKILL &&
627 state != MOUNT_REMOUNTING_SIGTERM &&
628 state != MOUNT_REMOUNTING_SIGKILL) {
629 unit_unwatch_timer(UNIT(m), &m->timer_watch);
630 mount_unwatch_control_pid(m);
631 m->control_command = NULL;
632 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
635 if (state == MOUNT_MOUNTED ||
636 state == MOUNT_REMOUNTING)
637 mount_notify_automount(m, 0);
638 else if (state == MOUNT_DEAD ||
639 state == MOUNT_UNMOUNTING ||
640 state == MOUNT_MOUNTING_SIGTERM ||
641 state == MOUNT_MOUNTING_SIGKILL ||
642 state == MOUNT_REMOUNTING_SIGTERM ||
643 state == MOUNT_REMOUNTING_SIGKILL ||
644 state == MOUNT_UNMOUNTING_SIGTERM ||
645 state == MOUNT_UNMOUNTING_SIGKILL ||
646 state == MOUNT_FAILED) {
647 if (state != old_state)
648 mount_notify_automount(m, -ENODEV);
651 if (state != old_state)
652 log_debug_unit(UNIT(m)->id,
653 "%s changed %s -> %s",
655 mount_state_to_string(old_state),
656 mount_state_to_string(state));
658 unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
659 m->reload_result = MOUNT_SUCCESS;
662 static int mount_coldplug(Unit *u) {
664 MountState new_state = MOUNT_DEAD;
668 assert(m->state == MOUNT_DEAD);
670 if (m->deserialized_state != m->state)
671 new_state = m->deserialized_state;
672 else if (m->from_proc_self_mountinfo)
673 new_state = MOUNT_MOUNTED;
675 if (new_state != m->state) {
677 if (new_state == MOUNT_MOUNTING ||
678 new_state == MOUNT_MOUNTING_DONE ||
679 new_state == MOUNT_REMOUNTING ||
680 new_state == MOUNT_UNMOUNTING ||
681 new_state == MOUNT_MOUNTING_SIGTERM ||
682 new_state == MOUNT_MOUNTING_SIGKILL ||
683 new_state == MOUNT_UNMOUNTING_SIGTERM ||
684 new_state == MOUNT_UNMOUNTING_SIGKILL ||
685 new_state == MOUNT_REMOUNTING_SIGTERM ||
686 new_state == MOUNT_REMOUNTING_SIGKILL) {
688 if (m->control_pid <= 0)
691 r = unit_watch_pid(UNIT(m), m->control_pid);
695 r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
700 mount_set_state(m, new_state);
706 static void mount_dump(Unit *u, FILE *f, const char *prefix) {
713 p = get_mount_parameters(m);
716 "%sMount State: %s\n"
720 "%sFile System Type: %s\n"
722 "%sFrom /proc/self/mountinfo: %s\n"
723 "%sFrom fragment: %s\n"
724 "%sDirectoryMode: %04o\n",
725 prefix, mount_state_to_string(m->state),
726 prefix, mount_result_to_string(m->result),
728 prefix, p ? strna(p->what) : "n/a",
729 prefix, p ? strna(p->fstype) : "n/a",
730 prefix, p ? strna(p->options) : "n/a",
731 prefix, yes_no(m->from_proc_self_mountinfo),
732 prefix, yes_no(m->from_fragment),
733 prefix, m->directory_mode);
735 if (m->control_pid > 0)
737 "%sControl PID: %lu\n",
738 prefix, (unsigned long) m->control_pid);
740 exec_context_dump(&m->exec_context, f, prefix);
741 kill_context_dump(&m->kill_context, f, prefix);
744 static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
752 unit_realize_cgroup(UNIT(m));
754 r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
762 UNIT(m)->manager->environment,
766 UNIT(m)->manager->confirm_spawn,
767 UNIT(m)->manager->cgroup_supported,
768 UNIT(m)->cgroup_path,
775 r = unit_watch_pid(UNIT(m), pid);
777 /* FIXME: we need to do something here */
785 unit_unwatch_timer(UNIT(m), &m->timer_watch);
790 static void mount_enter_dead(Mount *m, MountResult f) {
793 if (f != MOUNT_SUCCESS)
796 exec_context_tmp_dirs_done(&m->exec_context);
797 mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
800 static void mount_enter_mounted(Mount *m, MountResult f) {
803 if (f != MOUNT_SUCCESS)
806 mount_set_state(m, MOUNT_MOUNTED);
809 static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
814 if (f != MOUNT_SUCCESS)
817 r = unit_kill_context(
820 state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM,
828 r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
832 mount_set_state(m, state);
833 } else if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
834 mount_enter_mounted(m, MOUNT_SUCCESS);
836 mount_enter_dead(m, MOUNT_SUCCESS);
841 log_warning_unit(UNIT(m)->id,
842 "%s failed to kill processes: %s", UNIT(m)->id, strerror(-r));
844 if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
845 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
847 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
850 void warn_if_dir_nonempty(const char *unit, const char* where) {
854 if (dir_is_empty(where) > 0)
857 log_struct_unit(LOG_NOTICE,
859 "MESSAGE=%s: Directory %s to mount over is not empty, mounting anyway.",
862 MESSAGE_ID(SD_MESSAGE_OVERMOUNTING),
866 static void mount_enter_unmounting(Mount *m) {
871 m->control_command_id = MOUNT_EXEC_UNMOUNT;
872 m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
874 if ((r = exec_command_set(
881 mount_unwatch_control_pid(m);
883 if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
886 mount_set_state(m, MOUNT_UNMOUNTING);
891 log_warning_unit(UNIT(m)->id,
892 "%s failed to run 'umount' task: %s",
893 UNIT(m)->id, strerror(-r));
894 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
897 static void mount_enter_mounting(Mount *m) {
903 m->control_command_id = MOUNT_EXEC_MOUNT;
904 m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
906 mkdir_p_label(m->where, m->directory_mode);
908 warn_if_dir_nonempty(m->meta.id, m->where);
910 /* Create the source directory for bind-mounts if needed */
911 p = get_mount_parameters_fragment(m);
912 if (p && mount_is_bind(p))
913 mkdir_p_label(p->what, m->directory_mode);
915 if (m->from_fragment)
916 r = exec_command_set(
919 m->parameters_fragment.what,
921 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
922 m->parameters_fragment.options ? "-o" : NULL, m->parameters_fragment.options,
930 mount_unwatch_control_pid(m);
932 r = mount_spawn(m, m->control_command, &m->control_pid);
936 mount_set_state(m, MOUNT_MOUNTING);
941 log_warning_unit(UNIT(m)->id,
942 "%s failed to run 'mount' task: %s",
943 UNIT(m)->id, strerror(-r));
944 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
947 static void mount_enter_mounting_done(Mount *m) {
950 mount_set_state(m, MOUNT_MOUNTING_DONE);
953 static void mount_enter_remounting(Mount *m) {
958 m->control_command_id = MOUNT_EXEC_REMOUNT;
959 m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
961 if (m->from_fragment) {
965 if (m->parameters_fragment.options) {
966 if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
975 r = exec_command_set(
978 m->parameters_fragment.what,
980 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
991 mount_unwatch_control_pid(m);
993 if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
996 mount_set_state(m, MOUNT_REMOUNTING);
1001 log_warning_unit(UNIT(m)->id,
1002 "%s failed to run 'remount' task: %s",
1003 UNIT(m)->id, strerror(-r));
1004 m->reload_result = MOUNT_FAILURE_RESOURCES;
1005 mount_enter_mounted(m, MOUNT_SUCCESS);
1008 static int mount_start(Unit *u) {
1009 Mount *m = MOUNT(u);
1013 /* We cannot fulfill this request right now, try again later
1015 if (m->state == MOUNT_UNMOUNTING ||
1016 m->state == MOUNT_UNMOUNTING_SIGTERM ||
1017 m->state == MOUNT_UNMOUNTING_SIGKILL ||
1018 m->state == MOUNT_MOUNTING_SIGTERM ||
1019 m->state == MOUNT_MOUNTING_SIGKILL)
1022 /* Already on it! */
1023 if (m->state == MOUNT_MOUNTING)
1026 assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
1028 m->result = MOUNT_SUCCESS;
1029 m->reload_result = MOUNT_SUCCESS;
1031 mount_enter_mounting(m);
1035 static int mount_stop(Unit *u) {
1036 Mount *m = MOUNT(u);
1041 if (m->state == MOUNT_UNMOUNTING ||
1042 m->state == MOUNT_UNMOUNTING_SIGKILL ||
1043 m->state == MOUNT_UNMOUNTING_SIGTERM ||
1044 m->state == MOUNT_MOUNTING_SIGTERM ||
1045 m->state == MOUNT_MOUNTING_SIGKILL)
1048 assert(m->state == MOUNT_MOUNTING ||
1049 m->state == MOUNT_MOUNTING_DONE ||
1050 m->state == MOUNT_MOUNTED ||
1051 m->state == MOUNT_REMOUNTING ||
1052 m->state == MOUNT_REMOUNTING_SIGTERM ||
1053 m->state == MOUNT_REMOUNTING_SIGKILL);
1055 mount_enter_unmounting(m);
1059 static int mount_reload(Unit *u) {
1060 Mount *m = MOUNT(u);
1064 if (m->state == MOUNT_MOUNTING_DONE)
1067 assert(m->state == MOUNT_MOUNTED);
1069 mount_enter_remounting(m);
1073 static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
1074 Mount *m = MOUNT(u);
1080 unit_serialize_item(u, f, "state", mount_state_to_string(m->state));
1081 unit_serialize_item(u, f, "result", mount_result_to_string(m->result));
1082 unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result));
1084 if (m->control_pid > 0)
1085 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) m->control_pid);
1087 if (m->control_command_id >= 0)
1088 unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
1090 exec_context_serialize(&m->exec_context, UNIT(m), f);
1095 static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1096 Mount *m = MOUNT(u);
1103 if (streq(key, "state")) {
1106 if ((state = mount_state_from_string(value)) < 0)
1107 log_debug_unit(u->id, "Failed to parse state value %s", value);
1109 m->deserialized_state = state;
1110 } else if (streq(key, "result")) {
1113 f = mount_result_from_string(value);
1115 log_debug_unit(UNIT(m)->id,
1116 "Failed to parse result value %s", value);
1117 else if (f != MOUNT_SUCCESS)
1120 } else if (streq(key, "reload-result")) {
1123 f = mount_result_from_string(value);
1125 log_debug_unit(UNIT(m)->id,
1126 "Failed to parse reload result value %s", value);
1127 else if (f != MOUNT_SUCCESS)
1128 m->reload_result = f;
1130 } else if (streq(key, "control-pid")) {
1133 if (parse_pid(value, &pid) < 0)
1134 log_debug_unit(UNIT(m)->id,
1135 "Failed to parse control-pid value %s", value);
1137 m->control_pid = pid;
1138 } else if (streq(key, "control-command")) {
1139 MountExecCommand id;
1141 if ((id = mount_exec_command_from_string(value)) < 0)
1142 log_debug_unit(UNIT(m)->id,
1143 "Failed to parse exec-command value %s", value);
1145 m->control_command_id = id;
1146 m->control_command = m->exec_command + id;
1148 } else if (streq(key, "tmp-dir")) {
1155 m->exec_context.tmp_dir = t;
1156 } else if (streq(key, "var-tmp-dir")) {
1163 m->exec_context.var_tmp_dir = t;
1165 log_debug_unit(UNIT(m)->id,
1166 "Unknown serialization key '%s'", key);
1171 _pure_ static UnitActiveState mount_active_state(Unit *u) {
1174 return state_translation_table[MOUNT(u)->state];
1177 _pure_ static const char *mount_sub_state_to_string(Unit *u) {
1180 return mount_state_to_string(MOUNT(u)->state);
1183 _pure_ static bool mount_check_gc(Unit *u) {
1184 Mount *m = MOUNT(u);
1188 return m->from_proc_self_mountinfo;
1191 static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1192 Mount *m = MOUNT(u);
1198 if (pid != m->control_pid)
1203 if (is_clean_exit(code, status, NULL))
1205 else if (code == CLD_EXITED)
1206 f = MOUNT_FAILURE_EXIT_CODE;
1207 else if (code == CLD_KILLED)
1208 f = MOUNT_FAILURE_SIGNAL;
1209 else if (code == CLD_DUMPED)
1210 f = MOUNT_FAILURE_CORE_DUMP;
1212 assert_not_reached("Unknown code");
1214 if (f != MOUNT_SUCCESS)
1217 if (m->control_command) {
1218 exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status);
1220 m->control_command = NULL;
1221 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
1224 log_full_unit(f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, u->id,
1225 "%s mount process exited, code=%s status=%i",
1226 u->id, sigchld_code_to_string(code), status);
1228 /* Note that mount(8) returning and the kernel sending us a
1229 * mount table change event might happen out-of-order. If an
1230 * operation succeed we assume the kernel will follow soon too
1231 * and already change into the resulting state. If it fails
1232 * we check if the kernel still knows about the mount. and
1233 * change state accordingly. */
1237 case MOUNT_MOUNTING:
1238 case MOUNT_MOUNTING_DONE:
1239 case MOUNT_MOUNTING_SIGKILL:
1240 case MOUNT_MOUNTING_SIGTERM:
1242 if (f == MOUNT_SUCCESS)
1243 mount_enter_mounted(m, f);
1244 else if (m->from_proc_self_mountinfo)
1245 mount_enter_mounted(m, f);
1247 mount_enter_dead(m, f);
1250 case MOUNT_REMOUNTING:
1251 case MOUNT_REMOUNTING_SIGKILL:
1252 case MOUNT_REMOUNTING_SIGTERM:
1254 m->reload_result = f;
1255 if (m->from_proc_self_mountinfo)
1256 mount_enter_mounted(m, MOUNT_SUCCESS);
1258 mount_enter_dead(m, MOUNT_SUCCESS);
1262 case MOUNT_UNMOUNTING:
1263 case MOUNT_UNMOUNTING_SIGKILL:
1264 case MOUNT_UNMOUNTING_SIGTERM:
1266 if (f == MOUNT_SUCCESS)
1267 mount_enter_dead(m, f);
1268 else if (m->from_proc_self_mountinfo)
1269 mount_enter_mounted(m, f);
1271 mount_enter_dead(m, f);
1275 assert_not_reached("Uh, control process died at wrong time.");
1278 /* Notify clients about changed exit status */
1279 unit_add_to_dbus_queue(u);
1282 static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
1283 Mount *m = MOUNT(u);
1286 assert(elapsed == 1);
1287 assert(w == &m->timer_watch);
1291 case MOUNT_MOUNTING:
1292 case MOUNT_MOUNTING_DONE:
1293 log_warning_unit(u->id,
1294 "%s mounting timed out. Stopping.", u->id);
1295 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
1298 case MOUNT_REMOUNTING:
1299 log_warning_unit(u->id,
1300 "%s remounting timed out. Stopping.", u->id);
1301 m->reload_result = MOUNT_FAILURE_TIMEOUT;
1302 mount_enter_mounted(m, MOUNT_SUCCESS);
1305 case MOUNT_UNMOUNTING:
1306 log_warning_unit(u->id,
1307 "%s unmounting timed out. Stopping.", u->id);
1308 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
1311 case MOUNT_MOUNTING_SIGTERM:
1312 if (m->kill_context.send_sigkill) {
1313 log_warning_unit(u->id,
1314 "%s mounting timed out. Killing.", u->id);
1315 mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
1317 log_warning_unit(u->id,
1318 "%s mounting timed out. Skipping SIGKILL. Ignoring.",
1321 if (m->from_proc_self_mountinfo)
1322 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
1324 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
1328 case MOUNT_REMOUNTING_SIGTERM:
1329 if (m->kill_context.send_sigkill) {
1330 log_warning_unit(u->id,
1331 "%s remounting timed out. Killing.", u->id);
1332 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
1334 log_warning_unit(u->id,
1335 "%s remounting timed out. Skipping SIGKILL. Ignoring.",
1338 if (m->from_proc_self_mountinfo)
1339 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
1341 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
1345 case MOUNT_UNMOUNTING_SIGTERM:
1346 if (m->kill_context.send_sigkill) {
1347 log_warning_unit(u->id,
1348 "%s unmounting timed out. Killing.", u->id);
1349 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
1351 log_warning_unit(u->id,
1352 "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
1355 if (m->from_proc_self_mountinfo)
1356 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
1358 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
1362 case MOUNT_MOUNTING_SIGKILL:
1363 case MOUNT_REMOUNTING_SIGKILL:
1364 case MOUNT_UNMOUNTING_SIGKILL:
1365 log_warning_unit(u->id,
1366 "%s mount process still around after SIGKILL. Ignoring.",
1369 if (m->from_proc_self_mountinfo)
1370 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
1372 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
1376 assert_not_reached("Timeout at wrong time.");
1380 static int mount_add_one(
1384 const char *options,
1390 char *e, *w = NULL, *o = NULL, *f = NULL;
1392 bool load_extras = false;
1400 /* Ignore API mount points. They should never be referenced in
1401 * dependencies ever. */
1402 if (mount_point_is_api(where) || mount_point_ignore(where))
1405 if (streq(fstype, "autofs"))
1408 /* probably some kind of swap, ignore */
1409 if (!is_path(where))
1412 e = unit_name_from_path(where, ".mount");
1416 u = manager_get_unit(m, e);
1418 const char* const target =
1419 fstype_is_network(fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
1423 u = unit_new(m, sizeof(Mount));
1429 r = unit_add_name(u, e);
1435 MOUNT(u)->where = strdup(where);
1436 if (!MOUNT(u)->where) {
1441 u->source_path = strdup("/proc/self/mountinfo");
1442 if (!u->source_path) {
1447 r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true);
1451 if (should_umount(MOUNT(u))) {
1452 r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
1457 unit_add_to_load_queue(u);
1462 if (!MOUNT(u)->where) {
1463 MOUNT(u)->where = strdup(where);
1464 if (!MOUNT(u)->where) {
1470 if (u->load_state == UNIT_NOT_FOUND) {
1471 u->load_state = UNIT_LOADED;
1474 /* Load in the extras later on, after we
1475 * finished initialization of the unit */
1480 if (!(w = strdup(what)) ||
1481 !(o = strdup(options)) ||
1482 !(f = strdup(fstype))) {
1487 p = &MOUNT(u)->parameters_proc_self_mountinfo;
1489 MOUNT(u)->is_mounted = true;
1490 MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
1491 MOUNT(u)->just_changed = !streq_ptr(p->options, o);
1494 MOUNT(u)->from_proc_self_mountinfo = true;
1506 r = mount_add_extras(MOUNT(u));
1511 unit_add_to_dbus_queue(u);
1526 static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
1532 rewind(m->proc_self_mountinfo);
1535 _cleanup_free_ char *device = NULL, *path = NULL, *options = NULL, *options2 = NULL, *fstype = NULL, *d = NULL, *p = NULL, *o = NULL;
1538 k = fscanf(m->proc_self_mountinfo,
1539 "%*s " /* (1) mount id */
1540 "%*s " /* (2) parent id */
1541 "%*s " /* (3) major:minor */
1542 "%*s " /* (4) root */
1543 "%ms " /* (5) mount point */
1544 "%ms" /* (6) mount options */
1545 "%*[^-]" /* (7) optional fields */
1546 "- " /* (8) separator */
1547 "%ms " /* (9) file system type */
1548 "%ms" /* (10) mount source */
1549 "%ms" /* (11) mount options 2 */
1550 "%*[^\n]", /* some rubbish at the end */
1561 log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
1565 o = strjoin(options, ",", options2, NULL);
1569 d = cunescape(device);
1570 p = cunescape(path);
1574 k = mount_add_one(m, d, p, o, fstype, set_flags);
1582 static void mount_shutdown(Manager *m) {
1585 if (m->proc_self_mountinfo) {
1586 fclose(m->proc_self_mountinfo);
1587 m->proc_self_mountinfo = NULL;
1591 static int mount_enumerate(Manager *m) {
1595 if (!m->proc_self_mountinfo) {
1596 struct epoll_event ev = {
1598 .data.ptr = &m->mount_watch,
1601 m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
1602 if (!m->proc_self_mountinfo)
1605 m->mount_watch.type = WATCH_MOUNT;
1606 m->mount_watch.fd = fileno(m->proc_self_mountinfo);
1608 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
1612 r = mount_load_proc_self_mountinfo(m, false);
1623 void mount_fd_event(Manager *m, int events) {
1628 assert(events & EPOLLPRI);
1630 /* The manager calls this for every fd event happening on the
1631 * /proc/self/mountinfo file, which informs us about mounting
1634 r = mount_load_proc_self_mountinfo(m, true);
1636 log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-r));
1638 /* Reset flags, just in case, for later calls */
1639 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1640 Mount *mount = MOUNT(u);
1642 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1648 manager_dispatch_load_queue(m);
1650 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1651 Mount *mount = MOUNT(u);
1653 if (!mount->is_mounted) {
1654 /* This has just been unmounted. */
1656 mount->from_proc_self_mountinfo = false;
1658 switch (mount->state) {
1661 mount_enter_dead(mount, MOUNT_SUCCESS);
1665 mount_set_state(mount, mount->state);
1670 } else if (mount->just_mounted || mount->just_changed) {
1672 /* New or changed mount entry */
1674 switch (mount->state) {
1678 mount_enter_mounted(mount, MOUNT_SUCCESS);
1681 case MOUNT_MOUNTING:
1682 mount_enter_mounting_done(mount);
1686 /* Nothing really changed, but let's
1687 * issue an notification call
1688 * nonetheless, in case somebody is
1689 * waiting for this. (e.g. file system
1690 * ro/rw remounts.) */
1691 mount_set_state(mount, mount->state);
1696 /* Reset the flags for later calls */
1697 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1701 static void mount_reset_failed(Unit *u) {
1702 Mount *m = MOUNT(u);
1706 if (m->state == MOUNT_FAILED)
1707 mount_set_state(m, MOUNT_DEAD);
1709 m->result = MOUNT_SUCCESS;
1710 m->reload_result = MOUNT_SUCCESS;
1713 static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
1714 return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
1717 static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
1718 [MOUNT_DEAD] = "dead",
1719 [MOUNT_MOUNTING] = "mounting",
1720 [MOUNT_MOUNTING_DONE] = "mounting-done",
1721 [MOUNT_MOUNTED] = "mounted",
1722 [MOUNT_REMOUNTING] = "remounting",
1723 [MOUNT_UNMOUNTING] = "unmounting",
1724 [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
1725 [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
1726 [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
1727 [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
1728 [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
1729 [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
1730 [MOUNT_FAILED] = "failed"
1733 DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
1735 static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
1736 [MOUNT_EXEC_MOUNT] = "ExecMount",
1737 [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
1738 [MOUNT_EXEC_REMOUNT] = "ExecRemount",
1741 DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
1743 static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
1744 [MOUNT_SUCCESS] = "success",
1745 [MOUNT_FAILURE_RESOURCES] = "resources",
1746 [MOUNT_FAILURE_TIMEOUT] = "timeout",
1747 [MOUNT_FAILURE_EXIT_CODE] = "exit-code",
1748 [MOUNT_FAILURE_SIGNAL] = "signal",
1749 [MOUNT_FAILURE_CORE_DUMP] = "core-dump"
1752 DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
1754 const UnitVTable mount_vtable = {
1755 .object_size = sizeof(Mount),
1762 .private_section = "Mount",
1763 .exec_context_offset = offsetof(Mount, exec_context),
1764 .cgroup_context_offset = offsetof(Mount, cgroup_context),
1767 .no_instances = true,
1773 .coldplug = mount_coldplug,
1777 .start = mount_start,
1779 .reload = mount_reload,
1783 .serialize = mount_serialize,
1784 .deserialize_item = mount_deserialize_item,
1786 .active_state = mount_active_state,
1787 .sub_state_to_string = mount_sub_state_to_string,
1789 .check_gc = mount_check_gc,
1791 .sigchld_event = mount_sigchld_event,
1792 .timer_event = mount_timer_event,
1794 .reset_failed = mount_reset_failed,
1796 .bus_interface = "org.freedesktop.systemd1.Mount",
1797 .bus_message_handler = bus_mount_message_handler,
1798 .bus_invalidating_properties = bus_mount_invalidating_properties,
1799 .bus_set_property = bus_mount_set_property,
1800 .bus_commit_properties = bus_mount_commit_properties,
1802 .enumerate = mount_enumerate,
1803 .shutdown = mount_shutdown,
1805 .status_message_formats = {
1806 .starting_stopping = {
1807 [0] = "Mounting %s...",
1808 [1] = "Unmounting %s...",
1810 .finished_start_job = {
1811 [JOB_DONE] = "Mounted %s.",
1812 [JOB_FAILED] = "Failed to mount %s.",
1813 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1814 [JOB_TIMEOUT] = "Timed out mounting %s.",
1816 .finished_stop_job = {
1817 [JOB_DONE] = "Unmounted %s.",
1818 [JOB_FAILED] = "Failed unmounting %s.",
1819 [JOB_TIMEOUT] = "Timed out unmounting %s.",