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