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