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