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