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