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