]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/mount.c
sd-event: rework API to support CLOCK_REALTIME_ALARM and CLOCK_BOOTTIME_ALARM, too
[thirdparty/systemd.git] / src / core / mount.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5cb5a6ff 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
a7334b09
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
5cb5a6ff 22#include <errno.h>
b08d03ff
LP
23#include <stdio.h>
24#include <mntent.h>
ef734fd6 25#include <sys/epoll.h>
e537352b 26#include <signal.h>
5cb5a6ff 27
c17ec25e 28#include "manager.h"
87f0e418 29#include "unit.h"
5cb5a6ff
LP
30#include "mount.h"
31#include "load-fragment.h"
5cb5a6ff 32#include "load-dropin.h"
b08d03ff 33#include "log.h"
20ad4cfd 34#include "sd-messages.h"
e537352b 35#include "strv.h"
49e942b2 36#include "mkdir.h"
9eb977db 37#include "path-util.h"
e537352b 38#include "mount-setup.h"
9e2f7c11 39#include "unit-name.h"
4139c1b2 40#include "dbus-mount.h"
514f4ef5 41#include "special.h"
8a0867d6 42#include "bus-errors.h"
9a57c629 43#include "exit-status.h"
f6a6225e 44#include "def.h"
5cb5a6ff 45
f50e0a01
LP
46static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
47 [MOUNT_DEAD] = UNIT_INACTIVE,
48 [MOUNT_MOUNTING] = UNIT_ACTIVATING,
e537352b 49 [MOUNT_MOUNTING_DONE] = UNIT_ACTIVE,
f50e0a01 50 [MOUNT_MOUNTED] = UNIT_ACTIVE,
032ff4af 51 [MOUNT_REMOUNTING] = UNIT_RELOADING,
f50e0a01 52 [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
e537352b
LP
53 [MOUNT_MOUNTING_SIGTERM] = UNIT_DEACTIVATING,
54 [MOUNT_MOUNTING_SIGKILL] = UNIT_DEACTIVATING,
032ff4af
LP
55 [MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
56 [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
e537352b
LP
57 [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
58 [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
fdf20a31 59 [MOUNT_FAILED] = UNIT_FAILED
f50e0a01 60};
5cb5a6ff 61
718db961
LP
62static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
63static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
64
fc676b00
ZJS
65static bool mount_is_network(MountParameters *p) {
66 assert(p);
67
68 if (mount_test_option(p->options, "_netdev"))
69 return true;
70
71 if (p->fstype && fstype_is_network(p->fstype))
72 return true;
73
74 return false;
75}
76
77static bool mount_is_bind(MountParameters *p) {
78 assert(p);
79
80 if (mount_test_option(p->options, "bind"))
81 return true;
82
83 if (p->fstype && streq(p->fstype, "bind"))
84 return true;
85
86 if (mount_test_option(p->options, "rbind"))
87 return true;
88
89 if (p->fstype && streq(p->fstype, "rbind"))
90 return true;
91
92 return false;
93}
94
95static bool mount_is_auto(MountParameters *p) {
96 assert(p);
97
98 return !mount_test_option(p->options, "noauto");
99}
100
101static bool needs_quota(MountParameters *p) {
102 assert(p);
103
104 if (mount_is_network(p))
105 return false;
106
107 if (mount_is_bind(p))
108 return false;
109
110 return mount_test_option(p->options, "usrquota") ||
111 mount_test_option(p->options, "grpquota") ||
112 mount_test_option(p->options, "quota") ||
113 mount_test_option(p->options, "usrjquota") ||
114 mount_test_option(p->options, "grpjquota");
115}
116
a16e1123
LP
117static void mount_init(Unit *u) {
118 Mount *m = MOUNT(u);
5cb5a6ff 119
a16e1123 120 assert(u);
ac155bb8 121 assert(u->load_state == UNIT_STUB);
a16e1123 122
1f19a534 123 m->timeout_usec = u->manager->default_timeout_start_usec;
3e5235b0
LP
124 m->directory_mode = 0755;
125
6b1dc2bd
LP
126 if (unit_has_name(u, "-.mount")) {
127 /* Don't allow start/stop for root directory */
5bcb0f2b
LP
128 u->refuse_manual_start = true;
129 u->refuse_manual_stop = true;
6b1dc2bd
LP
130 } else {
131 /* The stdio/kmsg bridge socket is on /, in order to avoid a
132 * dep loop, don't use kmsg logging for -.mount */
ac155bb8
MS
133 m->exec_context.std_output = u->manager->default_std_output;
134 m->exec_context.std_error = u->manager->default_std_error;
f6cebb3b 135 }
c3686083 136
a16e1123
LP
137 /* We need to make sure that /bin/mount is always called in
138 * the same process group as us, so that the autofs kernel
139 * side doesn't send us another mount request while we are
140 * already trying to comply its last one. */
74922904 141 m->exec_context.same_pgrp = true;
8d567588 142
a16e1123 143 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
c8f4d764 144
5bcb0f2b 145 u->ignore_on_isolate = true;
8d567588
LP
146}
147
718db961
LP
148static int mount_arm_timer(Mount *m) {
149 int r;
150
151 assert(m);
152
153 if (m->timeout_usec <= 0) {
154 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
155 return 0;
156 }
157
158 if (m->timer_event_source) {
159 r = sd_event_source_set_time(m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec);
160 if (r < 0)
161 return r;
162
163 return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
164 }
165
6a0f1f6d
LP
166 return sd_event_add_time(
167 UNIT(m)->manager->event,
168 &m->timer_event_source,
169 CLOCK_MONOTONIC,
170 now(CLOCK_MONOTONIC) + m->timeout_usec, 0,
171 mount_dispatch_timer, m);
718db961
LP
172}
173
a16e1123 174static void mount_unwatch_control_pid(Mount *m) {
5e94833f
LP
175 assert(m);
176
177 if (m->control_pid <= 0)
178 return;
179
180 unit_unwatch_pid(UNIT(m), m->control_pid);
181 m->control_pid = 0;
182}
183
e537352b
LP
184static void mount_parameters_done(MountParameters *p) {
185 assert(p);
186
187 free(p->what);
188 free(p->options);
189 free(p->fstype);
190
191 p->what = p->options = p->fstype = NULL;
192}
193
87f0e418 194static void mount_done(Unit *u) {
ef734fd6 195 Mount *m = MOUNT(u);
034c6ed7 196
ef734fd6 197 assert(m);
034c6ed7 198
e537352b
LP
199 free(m->where);
200 m->where = NULL;
f50e0a01 201
e537352b
LP
202 mount_parameters_done(&m->parameters_proc_self_mountinfo);
203 mount_parameters_done(&m->parameters_fragment);
ef734fd6 204
613b411c 205 m->exec_runtime = exec_runtime_unref(m->exec_runtime);
e537352b
LP
206 exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
207 m->control_command = NULL;
f50e0a01 208
a16e1123 209 mount_unwatch_control_pid(m);
f50e0a01 210
718db961 211 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
f50e0a01
LP
212}
213
44a6b1b6 214_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
cb39ed3f
LP
215 assert(m);
216
217 if (m->from_fragment)
218 return &m->parameters_fragment;
cb39ed3f
LP
219
220 return NULL;
221}
222
44a6b1b6 223_pure_ static MountParameters* get_mount_parameters(Mount *m) {
cb39ed3f
LP
224 assert(m);
225
226 if (m->from_proc_self_mountinfo)
227 return &m->parameters_proc_self_mountinfo;
228
6b1dc2bd 229 return get_mount_parameters_fragment(m);
cb39ed3f
LP
230}
231
6e2ef85b 232static int mount_add_mount_links(Mount *m) {
a57f7e2c 233 _cleanup_free_ char *parent = NULL;
5c78d8e2 234 MountParameters *pm;
ac155bb8 235 Unit *other;
a57f7e2c
LP
236 Iterator i;
237 Set *s;
b08d03ff
LP
238 int r;
239
6e2ef85b 240 assert(m);
b08d03ff 241
a57f7e2c
LP
242 if (!path_equal(m->where, "/")) {
243 /* Adds in links to other mount points that might lie further
244 * up in the hierarchy */
245 r = path_get_parent(m->where, &parent);
4f0eedb7 246 if (r < 0)
6e2ef85b 247 return r;
01f78473 248
a57f7e2c 249 r = unit_require_mounts_for(UNIT(m), parent);
4f0eedb7 250 if (r < 0)
01f78473 251 return r;
4f0eedb7 252 }
01f78473 253
a57f7e2c
LP
254 /* Adds in links to other mount points that might be needed
255 * for the source path (if this is a bind mount) to be
256 * available. */
257 pm = get_mount_parameters_fragment(m);
fc676b00
ZJS
258 if (pm && pm->what &&
259 path_is_absolute(pm->what) &&
260 !mount_is_network(pm)) {
261
a57f7e2c 262 r = unit_require_mounts_for(UNIT(m), pm->what);
4f0eedb7 263 if (r < 0)
6e2ef85b 264 return r;
4f0eedb7 265 }
b08d03ff 266
a57f7e2c
LP
267 /* Adds in links to other units that use this path or paths
268 * further down in the hierarchy */
269 s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
270 SET_FOREACH(other, s, i) {
b08d03ff 271
a57f7e2c
LP
272 if (other->load_state != UNIT_LOADED)
273 continue;
b08d03ff 274
a57f7e2c
LP
275 if (other == UNIT(m))
276 continue;
b08d03ff 277
a57f7e2c 278 r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true);
4f0eedb7 279 if (r < 0)
6e2ef85b 280 return r;
b08d03ff 281
a57f7e2c
LP
282 if (UNIT(m)->fragment_path) {
283 /* If we have fragment configuration, then make this dependency required */
284 r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true);
285 if (r < 0)
286 return r;
287 }
7c8fa05c
LP
288 }
289
290 return 0;
291}
292
173a8d04
LP
293static int mount_add_device_links(Mount *m) {
294 MountParameters *p;
5073f89f 295 bool device_wants_mount = false;
9fff8a1f 296 int r;
173a8d04
LP
297
298 assert(m);
299
6b1dc2bd
LP
300 p = get_mount_parameters_fragment(m);
301 if (!p)
173a8d04
LP
302 return 0;
303
9fff8a1f 304 if (!p->what)
173a8d04 305 return 0;
5c78d8e2 306
dd144c63
LP
307 if (mount_is_bind(p))
308 return 0;
309
310 if (!is_device_path(p->what))
311 return 0;
312
313 if (path_equal(m->where, "/"))
314 return 0;
315
5073f89f
TG
316 if (mount_is_auto(p) && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
317 device_wants_mount = true;
318
319 r = unit_add_node_link(UNIT(m), p->what, device_wants_mount);
dd144c63
LP
320 if (r < 0)
321 return r;
9fff8a1f 322
9fff8a1f 323 return 0;
173a8d04
LP
324}
325
6b1dc2bd
LP
326static int mount_add_quota_links(Mount *m) {
327 int r;
328 MountParameters *p;
329
330 assert(m);
331
67445f4e 332 if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
6b1dc2bd
LP
333 return 0;
334
335 p = get_mount_parameters_fragment(m);
336 if (!p)
337 return 0;
338
339 if (!needs_quota(p))
340 return 0;
341
342 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true);
343 if (r < 0)
344 return r;
345
346 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true);
347 if (r < 0)
348 return r;
349
350 return 0;
351}
352
88ac30a1
TG
353static bool should_umount(Mount *m) {
354 MountParameters *p;
355
356 if (path_equal(m->where, "/") ||
357 path_equal(m->where, "/usr"))
358 return false;
359
360 p = get_mount_parameters(m);
361 if (p && mount_test_option(p->options, "x-initrd.mount") &&
362 !in_initrd())
363 return false;
364
365 return true;
366}
367
2edd4434 368static int mount_add_default_dependencies(Mount *m) {
0c17fbce 369 const char *after, *after2, *online;
9ddc4a26 370 MountParameters *p;
0c17fbce 371 int r;
2edd4434
LP
372
373 assert(m);
374
67445f4e 375 if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
9ddc4a26 376 return 0;
cb39ed3f 377
4d4fe926
MS
378 p = get_mount_parameters(m);
379
6b1dc2bd
LP
380 if (!p)
381 return 0;
2edd4434 382
6b1dc2bd
LP
383 if (path_equal(m->where, "/"))
384 return 0;
385
e8d2f6cd 386 if (mount_is_network(p)) {
6b1dc2bd 387 after = SPECIAL_REMOTE_FS_PRE_TARGET;
a63a5c46 388 after2 = SPECIAL_NETWORK_TARGET;
0c17fbce 389 online = SPECIAL_NETWORK_ONLINE_TARGET;
e8d2f6cd 390 } else {
6b1dc2bd 391 after = SPECIAL_LOCAL_FS_PRE_TARGET;
a63a5c46 392 after2 = NULL;
0c17fbce 393 online = NULL;
e8d2f6cd 394 }
6b1dc2bd 395
e8d2f6cd 396 r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
6b1dc2bd
LP
397 if (r < 0)
398 return r;
399
a63a5c46
LP
400 if (after2) {
401 r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after2, NULL, true);
402 if (r < 0)
403 return r;
404 }
405
0c17fbce
LP
406 if (online) {
407 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, online, NULL, true);
e8d2f6cd
LP
408 if (r < 0)
409 return r;
410 }
411
88ac30a1
TG
412 if (should_umount(m)) {
413 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
414 if (r < 0)
415 return r;
416 }
2edd4434
LP
417
418 return 0;
419}
420
f4c05147 421static int mount_fix_timeouts(Mount *m) {
8024c3a7
LP
422 MountParameters *p;
423 const char *timeout = NULL;
424 Unit *other;
425 Iterator i;
426 usec_t u;
f4c05147
LP
427 char *t;
428 int r;
8024c3a7
LP
429
430 assert(m);
431
6b1dc2bd
LP
432 p = get_mount_parameters_fragment(m);
433 if (!p)
f4c05147 434 return 0;
8024c3a7
LP
435
436 /* Allow configuration how long we wait for a device that
437 * backs a mount point to show up. This is useful to support
438 * endless device timeouts for devices that show up only after
439 * user input, like crypto devices. */
440
441 if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout")))
442 timeout += 31;
92a39ae1 443 else if ((timeout = mount_test_option(p->options, "x-systemd.device-timeout")))
8024c3a7
LP
444 timeout += 25;
445 else
f4c05147
LP
446 return 0;
447
448 t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE));
449 if (!t)
450 return -ENOMEM;
8024c3a7 451
7f602784 452 r = parse_sec(t, &u);
f4c05147
LP
453 free(t);
454
455 if (r < 0) {
66870f90
ZJS
456 log_warning_unit(UNIT(m)->id,
457 "Failed to parse timeout for %s, ignoring: %s",
458 m->where, timeout);
f4c05147 459 return r;
8024c3a7
LP
460 }
461
1124fe6f 462 SET_FOREACH(other, UNIT(m)->dependencies[UNIT_AFTER], i) {
ac155bb8 463 if (other->type != UNIT_DEVICE)
8024c3a7
LP
464 continue;
465
ac155bb8 466 other->job_timeout = u;
8024c3a7 467 }
f4c05147
LP
468
469 return 0;
8024c3a7
LP
470}
471
8d567588 472static int mount_verify(Mount *m) {
a57f7e2c 473 _cleanup_free_ char *e = NULL;
8d567588 474 bool b;
a57f7e2c 475
8d567588
LP
476 assert(m);
477
1124fe6f 478 if (UNIT(m)->load_state != UNIT_LOADED)
8d567588
LP
479 return 0;
480
6b1dc2bd 481 if (!m->from_fragment && !m->from_proc_self_mountinfo)
8cbef760
LP
482 return -ENOENT;
483
a57f7e2c
LP
484 e = unit_name_from_path(m->where, ".mount");
485 if (!e)
8d567588
LP
486 return -ENOMEM;
487
488 b = unit_has_name(UNIT(m), e);
8d567588 489 if (!b) {
e821075a 490 log_error_unit(UNIT(m)->id, "%s's Where= setting doesn't match unit name. Refusing.", UNIT(m)->id);
8d567588
LP
491 return -EINVAL;
492 }
493
33ff02c9 494 if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
e821075a 495 log_error_unit(UNIT(m)->id, "Cannot create mount unit for API file system %s. Refusing.", m->where);
33ff02c9
LP
496 return -EINVAL;
497 }
498
1124fe6f 499 if (UNIT(m)->fragment_path && !m->parameters_fragment.what) {
e821075a 500 log_error_unit(UNIT(m)->id, "%s's What setting is missing. Refusing.", UNIT(m)->id);
4e85aff4
LP
501 return -EBADMSG;
502 }
503
4819ff03 504 if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) {
e821075a 505 log_error_unit(UNIT(m)->id, "%s has PAM enabled. Kill mode must be set to control-group'. Refusing.",UNIT(m)->id);
4d0e5dbd
LP
506 return -EINVAL;
507 }
508
8d567588
LP
509 return 0;
510}
511
1a4ac875
MS
512static int mount_add_extras(Mount *m) {
513 Unit *u = UNIT(m);
e537352b
LP
514 int r;
515
e821075a
LP
516 assert(m);
517
518 if (u->fragment_path)
1a4ac875 519 m->from_fragment = true;
e537352b 520
1a4ac875
MS
521 if (!m->where) {
522 m->where = unit_name_to_path(u->id);
a16e1123 523 if (!m->where)
1a4ac875
MS
524 return -ENOMEM;
525 }
a16e1123 526
1a4ac875 527 path_kill_slashes(m->where);
e537352b 528
e821075a 529 if (!u->description) {
1a4ac875
MS
530 r = unit_set_description(u, m->where);
531 if (r < 0)
173a8d04 532 return r;
1a4ac875 533 }
6e2ef85b 534
1a4ac875
MS
535 r = mount_add_device_links(m);
536 if (r < 0)
537 return r;
6e2ef85b 538
1a4ac875
MS
539 r = mount_add_mount_links(m);
540 if (r < 0)
541 return r;
6e2ef85b 542
1a4ac875
MS
543 r = mount_add_quota_links(m);
544 if (r < 0)
545 return r;
e537352b 546
598459ce
LP
547 r = unit_patch_contexts(u);
548 if (r < 0)
549 return r;
4e67ddd6 550
598459ce 551 r = unit_add_exec_dependencies(u, &m->exec_context);
a016b922
LP
552 if (r < 0)
553 return r;
554
598459ce 555 r = unit_add_default_slice(u, &m->cgroup_context);
1a4ac875
MS
556 if (r < 0)
557 return r;
558
598459ce 559 r = mount_fix_timeouts(m);
e821075a
LP
560 if (r < 0)
561 return r;
562
598459ce
LP
563 if (u->default_dependencies) {
564 r = mount_add_default_dependencies(m);
565 if (r < 0)
566 return r;
567 }
568
1a4ac875
MS
569 return 0;
570}
571
572static int mount_load(Unit *u) {
573 Mount *m = MOUNT(u);
574 int r;
575
576 assert(u);
577 assert(u->load_state == UNIT_STUB);
578
8eba616f
MS
579 if (m->from_proc_self_mountinfo)
580 r = unit_load_fragment_and_dropin_optional(u);
581 else
582 r = unit_load_fragment_and_dropin(u);
583
1a4ac875
MS
584 if (r < 0)
585 return r;
155da457 586
1a4ac875
MS
587 /* This is a new unit? Then let's add in some extras */
588 if (u->load_state == UNIT_LOADED) {
589 r = mount_add_extras(m);
590 if (r < 0)
591 return r;
e537352b
LP
592 }
593
8d567588 594 return mount_verify(m);
e537352b
LP
595}
596
a16e1123
LP
597static int mount_notify_automount(Mount *m, int status) {
598 Unit *p;
599 int r;
57020a3a 600 Iterator i;
a16e1123
LP
601
602 assert(m);
603
1124fe6f 604 SET_FOREACH(p, UNIT(m)->dependencies[UNIT_TRIGGERED_BY], i)
ac155bb8 605 if (p->type == UNIT_AUTOMOUNT) {
57020a3a
LP
606 r = automount_send_ready(AUTOMOUNT(p), status);
607 if (r < 0)
608 return r;
609 }
a16e1123 610
57020a3a 611 return 0;
a16e1123
LP
612}
613
e537352b
LP
614static void mount_set_state(Mount *m, MountState state) {
615 MountState old_state;
616 assert(m);
617
618 old_state = m->state;
619 m->state = state;
620
621 if (state != MOUNT_MOUNTING &&
622 state != MOUNT_MOUNTING_DONE &&
623 state != MOUNT_REMOUNTING &&
624 state != MOUNT_UNMOUNTING &&
625 state != MOUNT_MOUNTING_SIGTERM &&
626 state != MOUNT_MOUNTING_SIGKILL &&
627 state != MOUNT_UNMOUNTING_SIGTERM &&
628 state != MOUNT_UNMOUNTING_SIGKILL &&
629 state != MOUNT_REMOUNTING_SIGTERM &&
630 state != MOUNT_REMOUNTING_SIGKILL) {
718db961 631 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
a16e1123 632 mount_unwatch_control_pid(m);
e537352b 633 m->control_command = NULL;
a16e1123 634 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
e537352b
LP
635 }
636
8d567588
LP
637 if (state == MOUNT_MOUNTED ||
638 state == MOUNT_REMOUNTING)
639 mount_notify_automount(m, 0);
640 else if (state == MOUNT_DEAD ||
641 state == MOUNT_UNMOUNTING ||
642 state == MOUNT_MOUNTING_SIGTERM ||
643 state == MOUNT_MOUNTING_SIGKILL ||
644 state == MOUNT_REMOUNTING_SIGTERM ||
645 state == MOUNT_REMOUNTING_SIGKILL ||
646 state == MOUNT_UNMOUNTING_SIGTERM ||
647 state == MOUNT_UNMOUNTING_SIGKILL ||
36fcd77e 648 state == MOUNT_FAILED) {
b929bf04
TA
649 if (state != old_state)
650 mount_notify_automount(m, -ENODEV);
651 }
8d567588 652
e537352b 653 if (state != old_state)
66870f90
ZJS
654 log_debug_unit(UNIT(m)->id,
655 "%s changed %s -> %s",
656 UNIT(m)->id,
657 mount_state_to_string(old_state),
658 mount_state_to_string(state));
e537352b 659
9d2f5178
LP
660 unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
661 m->reload_result = MOUNT_SUCCESS;
e537352b
LP
662}
663
664static int mount_coldplug(Unit *u) {
665 Mount *m = MOUNT(u);
a16e1123
LP
666 MountState new_state = MOUNT_DEAD;
667 int r;
e537352b
LP
668
669 assert(m);
670 assert(m->state == MOUNT_DEAD);
671
a16e1123
LP
672 if (m->deserialized_state != m->state)
673 new_state = m->deserialized_state;
674 else if (m->from_proc_self_mountinfo)
675 new_state = MOUNT_MOUNTED;
e537352b 676
5bcb0f2b
LP
677 if (new_state == m->state)
678 return 0;
e537352b 679
5bcb0f2b
LP
680 if (new_state == MOUNT_MOUNTING ||
681 new_state == MOUNT_MOUNTING_DONE ||
682 new_state == MOUNT_REMOUNTING ||
683 new_state == MOUNT_UNMOUNTING ||
684 new_state == MOUNT_MOUNTING_SIGTERM ||
685 new_state == MOUNT_MOUNTING_SIGKILL ||
686 new_state == MOUNT_UNMOUNTING_SIGTERM ||
687 new_state == MOUNT_UNMOUNTING_SIGKILL ||
688 new_state == MOUNT_REMOUNTING_SIGTERM ||
689 new_state == MOUNT_REMOUNTING_SIGKILL) {
690
691 if (m->control_pid <= 0)
692 return -EBADMSG;
693
694 r = unit_watch_pid(UNIT(m), m->control_pid);
695 if (r < 0)
696 return r;
e537352b 697
5bcb0f2b
LP
698 r = mount_arm_timer(m);
699 if (r < 0)
700 return r;
a16e1123 701 }
e537352b 702
5bcb0f2b 703 mount_set_state(m, new_state);
e537352b 704 return 0;
e537352b
LP
705}
706
707static void mount_dump(Unit *u, FILE *f, const char *prefix) {
708 Mount *m = MOUNT(u);
709 MountParameters *p;
710
711 assert(m);
712 assert(f);
713
cb39ed3f 714 p = get_mount_parameters(m);
e537352b
LP
715
716 fprintf(f,
717 "%sMount State: %s\n"
81a5c6d0 718 "%sResult: %s\n"
e537352b
LP
719 "%sWhere: %s\n"
720 "%sWhat: %s\n"
721 "%sFile System Type: %s\n"
722 "%sOptions: %s\n"
e537352b
LP
723 "%sFrom /proc/self/mountinfo: %s\n"
724 "%sFrom fragment: %s\n"
3e5235b0 725 "%sDirectoryMode: %04o\n",
a16e1123 726 prefix, mount_state_to_string(m->state),
81a5c6d0 727 prefix, mount_result_to_string(m->result),
e537352b 728 prefix, m->where,
1e4fc9b1
HH
729 prefix, p ? strna(p->what) : "n/a",
730 prefix, p ? strna(p->fstype) : "n/a",
731 prefix, p ? strna(p->options) : "n/a",
e537352b
LP
732 prefix, yes_no(m->from_proc_self_mountinfo),
733 prefix, yes_no(m->from_fragment),
3e5235b0 734 prefix, m->directory_mode);
e537352b
LP
735
736 if (m->control_pid > 0)
737 fprintf(f,
ccd06097
ZJS
738 "%sControl PID: "PID_FMT"\n",
739 prefix, m->control_pid);
e537352b
LP
740
741 exec_context_dump(&m->exec_context, f, prefix);
4819ff03 742 kill_context_dump(&m->kill_context, f, prefix);
e537352b
LP
743}
744
a16e1123
LP
745static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
746 pid_t pid;
747 int r;
748
749 assert(m);
750 assert(c);
751 assert(_pid);
752
4ad49000
LP
753 unit_realize_cgroup(UNIT(m));
754
613b411c
LP
755 r = unit_setup_exec_runtime(UNIT(m));
756 if (r < 0)
757 goto fail;
758
718db961 759 r = mount_arm_timer(m);
36697dc0 760 if (r < 0)
a16e1123
LP
761 goto fail;
762
4ad49000
LP
763 r = exec_spawn(c,
764 NULL,
765 &m->exec_context,
766 NULL, 0,
767 UNIT(m)->manager->environment,
768 true,
769 true,
770 true,
771 UNIT(m)->manager->confirm_spawn,
13b84ec7 772 UNIT(m)->manager->cgroup_supported,
4ad49000 773 UNIT(m)->cgroup_path,
e66cf1a3 774 manager_get_runtime_prefix(UNIT(m)->manager),
4ad49000 775 UNIT(m)->id,
09812eb7 776 0,
4ad49000 777 NULL,
613b411c 778 m->exec_runtime,
4ad49000
LP
779 &pid);
780 if (r < 0)
a16e1123
LP
781 goto fail;
782
4ad49000
LP
783 r = unit_watch_pid(UNIT(m), pid);
784 if (r < 0)
a16e1123
LP
785 /* FIXME: we need to do something here */
786 goto fail;
787
788 *_pid = pid;
789
790 return 0;
791
792fail:
718db961 793 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
a16e1123
LP
794
795 return r;
796}
797
9d2f5178 798static void mount_enter_dead(Mount *m, MountResult f) {
e537352b
LP
799 assert(m);
800
9d2f5178
LP
801 if (f != MOUNT_SUCCESS)
802 m->result = f;
e537352b 803
613b411c
LP
804 exec_runtime_destroy(m->exec_runtime);
805 m->exec_runtime = exec_runtime_unref(m->exec_runtime);
806
e66cf1a3
LP
807 exec_context_destroy_runtime_directory(&m->exec_context, manager_get_runtime_prefix(UNIT(m)->manager));
808
9d2f5178 809 mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
e537352b
LP
810}
811
9d2f5178 812static void mount_enter_mounted(Mount *m, MountResult f) {
80876c20
LP
813 assert(m);
814
9d2f5178
LP
815 if (f != MOUNT_SUCCESS)
816 m->result = f;
80876c20
LP
817
818 mount_set_state(m, MOUNT_MOUNTED);
819}
820
9d2f5178 821static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
e537352b
LP
822 int r;
823
824 assert(m);
825
9d2f5178
LP
826 if (f != MOUNT_SUCCESS)
827 m->result = f;
e537352b 828
cd2086fe
LP
829 r = unit_kill_context(
830 UNIT(m),
831 &m->kill_context,
832 state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM,
833 -1,
834 m->control_pid,
835 false);
836 if (r < 0)
837 goto fail;
e537352b 838
cd2086fe 839 if (r > 0) {
718db961 840 r = mount_arm_timer(m);
36697dc0 841 if (r < 0)
80876c20 842 goto fail;
e537352b 843
80876c20 844 mount_set_state(m, state);
ac84d1fb
LP
845 } else if (state == MOUNT_REMOUNTING_SIGTERM)
846 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
847 else if (state == MOUNT_REMOUNTING_SIGKILL)
9d2f5178 848 mount_enter_mounted(m, MOUNT_SUCCESS);
ac84d1fb
LP
849 else if (state == MOUNT_MOUNTING_SIGTERM)
850 mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_SUCCESS);
851 else if (state == MOUNT_UNMOUNTING_SIGTERM)
852 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS);
80876c20 853 else
9d2f5178 854 mount_enter_dead(m, MOUNT_SUCCESS);
e537352b
LP
855
856 return;
857
858fail:
66870f90
ZJS
859 log_warning_unit(UNIT(m)->id,
860 "%s failed to kill processes: %s", UNIT(m)->id, strerror(-r));
e537352b 861
80876c20 862 if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
9d2f5178 863 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
80876c20 864 else
9d2f5178 865 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
866}
867
20ad4cfd 868void warn_if_dir_nonempty(const char *unit, const char* where) {
cd2086fe
LP
869 assert(unit);
870 assert(where);
871
20ad4cfd
ZJS
872 if (dir_is_empty(where) > 0)
873 return;
cd2086fe 874
bbc9006e
MT
875 log_struct_unit(LOG_NOTICE,
876 unit,
20ad4cfd
ZJS
877 "MESSAGE=%s: Directory %s to mount over is not empty, mounting anyway.",
878 unit, where,
879 "WHERE=%s", where,
20ad4cfd
ZJS
880 MESSAGE_ID(SD_MESSAGE_OVERMOUNTING),
881 NULL);
882}
883
9d2f5178 884static void mount_enter_unmounting(Mount *m) {
e537352b
LP
885 int r;
886
887 assert(m);
888
a16e1123
LP
889 m->control_command_id = MOUNT_EXEC_UNMOUNT;
890 m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
e537352b
LP
891
892 if ((r = exec_command_set(
a16e1123 893 m->control_command,
e537352b
LP
894 "/bin/umount",
895 m->where,
896 NULL)) < 0)
897 goto fail;
898
a16e1123 899 mount_unwatch_control_pid(m);
5e94833f 900
a16e1123 901 if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
e537352b
LP
902 goto fail;
903
904 mount_set_state(m, MOUNT_UNMOUNTING);
905
906 return;
907
908fail:
66870f90
ZJS
909 log_warning_unit(UNIT(m)->id,
910 "%s failed to run 'umount' task: %s",
911 UNIT(m)->id, strerror(-r));
9d2f5178 912 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
913}
914
8d567588 915static void mount_enter_mounting(Mount *m) {
e537352b 916 int r;
cb39ed3f 917 MountParameters *p;
e537352b
LP
918
919 assert(m);
920
a16e1123
LP
921 m->control_command_id = MOUNT_EXEC_MOUNT;
922 m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
e537352b 923
d2e54fae 924 mkdir_p_label(m->where, m->directory_mode);
3e5235b0 925
20ad4cfd 926 warn_if_dir_nonempty(m->meta.id, m->where);
257f1d8e 927
cb39ed3f 928 /* Create the source directory for bind-mounts if needed */
6b1dc2bd 929 p = get_mount_parameters_fragment(m);
cb39ed3f 930 if (p && mount_is_bind(p))
d2e54fae 931 mkdir_p_label(p->what, m->directory_mode);
2b583ce6 932
e537352b
LP
933 if (m->from_fragment)
934 r = exec_command_set(
a16e1123 935 m->control_command,
e537352b
LP
936 "/bin/mount",
937 m->parameters_fragment.what,
938 m->where,
40b8a332 939 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
8d567588 940 m->parameters_fragment.options ? "-o" : NULL, m->parameters_fragment.options,
e537352b 941 NULL);
e537352b
LP
942 else
943 r = -ENOENT;
944
945 if (r < 0)
946 goto fail;
947
a16e1123 948 mount_unwatch_control_pid(m);
5e94833f 949
257f1d8e
LP
950 r = mount_spawn(m, m->control_command, &m->control_pid);
951 if (r < 0)
e537352b
LP
952 goto fail;
953
954 mount_set_state(m, MOUNT_MOUNTING);
955
956 return;
957
958fail:
66870f90
ZJS
959 log_warning_unit(UNIT(m)->id,
960 "%s failed to run 'mount' task: %s",
961 UNIT(m)->id, strerror(-r));
9d2f5178 962 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
963}
964
9d2f5178 965static void mount_enter_remounting(Mount *m) {
e537352b
LP
966 int r;
967
968 assert(m);
969
a16e1123
LP
970 m->control_command_id = MOUNT_EXEC_REMOUNT;
971 m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
e537352b
LP
972
973 if (m->from_fragment) {
e537352b
LP
974 const char *o;
975
718db961
LP
976 if (m->parameters_fragment.options)
977 o = strappenda("remount,", m->parameters_fragment.options);
978 else
e537352b
LP
979 o = "remount";
980
981 r = exec_command_set(
a16e1123 982 m->control_command,
e537352b
LP
983 "/bin/mount",
984 m->parameters_fragment.what,
985 m->where,
40b8a332 986 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
e537352b
LP
987 "-o", o,
988 NULL);
6b1dc2bd 989 } else
e537352b
LP
990 r = -ENOENT;
991
60b912f6 992 if (r < 0)
e537352b 993 goto fail;
e537352b 994
a16e1123 995 mount_unwatch_control_pid(m);
5e94833f 996
718db961
LP
997 r = mount_spawn(m, m->control_command, &m->control_pid);
998 if (r < 0)
e537352b
LP
999 goto fail;
1000
1001 mount_set_state(m, MOUNT_REMOUNTING);
1002
1003 return;
1004
1005fail:
66870f90
ZJS
1006 log_warning_unit(UNIT(m)->id,
1007 "%s failed to run 'remount' task: %s",
1008 UNIT(m)->id, strerror(-r));
9d2f5178
LP
1009 m->reload_result = MOUNT_FAILURE_RESOURCES;
1010 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1011}
1012
1013static int mount_start(Unit *u) {
1014 Mount *m = MOUNT(u);
1015
1016 assert(m);
1017
1018 /* We cannot fulfill this request right now, try again later
1019 * please! */
1020 if (m->state == MOUNT_UNMOUNTING ||
1021 m->state == MOUNT_UNMOUNTING_SIGTERM ||
60b912f6
LP
1022 m->state == MOUNT_UNMOUNTING_SIGKILL ||
1023 m->state == MOUNT_MOUNTING_SIGTERM ||
1024 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1025 return -EAGAIN;
1026
1027 /* Already on it! */
60b912f6 1028 if (m->state == MOUNT_MOUNTING)
e537352b
LP
1029 return 0;
1030
fdf20a31 1031 assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
e537352b 1032
9d2f5178
LP
1033 m->result = MOUNT_SUCCESS;
1034 m->reload_result = MOUNT_SUCCESS;
1035
8d567588 1036 mount_enter_mounting(m);
e537352b
LP
1037 return 0;
1038}
1039
1040static int mount_stop(Unit *u) {
1041 Mount *m = MOUNT(u);
1042
1043 assert(m);
1044
e537352b
LP
1045 /* Already on it */
1046 if (m->state == MOUNT_UNMOUNTING ||
1047 m->state == MOUNT_UNMOUNTING_SIGKILL ||
60b912f6
LP
1048 m->state == MOUNT_UNMOUNTING_SIGTERM ||
1049 m->state == MOUNT_MOUNTING_SIGTERM ||
1050 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1051 return 0;
1052
3f6c78dc
LP
1053 assert(m->state == MOUNT_MOUNTING ||
1054 m->state == MOUNT_MOUNTING_DONE ||
1055 m->state == MOUNT_MOUNTED ||
3f6c78dc
LP
1056 m->state == MOUNT_REMOUNTING ||
1057 m->state == MOUNT_REMOUNTING_SIGTERM ||
1058 m->state == MOUNT_REMOUNTING_SIGKILL);
e537352b 1059
9d2f5178 1060 mount_enter_unmounting(m);
e537352b
LP
1061 return 0;
1062}
1063
1064static int mount_reload(Unit *u) {
1065 Mount *m = MOUNT(u);
1066
1067 assert(m);
1068
1069 if (m->state == MOUNT_MOUNTING_DONE)
1070 return -EAGAIN;
1071
1072 assert(m->state == MOUNT_MOUNTED);
1073
9d2f5178 1074 mount_enter_remounting(m);
e537352b
LP
1075 return 0;
1076}
1077
a16e1123
LP
1078static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
1079 Mount *m = MOUNT(u);
1080
1081 assert(m);
1082 assert(f);
1083 assert(fds);
1084
1085 unit_serialize_item(u, f, "state", mount_state_to_string(m->state));
9d2f5178
LP
1086 unit_serialize_item(u, f, "result", mount_result_to_string(m->result));
1087 unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result));
a16e1123
LP
1088
1089 if (m->control_pid > 0)
ccd06097 1090 unit_serialize_item_format(u, f, "control-pid", PID_FMT, m->control_pid);
a16e1123
LP
1091
1092 if (m->control_command_id >= 0)
1093 unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
1094
1095 return 0;
1096}
1097
1098static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1099 Mount *m = MOUNT(u);
a16e1123
LP
1100
1101 assert(u);
1102 assert(key);
1103 assert(value);
1104 assert(fds);
1105
1106 if (streq(key, "state")) {
1107 MountState state;
1108
1109 if ((state = mount_state_from_string(value)) < 0)
66870f90 1110 log_debug_unit(u->id, "Failed to parse state value %s", value);
a16e1123
LP
1111 else
1112 m->deserialized_state = state;
9d2f5178
LP
1113 } else if (streq(key, "result")) {
1114 MountResult f;
a16e1123 1115
9d2f5178
LP
1116 f = mount_result_from_string(value);
1117 if (f < 0)
66870f90
ZJS
1118 log_debug_unit(UNIT(m)->id,
1119 "Failed to parse result value %s", value);
9d2f5178
LP
1120 else if (f != MOUNT_SUCCESS)
1121 m->result = f;
1122
1123 } else if (streq(key, "reload-result")) {
1124 MountResult f;
1125
1126 f = mount_result_from_string(value);
1127 if (f < 0)
66870f90
ZJS
1128 log_debug_unit(UNIT(m)->id,
1129 "Failed to parse reload result value %s", value);
9d2f5178
LP
1130 else if (f != MOUNT_SUCCESS)
1131 m->reload_result = f;
a16e1123
LP
1132
1133 } else if (streq(key, "control-pid")) {
5925dd3c 1134 pid_t pid;
a16e1123 1135
e364ad06 1136 if (parse_pid(value, &pid) < 0)
66870f90
ZJS
1137 log_debug_unit(UNIT(m)->id,
1138 "Failed to parse control-pid value %s", value);
a16e1123 1139 else
5925dd3c 1140 m->control_pid = pid;
a16e1123
LP
1141 } else if (streq(key, "control-command")) {
1142 MountExecCommand id;
1143
1144 if ((id = mount_exec_command_from_string(value)) < 0)
66870f90
ZJS
1145 log_debug_unit(UNIT(m)->id,
1146 "Failed to parse exec-command value %s", value);
a16e1123
LP
1147 else {
1148 m->control_command_id = id;
1149 m->control_command = m->exec_command + id;
1150 }
a16e1123 1151 } else
66870f90
ZJS
1152 log_debug_unit(UNIT(m)->id,
1153 "Unknown serialization key '%s'", key);
a16e1123
LP
1154
1155 return 0;
1156}
1157
44a6b1b6 1158_pure_ static UnitActiveState mount_active_state(Unit *u) {
e537352b
LP
1159 assert(u);
1160
1161 return state_translation_table[MOUNT(u)->state];
1162}
1163
44a6b1b6 1164_pure_ static const char *mount_sub_state_to_string(Unit *u) {
10a94420
LP
1165 assert(u);
1166
a16e1123 1167 return mount_state_to_string(MOUNT(u)->state);
10a94420
LP
1168}
1169
44a6b1b6 1170_pure_ static bool mount_check_gc(Unit *u) {
701cc384
LP
1171 Mount *m = MOUNT(u);
1172
1173 assert(m);
1174
6b1dc2bd 1175 return m->from_proc_self_mountinfo;
701cc384
LP
1176}
1177
e537352b
LP
1178static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1179 Mount *m = MOUNT(u);
9d2f5178 1180 MountResult f;
e537352b
LP
1181
1182 assert(m);
1183 assert(pid >= 0);
1184
8c47c732
LP
1185 if (pid != m->control_pid)
1186 return;
e537352b 1187
e537352b
LP
1188 m->control_pid = 0;
1189
96342de6 1190 if (is_clean_exit(code, status, NULL))
9d2f5178
LP
1191 f = MOUNT_SUCCESS;
1192 else if (code == CLD_EXITED)
1193 f = MOUNT_FAILURE_EXIT_CODE;
1194 else if (code == CLD_KILLED)
1195 f = MOUNT_FAILURE_SIGNAL;
1196 else if (code == CLD_DUMPED)
1197 f = MOUNT_FAILURE_CORE_DUMP;
1198 else
1199 assert_not_reached("Unknown code");
1200
1201 if (f != MOUNT_SUCCESS)
1202 m->result = f;
8c47c732 1203
a16e1123 1204 if (m->control_command) {
6ea832a2 1205 exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status);
9d2f5178 1206
a16e1123
LP
1207 m->control_command = NULL;
1208 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
1209 }
1210
66870f90
ZJS
1211 log_full_unit(f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, u->id,
1212 "%s mount process exited, code=%s status=%i",
1213 u->id, sigchld_code_to_string(code), status);
e537352b
LP
1214
1215 /* Note that mount(8) returning and the kernel sending us a
1216 * mount table change event might happen out-of-order. If an
1217 * operation succeed we assume the kernel will follow soon too
1218 * and already change into the resulting state. If it fails
1219 * we check if the kernel still knows about the mount. and
1220 * change state accordingly. */
1221
1222 switch (m->state) {
1223
1224 case MOUNT_MOUNTING:
1225 case MOUNT_MOUNTING_DONE:
1226 case MOUNT_MOUNTING_SIGKILL:
1227 case MOUNT_MOUNTING_SIGTERM:
e537352b 1228
9d2f5178
LP
1229 if (f == MOUNT_SUCCESS)
1230 mount_enter_mounted(m, f);
e537352b 1231 else if (m->from_proc_self_mountinfo)
9d2f5178 1232 mount_enter_mounted(m, f);
e537352b 1233 else
9d2f5178 1234 mount_enter_dead(m, f);
e537352b
LP
1235 break;
1236
e2f3b44c
LP
1237 case MOUNT_REMOUNTING:
1238 case MOUNT_REMOUNTING_SIGKILL:
1239 case MOUNT_REMOUNTING_SIGTERM:
1240
9d2f5178 1241 m->reload_result = f;
e2f3b44c 1242 if (m->from_proc_self_mountinfo)
9d2f5178 1243 mount_enter_mounted(m, MOUNT_SUCCESS);
e2f3b44c 1244 else
9d2f5178 1245 mount_enter_dead(m, MOUNT_SUCCESS);
e2f3b44c
LP
1246
1247 break;
1248
e537352b
LP
1249 case MOUNT_UNMOUNTING:
1250 case MOUNT_UNMOUNTING_SIGKILL:
1251 case MOUNT_UNMOUNTING_SIGTERM:
1252
9d2f5178
LP
1253 if (f == MOUNT_SUCCESS)
1254 mount_enter_dead(m, f);
e537352b 1255 else if (m->from_proc_self_mountinfo)
9d2f5178 1256 mount_enter_mounted(m, f);
e537352b 1257 else
9d2f5178 1258 mount_enter_dead(m, f);
e537352b
LP
1259 break;
1260
1261 default:
1262 assert_not_reached("Uh, control process died at wrong time.");
1263 }
c4e2ceae
LP
1264
1265 /* Notify clients about changed exit status */
1266 unit_add_to_dbus_queue(u);
e537352b
LP
1267}
1268
718db961
LP
1269static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
1270 Mount *m = MOUNT(userdata);
e537352b
LP
1271
1272 assert(m);
718db961 1273 assert(m->timer_event_source == source);
e537352b
LP
1274
1275 switch (m->state) {
1276
1277 case MOUNT_MOUNTING:
1278 case MOUNT_MOUNTING_DONE:
718db961
LP
1279 log_warning_unit(UNIT(m)->id,
1280 "%s mounting timed out. Stopping.", UNIT(m)->id);
9d2f5178 1281 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1282 break;
1283
1284 case MOUNT_REMOUNTING:
718db961
LP
1285 log_warning_unit(UNIT(m)->id,
1286 "%s remounting timed out. Stopping.", UNIT(m)->id);
9d2f5178
LP
1287 m->reload_result = MOUNT_FAILURE_TIMEOUT;
1288 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1289 break;
1290
1291 case MOUNT_UNMOUNTING:
718db961
LP
1292 log_warning_unit(UNIT(m)->id,
1293 "%s unmounting timed out. Stopping.", UNIT(m)->id);
9d2f5178 1294 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1295 break;
1296
1297 case MOUNT_MOUNTING_SIGTERM:
4819ff03 1298 if (m->kill_context.send_sigkill) {
718db961
LP
1299 log_warning_unit(UNIT(m)->id,
1300 "%s mounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1301 mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1302 } else {
718db961 1303 log_warning_unit(UNIT(m)->id,
66870f90 1304 "%s mounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1305 UNIT(m)->id);
ba035df2
LP
1306
1307 if (m->from_proc_self_mountinfo)
9d2f5178 1308 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1309 else
9d2f5178 1310 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1311 }
e537352b
LP
1312 break;
1313
1314 case MOUNT_REMOUNTING_SIGTERM:
4819ff03 1315 if (m->kill_context.send_sigkill) {
718db961
LP
1316 log_warning_unit(UNIT(m)->id,
1317 "%s remounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1318 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1319 } else {
718db961 1320 log_warning_unit(UNIT(m)->id,
66870f90 1321 "%s remounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1322 UNIT(m)->id);
ba035df2
LP
1323
1324 if (m->from_proc_self_mountinfo)
9d2f5178 1325 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1326 else
9d2f5178 1327 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1328 }
e537352b
LP
1329 break;
1330
1331 case MOUNT_UNMOUNTING_SIGTERM:
4819ff03 1332 if (m->kill_context.send_sigkill) {
718db961
LP
1333 log_warning_unit(UNIT(m)->id,
1334 "%s unmounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1335 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1336 } else {
718db961 1337 log_warning_unit(UNIT(m)->id,
66870f90 1338 "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1339 UNIT(m)->id);
ba035df2
LP
1340
1341 if (m->from_proc_self_mountinfo)
9d2f5178 1342 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1343 else
9d2f5178 1344 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1345 }
e537352b
LP
1346 break;
1347
1348 case MOUNT_MOUNTING_SIGKILL:
1349 case MOUNT_REMOUNTING_SIGKILL:
1350 case MOUNT_UNMOUNTING_SIGKILL:
718db961 1351 log_warning_unit(UNIT(m)->id,
66870f90 1352 "%s mount process still around after SIGKILL. Ignoring.",
718db961 1353 UNIT(m)->id);
e537352b
LP
1354
1355 if (m->from_proc_self_mountinfo)
9d2f5178 1356 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
e537352b 1357 else
9d2f5178 1358 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1359 break;
1360
1361 default:
1362 assert_not_reached("Timeout at wrong time.");
1363 }
718db961
LP
1364
1365 return 0;
e537352b
LP
1366}
1367
1368static int mount_add_one(
1369 Manager *m,
1370 const char *what,
1371 const char *where,
1372 const char *options,
1373 const char *fstype,
e537352b 1374 bool set_flags) {
057d9ab8
LP
1375
1376 _cleanup_free_ char *e = NULL, *w = NULL, *o = NULL, *f = NULL;
b87705cd 1377 bool load_extras = false;
057d9ab8 1378 MountParameters *p;
ff5f34d0 1379 bool delete, changed = false;
057d9ab8
LP
1380 Unit *u;
1381 int r;
b08d03ff 1382
f50e0a01 1383 assert(m);
b08d03ff
LP
1384 assert(what);
1385 assert(where);
e537352b
LP
1386 assert(options);
1387 assert(fstype);
1388
e537352b
LP
1389 /* Ignore API mount points. They should never be referenced in
1390 * dependencies ever. */
33ff02c9 1391 if (mount_point_is_api(where) || mount_point_ignore(where))
57f2a956 1392 return 0;
b08d03ff 1393
8d567588
LP
1394 if (streq(fstype, "autofs"))
1395 return 0;
1396
4e85aff4
LP
1397 /* probably some kind of swap, ignore */
1398 if (!is_path(where))
b08d03ff
LP
1399 return 0;
1400
7d17cfbc
MS
1401 e = unit_name_from_path(where, ".mount");
1402 if (!e)
b08d03ff
LP
1403 return -ENOMEM;
1404
7d17cfbc
MS
1405 u = manager_get_unit(m, e);
1406 if (!u) {
b08d03ff
LP
1407 delete = true;
1408
7d17cfbc 1409 u = unit_new(m, sizeof(Mount));
057d9ab8 1410 if (!u)
b08d03ff 1411 return -ENOMEM;
b08d03ff
LP
1412
1413 r = unit_add_name(u, e);
b08d03ff
LP
1414 if (r < 0)
1415 goto fail;
1416
7d17cfbc
MS
1417 MOUNT(u)->where = strdup(where);
1418 if (!MOUNT(u)->where) {
07b0b134
ML
1419 r = -ENOMEM;
1420 goto fail;
1421 }
f50e0a01 1422
47a81ba2
UTL
1423 u->source_path = strdup("/proc/self/mountinfo");
1424 if (!u->source_path) {
1425 r = -ENOMEM;
1426 goto fail;
1427 }
1428
89b1d5e0 1429
057d9ab8
LP
1430 if (m->running_as == SYSTEMD_SYSTEM) {
1431 const char* target;
1432
1433 target = fstype_is_network(fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
1434
1435 r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true);
602c0e74
LP
1436 if (r < 0)
1437 goto fail;
057d9ab8
LP
1438
1439 if (should_umount(MOUNT(u))) {
1440 r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
1441 if (r < 0)
1442 goto fail;
1443 }
602c0e74 1444 }
89b1d5e0 1445
f94ea366 1446 unit_add_to_load_queue(u);
ff5f34d0 1447 changed = true;
b08d03ff
LP
1448 } else {
1449 delete = false;
8eba616f 1450
bcbd5405
WW
1451 if (!MOUNT(u)->where) {
1452 MOUNT(u)->where = strdup(where);
1453 if (!MOUNT(u)->where) {
1454 r = -ENOMEM;
1455 goto fail;
1456 }
1457 }
1458
c2756a68 1459 if (u->load_state == UNIT_NOT_FOUND) {
8eba616f
MS
1460 u->load_state = UNIT_LOADED;
1461 u->load_error = 0;
b87705cd
LP
1462
1463 /* Load in the extras later on, after we
1464 * finished initialization of the unit */
1465 load_extras = true;
ff5f34d0 1466 changed = true;
8eba616f 1467 }
b08d03ff
LP
1468 }
1469
dd7a22a9
LP
1470 w = strdup(what);
1471 o = strdup(options);
1472 f = strdup(fstype);
1473 if (!w || !o || !f) {
e537352b
LP
1474 r = -ENOMEM;
1475 goto fail;
1476 }
1477
6b1dc2bd 1478 p = &MOUNT(u)->parameters_proc_self_mountinfo;
ff5f34d0
LP
1479
1480 changed = changed ||
1481 !streq_ptr(p->options, options) ||
1482 !streq_ptr(p->what, what) ||
1483 !streq_ptr(p->fstype, fstype);
1484
6b1dc2bd
LP
1485 if (set_flags) {
1486 MOUNT(u)->is_mounted = true;
1487 MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
ff5f34d0 1488 MOUNT(u)->just_changed = changed;
ef734fd6 1489 }
f50e0a01 1490
6b1dc2bd
LP
1491 MOUNT(u)->from_proc_self_mountinfo = true;
1492
4e85aff4
LP
1493 free(p->what);
1494 p->what = w;
057d9ab8 1495 w = NULL;
b08d03ff 1496
4e85aff4
LP
1497 free(p->options);
1498 p->options = o;
057d9ab8 1499 o = NULL;
e537352b 1500
4e85aff4
LP
1501 free(p->fstype);
1502 p->fstype = f;
057d9ab8 1503 f = NULL;
b08d03ff 1504
b87705cd
LP
1505 if (load_extras) {
1506 r = mount_add_extras(MOUNT(u));
1507 if (r < 0)
1508 goto fail;
1509 }
1510
ff5f34d0
LP
1511 if (changed)
1512 unit_add_to_dbus_queue(u);
c1e1601e 1513
b08d03ff
LP
1514 return 0;
1515
1516fail:
1517 if (delete && u)
1518 unit_free(u);
1519
4e85aff4 1520 return r;
b08d03ff
LP
1521}
1522
ef734fd6 1523static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
60b912f6 1524 int r = 0;
1ddff895 1525 unsigned i;
b08d03ff
LP
1526
1527 assert(m);
1528
ef734fd6 1529 rewind(m->proc_self_mountinfo);
b08d03ff 1530
1ddff895 1531 for (i = 1;; i++) {
a57f7e2c 1532 _cleanup_free_ char *device = NULL, *path = NULL, *options = NULL, *options2 = NULL, *fstype = NULL, *d = NULL, *p = NULL, *o = NULL;
b08d03ff 1533 int k;
e537352b 1534
a57f7e2c
LP
1535 k = fscanf(m->proc_self_mountinfo,
1536 "%*s " /* (1) mount id */
1537 "%*s " /* (2) parent id */
1538 "%*s " /* (3) major:minor */
1539 "%*s " /* (4) root */
1540 "%ms " /* (5) mount point */
1541 "%ms" /* (6) mount options */
1542 "%*[^-]" /* (7) optional fields */
1543 "- " /* (8) separator */
1544 "%ms " /* (9) file system type */
1545 "%ms" /* (10) mount source */
1546 "%ms" /* (11) mount options 2 */
1547 "%*[^\n]", /* some rubbish at the end */
1548 &path,
1549 &options,
1550 &fstype,
1551 &device,
1552 &options2);
1553
1554 if (k == EOF)
1555 break;
1556
1557 if (k != 5) {
1ddff895 1558 log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
a57f7e2c 1559 continue;
b08d03ff
LP
1560 }
1561
b7def684 1562 o = strjoin(options, ",", options2, NULL);
a57f7e2c
LP
1563 if (!o)
1564 return log_oom();
a2e0f3d3 1565
a57f7e2c
LP
1566 d = cunescape(device);
1567 p = cunescape(path);
1568 if (!d || !p)
1569 return log_oom();
b08d03ff 1570
accdd018 1571 k = mount_add_one(m, d, p, o, fstype, set_flags);
a57f7e2c 1572 if (k < 0)
60b912f6 1573 r = k;
b08d03ff
LP
1574 }
1575
e537352b
LP
1576 return r;
1577}
1578
1579static void mount_shutdown(Manager *m) {
1580 assert(m);
1581
718db961
LP
1582 m->mount_event_source = sd_event_source_unref(m->mount_event_source);
1583
a16e1123 1584 if (m->proc_self_mountinfo) {
e537352b 1585 fclose(m->proc_self_mountinfo);
a16e1123
LP
1586 m->proc_self_mountinfo = NULL;
1587 }
b08d03ff
LP
1588}
1589
68db7a3b
ZJS
1590static int mount_get_timeout(Unit *u, uint64_t *timeout) {
1591 Mount *m = MOUNT(u);
1592 int r;
1593
1594 if (!m->timer_event_source)
1595 return 0;
1596
1597 r = sd_event_source_get_time(m->timer_event_source, timeout);
1598 if (r < 0)
1599 return r;
1600
1601 return 1;
1602}
1603
b08d03ff
LP
1604static int mount_enumerate(Manager *m) {
1605 int r;
1606 assert(m);
1607
a16e1123 1608 if (!m->proc_self_mountinfo) {
e62d8c39
ZJS
1609 m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
1610 if (!m->proc_self_mountinfo)
a16e1123 1611 return -errno;
ef734fd6 1612
151b9b96 1613 r = sd_event_add_io(m->event, &m->mount_event_source, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m);
718db961
LP
1614 if (r < 0)
1615 goto fail;
29083707
LP
1616
1617 /* Dispatch this before we dispatch SIGCHLD, so that
1618 * we always get the events from /proc/self/mountinfo
1619 * before the SIGCHLD of /bin/mount. */
1620 r = sd_event_source_set_priority(m->mount_event_source, -10);
1621 if (r < 0)
1622 goto fail;
a16e1123 1623 }
ef734fd6 1624
e62d8c39
ZJS
1625 r = mount_load_proc_self_mountinfo(m, false);
1626 if (r < 0)
b08d03ff
LP
1627 goto fail;
1628
1629 return 0;
1630
1631fail:
1632 mount_shutdown(m);
1633 return r;
5cb5a6ff
LP
1634}
1635
718db961
LP
1636static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1637 Manager *m = userdata;
595ed347 1638 Unit *u;
ef734fd6
LP
1639 int r;
1640
1641 assert(m);
718db961 1642 assert(revents & EPOLLPRI);
ef734fd6
LP
1643
1644 /* The manager calls this for every fd event happening on the
1645 * /proc/self/mountinfo file, which informs us about mounting
1646 * table changes */
1647
4f0eedb7
ZJS
1648 r = mount_load_proc_self_mountinfo(m, true);
1649 if (r < 0) {
e364ad06 1650 log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-r));
e537352b
LP
1651
1652 /* Reset flags, just in case, for later calls */
595ed347
MS
1653 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1654 Mount *mount = MOUNT(u);
e537352b
LP
1655
1656 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1657 }
1658
718db961 1659 return 0;
ef734fd6
LP
1660 }
1661
1662 manager_dispatch_load_queue(m);
1663
595ed347
MS
1664 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1665 Mount *mount = MOUNT(u);
ef734fd6 1666
e537352b 1667 if (!mount->is_mounted) {
e537352b 1668
ef734fd6 1669 mount->from_proc_self_mountinfo = false;
e537352b
LP
1670
1671 switch (mount->state) {
1672
1673 case MOUNT_MOUNTED:
aef83136
LP
1674 /* This has just been unmounted by
1675 * somebody else, follow the state
1676 * change. */
9d2f5178 1677 mount_enter_dead(mount, MOUNT_SUCCESS);
e537352b
LP
1678 break;
1679
1680 default:
e537352b 1681 break;
e537352b
LP
1682 }
1683
1684 } else if (mount->just_mounted || mount->just_changed) {
1685
60b912f6 1686 /* New or changed mount entry */
e537352b
LP
1687
1688 switch (mount->state) {
1689
1690 case MOUNT_DEAD:
fdf20a31 1691 case MOUNT_FAILED:
aef83136
LP
1692 /* This has just been mounted by
1693 * somebody else, follow the state
1694 * change. */
9d2f5178 1695 mount_enter_mounted(mount, MOUNT_SUCCESS);
e537352b
LP
1696 break;
1697
1698 case MOUNT_MOUNTING:
5bcb0f2b 1699 mount_set_state(mount, MOUNT_MOUNTING_DONE);
e537352b
LP
1700 break;
1701
1702 default:
1703 /* Nothing really changed, but let's
1704 * issue an notification call
1705 * nonetheless, in case somebody is
1706 * waiting for this. (e.g. file system
1707 * ro/rw remounts.) */
1708 mount_set_state(mount, mount->state);
1709 break;
1710 }
1711 }
1712
1713 /* Reset the flags for later calls */
1714 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1715 }
718db961
LP
1716
1717 return 0;
e537352b
LP
1718}
1719
fdf20a31 1720static void mount_reset_failed(Unit *u) {
5632e374
LP
1721 Mount *m = MOUNT(u);
1722
1723 assert(m);
1724
fdf20a31 1725 if (m->state == MOUNT_FAILED)
5632e374
LP
1726 mount_set_state(m, MOUNT_DEAD);
1727
9d2f5178
LP
1728 m->result = MOUNT_SUCCESS;
1729 m->reload_result = MOUNT_SUCCESS;
5632e374
LP
1730}
1731
718db961 1732static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
814cc562 1733 return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
8a0867d6
LP
1734}
1735
a16e1123
LP
1736static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
1737 [MOUNT_DEAD] = "dead",
1738 [MOUNT_MOUNTING] = "mounting",
1739 [MOUNT_MOUNTING_DONE] = "mounting-done",
1740 [MOUNT_MOUNTED] = "mounted",
1741 [MOUNT_REMOUNTING] = "remounting",
1742 [MOUNT_UNMOUNTING] = "unmounting",
1743 [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
1744 [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
1745 [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
1746 [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
1747 [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
1748 [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
fdf20a31 1749 [MOUNT_FAILED] = "failed"
a16e1123
LP
1750};
1751
1752DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
1753
1754static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
1755 [MOUNT_EXEC_MOUNT] = "ExecMount",
1756 [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
1757 [MOUNT_EXEC_REMOUNT] = "ExecRemount",
1758};
1759
1760DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
1761
9d2f5178
LP
1762static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
1763 [MOUNT_SUCCESS] = "success",
1764 [MOUNT_FAILURE_RESOURCES] = "resources",
1765 [MOUNT_FAILURE_TIMEOUT] = "timeout",
1766 [MOUNT_FAILURE_EXIT_CODE] = "exit-code",
1767 [MOUNT_FAILURE_SIGNAL] = "signal",
1768 [MOUNT_FAILURE_CORE_DUMP] = "core-dump"
1769};
1770
1771DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
1772
87f0e418 1773const UnitVTable mount_vtable = {
7d17cfbc 1774 .object_size = sizeof(Mount),
718db961
LP
1775 .exec_context_offset = offsetof(Mount, exec_context),
1776 .cgroup_context_offset = offsetof(Mount, cgroup_context),
1777 .kill_context_offset = offsetof(Mount, kill_context),
613b411c 1778 .exec_runtime_offset = offsetof(Mount, exec_runtime),
3ef63c31 1779
f975e971
LP
1780 .sections =
1781 "Unit\0"
1782 "Mount\0"
1783 "Install\0",
4ad49000 1784 .private_section = "Mount",
71645aca 1785
e537352b 1786 .no_alias = true,
9e2f7c11 1787 .no_instances = true,
e537352b
LP
1788
1789 .init = mount_init,
1790 .load = mount_load,
034c6ed7 1791 .done = mount_done,
e537352b 1792
f50e0a01
LP
1793 .coldplug = mount_coldplug,
1794
034c6ed7 1795 .dump = mount_dump,
5cb5a6ff 1796
e537352b
LP
1797 .start = mount_start,
1798 .stop = mount_stop,
1799 .reload = mount_reload,
1800
8a0867d6
LP
1801 .kill = mount_kill,
1802
a16e1123
LP
1803 .serialize = mount_serialize,
1804 .deserialize_item = mount_deserialize_item,
1805
f50e0a01 1806 .active_state = mount_active_state,
10a94420 1807 .sub_state_to_string = mount_sub_state_to_string,
b08d03ff 1808
701cc384
LP
1809 .check_gc = mount_check_gc,
1810
e537352b 1811 .sigchld_event = mount_sigchld_event,
e537352b 1812
fdf20a31 1813 .reset_failed = mount_reset_failed,
5632e374 1814
c4e2ceae 1815 .bus_interface = "org.freedesktop.systemd1.Mount",
718db961 1816 .bus_vtable = bus_mount_vtable,
74c964d3
LP
1817 .bus_set_property = bus_mount_set_property,
1818 .bus_commit_properties = bus_mount_commit_properties,
4139c1b2 1819
68db7a3b
ZJS
1820 .get_timeout = mount_get_timeout,
1821
f50e0a01 1822 .enumerate = mount_enumerate,
c6918296
MS
1823 .shutdown = mount_shutdown,
1824
1825 .status_message_formats = {
1826 .starting_stopping = {
1827 [0] = "Mounting %s...",
1828 [1] = "Unmounting %s...",
1829 },
1830 .finished_start_job = {
1831 [JOB_DONE] = "Mounted %s.",
1832 [JOB_FAILED] = "Failed to mount %s.",
1833 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1834 [JOB_TIMEOUT] = "Timed out mounting %s.",
1835 },
1836 .finished_stop_job = {
1837 [JOB_DONE] = "Unmounted %s.",
1838 [JOB_FAILED] = "Failed unmounting %s.",
1839 [JOB_TIMEOUT] = "Timed out unmounting %s.",
1840 },
1841 },
5cb5a6ff 1842};