]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/mount.c
hashmap.h: fix coding style issue
[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) {
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
1a4ac875
MS
650 r = unit_add_default_cgroups(u);
651 if (r < 0)
652 return r;
8024c3a7 653
1a4ac875
MS
654 r = mount_fix_timeouts(m);
655 if (r < 0)
656 return r;
657
658 return 0;
659}
660
661static int mount_load(Unit *u) {
662 Mount *m = MOUNT(u);
663 int r;
664
665 assert(u);
666 assert(u->load_state == UNIT_STUB);
667
8eba616f
MS
668 if (m->from_proc_self_mountinfo)
669 r = unit_load_fragment_and_dropin_optional(u);
670 else
671 r = unit_load_fragment_and_dropin(u);
672
1a4ac875
MS
673 if (r < 0)
674 return r;
155da457 675
1a4ac875
MS
676 /* This is a new unit? Then let's add in some extras */
677 if (u->load_state == UNIT_LOADED) {
678 r = mount_add_extras(m);
679 if (r < 0)
680 return r;
e06c73cc 681
cba6e062 682 r = unit_exec_context_defaults(u, &m->exec_context);
e06c73cc
LP
683 if (r < 0)
684 return r;
e537352b
LP
685 }
686
8d567588 687 return mount_verify(m);
e537352b
LP
688}
689
a16e1123
LP
690static int mount_notify_automount(Mount *m, int status) {
691 Unit *p;
692 int r;
57020a3a 693 Iterator i;
a16e1123
LP
694
695 assert(m);
696
1124fe6f 697 SET_FOREACH(p, UNIT(m)->dependencies[UNIT_TRIGGERED_BY], i)
ac155bb8 698 if (p->type == UNIT_AUTOMOUNT) {
57020a3a
LP
699 r = automount_send_ready(AUTOMOUNT(p), status);
700 if (r < 0)
701 return r;
702 }
a16e1123 703
57020a3a 704 return 0;
a16e1123
LP
705}
706
e537352b
LP
707static void mount_set_state(Mount *m, MountState state) {
708 MountState old_state;
709 assert(m);
710
711 old_state = m->state;
712 m->state = state;
713
714 if (state != MOUNT_MOUNTING &&
715 state != MOUNT_MOUNTING_DONE &&
716 state != MOUNT_REMOUNTING &&
717 state != MOUNT_UNMOUNTING &&
718 state != MOUNT_MOUNTING_SIGTERM &&
719 state != MOUNT_MOUNTING_SIGKILL &&
720 state != MOUNT_UNMOUNTING_SIGTERM &&
721 state != MOUNT_UNMOUNTING_SIGKILL &&
722 state != MOUNT_REMOUNTING_SIGTERM &&
723 state != MOUNT_REMOUNTING_SIGKILL) {
724 unit_unwatch_timer(UNIT(m), &m->timer_watch);
a16e1123 725 mount_unwatch_control_pid(m);
e537352b 726 m->control_command = NULL;
a16e1123 727 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
e537352b
LP
728 }
729
8d567588
LP
730 if (state == MOUNT_MOUNTED ||
731 state == MOUNT_REMOUNTING)
732 mount_notify_automount(m, 0);
733 else if (state == MOUNT_DEAD ||
734 state == MOUNT_UNMOUNTING ||
735 state == MOUNT_MOUNTING_SIGTERM ||
736 state == MOUNT_MOUNTING_SIGKILL ||
737 state == MOUNT_REMOUNTING_SIGTERM ||
738 state == MOUNT_REMOUNTING_SIGKILL ||
739 state == MOUNT_UNMOUNTING_SIGTERM ||
740 state == MOUNT_UNMOUNTING_SIGKILL ||
36fcd77e 741 state == MOUNT_FAILED) {
b929bf04
TA
742 if (state != old_state)
743 mount_notify_automount(m, -ENODEV);
744 }
8d567588 745
e537352b 746 if (state != old_state)
66870f90
ZJS
747 log_debug_unit(UNIT(m)->id,
748 "%s changed %s -> %s",
749 UNIT(m)->id,
750 mount_state_to_string(old_state),
751 mount_state_to_string(state));
e537352b 752
9d2f5178
LP
753 unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
754 m->reload_result = MOUNT_SUCCESS;
e537352b
LP
755}
756
757static int mount_coldplug(Unit *u) {
758 Mount *m = MOUNT(u);
a16e1123
LP
759 MountState new_state = MOUNT_DEAD;
760 int r;
e537352b
LP
761
762 assert(m);
763 assert(m->state == MOUNT_DEAD);
764
a16e1123
LP
765 if (m->deserialized_state != m->state)
766 new_state = m->deserialized_state;
767 else if (m->from_proc_self_mountinfo)
768 new_state = MOUNT_MOUNTED;
e537352b 769
a16e1123 770 if (new_state != m->state) {
e537352b 771
a16e1123
LP
772 if (new_state == MOUNT_MOUNTING ||
773 new_state == MOUNT_MOUNTING_DONE ||
774 new_state == MOUNT_REMOUNTING ||
775 new_state == MOUNT_UNMOUNTING ||
776 new_state == MOUNT_MOUNTING_SIGTERM ||
777 new_state == MOUNT_MOUNTING_SIGKILL ||
778 new_state == MOUNT_UNMOUNTING_SIGTERM ||
779 new_state == MOUNT_UNMOUNTING_SIGKILL ||
780 new_state == MOUNT_REMOUNTING_SIGTERM ||
781 new_state == MOUNT_REMOUNTING_SIGKILL) {
e537352b 782
a16e1123
LP
783 if (m->control_pid <= 0)
784 return -EBADMSG;
e537352b 785
36697dc0
LP
786 r = unit_watch_pid(UNIT(m), m->control_pid);
787 if (r < 0)
a16e1123 788 return r;
e537352b 789
36697dc0
LP
790 r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
791 if (r < 0)
a16e1123
LP
792 return r;
793 }
e537352b 794
a16e1123
LP
795 mount_set_state(m, new_state);
796 }
e537352b
LP
797
798 return 0;
e537352b
LP
799}
800
801static void mount_dump(Unit *u, FILE *f, const char *prefix) {
802 Mount *m = MOUNT(u);
803 MountParameters *p;
804
805 assert(m);
806 assert(f);
807
cb39ed3f 808 p = get_mount_parameters(m);
e537352b
LP
809
810 fprintf(f,
811 "%sMount State: %s\n"
81a5c6d0 812 "%sResult: %s\n"
e537352b
LP
813 "%sWhere: %s\n"
814 "%sWhat: %s\n"
815 "%sFile System Type: %s\n"
816 "%sOptions: %s\n"
e537352b
LP
817 "%sFrom /proc/self/mountinfo: %s\n"
818 "%sFrom fragment: %s\n"
3e5235b0 819 "%sDirectoryMode: %04o\n",
a16e1123 820 prefix, mount_state_to_string(m->state),
81a5c6d0 821 prefix, mount_result_to_string(m->result),
e537352b
LP
822 prefix, m->where,
823 prefix, strna(p->what),
824 prefix, strna(p->fstype),
825 prefix, strna(p->options),
e537352b
LP
826 prefix, yes_no(m->from_proc_self_mountinfo),
827 prefix, yes_no(m->from_fragment),
3e5235b0 828 prefix, m->directory_mode);
e537352b
LP
829
830 if (m->control_pid > 0)
831 fprintf(f,
bb00e604
LP
832 "%sControl PID: %lu\n",
833 prefix, (unsigned long) m->control_pid);
e537352b
LP
834
835 exec_context_dump(&m->exec_context, f, prefix);
4819ff03 836 kill_context_dump(&m->kill_context, f, prefix);
e537352b
LP
837}
838
a16e1123
LP
839static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
840 pid_t pid;
841 int r;
842
843 assert(m);
844 assert(c);
845 assert(_pid);
846
36697dc0
LP
847 r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
848 if (r < 0)
a16e1123
LP
849 goto fail;
850
851 if ((r = exec_spawn(c,
852 NULL,
853 &m->exec_context,
854 NULL, 0,
1124fe6f 855 UNIT(m)->manager->environment,
a16e1123
LP
856 true,
857 true,
1e3ad081 858 true,
1124fe6f
MS
859 UNIT(m)->manager->confirm_spawn,
860 UNIT(m)->cgroup_bondings,
861 UNIT(m)->cgroup_attributes,
ecedd90f 862 NULL,
62bca2c6 863 UNIT(m)->id,
f2b68789 864 NULL,
a16e1123
LP
865 &pid)) < 0)
866 goto fail;
867
868 if ((r = unit_watch_pid(UNIT(m), pid)) < 0)
869 /* FIXME: we need to do something here */
870 goto fail;
871
872 *_pid = pid;
873
874 return 0;
875
876fail:
877 unit_unwatch_timer(UNIT(m), &m->timer_watch);
878
879 return r;
880}
881
9d2f5178 882static void mount_enter_dead(Mount *m, MountResult f) {
e537352b
LP
883 assert(m);
884
9d2f5178
LP
885 if (f != MOUNT_SUCCESS)
886 m->result = f;
e537352b 887
c17ec25e 888 exec_context_tmp_dirs_done(&m->exec_context);
9d2f5178 889 mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
e537352b
LP
890}
891
9d2f5178 892static void mount_enter_mounted(Mount *m, MountResult f) {
80876c20
LP
893 assert(m);
894
9d2f5178
LP
895 if (f != MOUNT_SUCCESS)
896 m->result = f;
80876c20
LP
897
898 mount_set_state(m, MOUNT_MOUNTED);
899}
900
9d2f5178 901static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
e537352b
LP
902 int r;
903
904 assert(m);
905
9d2f5178
LP
906 if (f != MOUNT_SUCCESS)
907 m->result = f;
e537352b 908
cd2086fe
LP
909 r = unit_kill_context(
910 UNIT(m),
911 &m->kill_context,
912 state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM,
913 -1,
914 m->control_pid,
915 false);
916 if (r < 0)
917 goto fail;
e537352b 918
cd2086fe 919 if (r > 0) {
36697dc0
LP
920 r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
921 if (r < 0)
80876c20 922 goto fail;
e537352b 923
80876c20
LP
924 mount_set_state(m, state);
925 } else if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
9d2f5178 926 mount_enter_mounted(m, MOUNT_SUCCESS);
80876c20 927 else
9d2f5178 928 mount_enter_dead(m, MOUNT_SUCCESS);
e537352b
LP
929
930 return;
931
932fail:
66870f90
ZJS
933 log_warning_unit(UNIT(m)->id,
934 "%s failed to kill processes: %s", UNIT(m)->id, strerror(-r));
e537352b 935
80876c20 936 if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
9d2f5178 937 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
80876c20 938 else
9d2f5178 939 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
940}
941
20ad4cfd 942void warn_if_dir_nonempty(const char *unit, const char* where) {
cd2086fe
LP
943 assert(unit);
944 assert(where);
945
20ad4cfd
ZJS
946 if (dir_is_empty(where) > 0)
947 return;
cd2086fe 948
bbc9006e
MT
949 log_struct_unit(LOG_NOTICE,
950 unit,
20ad4cfd
ZJS
951 "MESSAGE=%s: Directory %s to mount over is not empty, mounting anyway.",
952 unit, where,
953 "WHERE=%s", where,
20ad4cfd
ZJS
954 MESSAGE_ID(SD_MESSAGE_OVERMOUNTING),
955 NULL);
956}
957
9d2f5178 958static void mount_enter_unmounting(Mount *m) {
e537352b
LP
959 int r;
960
961 assert(m);
962
a16e1123
LP
963 m->control_command_id = MOUNT_EXEC_UNMOUNT;
964 m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
e537352b
LP
965
966 if ((r = exec_command_set(
a16e1123 967 m->control_command,
e537352b
LP
968 "/bin/umount",
969 m->where,
970 NULL)) < 0)
971 goto fail;
972
a16e1123 973 mount_unwatch_control_pid(m);
5e94833f 974
a16e1123 975 if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
e537352b
LP
976 goto fail;
977
978 mount_set_state(m, MOUNT_UNMOUNTING);
979
980 return;
981
982fail:
66870f90
ZJS
983 log_warning_unit(UNIT(m)->id,
984 "%s failed to run 'umount' task: %s",
985 UNIT(m)->id, strerror(-r));
9d2f5178 986 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
987}
988
8d567588 989static void mount_enter_mounting(Mount *m) {
e537352b 990 int r;
cb39ed3f 991 MountParameters *p;
e537352b
LP
992
993 assert(m);
994
a16e1123
LP
995 m->control_command_id = MOUNT_EXEC_MOUNT;
996 m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
e537352b 997
d2e54fae 998 mkdir_p_label(m->where, m->directory_mode);
3e5235b0 999
20ad4cfd 1000 warn_if_dir_nonempty(m->meta.id, m->where);
257f1d8e 1001
cb39ed3f 1002 /* Create the source directory for bind-mounts if needed */
6b1dc2bd 1003 p = get_mount_parameters_fragment(m);
cb39ed3f 1004 if (p && mount_is_bind(p))
d2e54fae 1005 mkdir_p_label(p->what, m->directory_mode);
2b583ce6 1006
e537352b
LP
1007 if (m->from_fragment)
1008 r = exec_command_set(
a16e1123 1009 m->control_command,
e537352b
LP
1010 "/bin/mount",
1011 m->parameters_fragment.what,
1012 m->where,
40b8a332 1013 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
8d567588 1014 m->parameters_fragment.options ? "-o" : NULL, m->parameters_fragment.options,
e537352b 1015 NULL);
e537352b
LP
1016 else
1017 r = -ENOENT;
1018
1019 if (r < 0)
1020 goto fail;
1021
a16e1123 1022 mount_unwatch_control_pid(m);
5e94833f 1023
257f1d8e
LP
1024 r = mount_spawn(m, m->control_command, &m->control_pid);
1025 if (r < 0)
e537352b
LP
1026 goto fail;
1027
1028 mount_set_state(m, MOUNT_MOUNTING);
1029
1030 return;
1031
1032fail:
66870f90
ZJS
1033 log_warning_unit(UNIT(m)->id,
1034 "%s failed to run 'mount' task: %s",
1035 UNIT(m)->id, strerror(-r));
9d2f5178 1036 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
1037}
1038
8d567588 1039static void mount_enter_mounting_done(Mount *m) {
e537352b
LP
1040 assert(m);
1041
e537352b
LP
1042 mount_set_state(m, MOUNT_MOUNTING_DONE);
1043}
1044
9d2f5178 1045static void mount_enter_remounting(Mount *m) {
e537352b
LP
1046 int r;
1047
1048 assert(m);
1049
a16e1123
LP
1050 m->control_command_id = MOUNT_EXEC_REMOUNT;
1051 m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
e537352b
LP
1052
1053 if (m->from_fragment) {
1054 char *buf = NULL;
1055 const char *o;
1056
1057 if (m->parameters_fragment.options) {
1058 if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
1059 r = -ENOMEM;
1060 goto fail;
1061 }
1062
1063 o = buf;
1064 } else
1065 o = "remount";
1066
1067 r = exec_command_set(
a16e1123 1068 m->control_command,
e537352b
LP
1069 "/bin/mount",
1070 m->parameters_fragment.what,
1071 m->where,
40b8a332 1072 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
e537352b
LP
1073 "-o", o,
1074 NULL);
1075
1076 free(buf);
6b1dc2bd 1077 } else
e537352b
LP
1078 r = -ENOENT;
1079
60b912f6 1080 if (r < 0)
e537352b 1081 goto fail;
e537352b 1082
a16e1123 1083 mount_unwatch_control_pid(m);
5e94833f 1084
a16e1123 1085 if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
e537352b
LP
1086 goto fail;
1087
1088 mount_set_state(m, MOUNT_REMOUNTING);
1089
1090 return;
1091
1092fail:
66870f90
ZJS
1093 log_warning_unit(UNIT(m)->id,
1094 "%s failed to run 'remount' task: %s",
1095 UNIT(m)->id, strerror(-r));
9d2f5178
LP
1096 m->reload_result = MOUNT_FAILURE_RESOURCES;
1097 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1098}
1099
1100static int mount_start(Unit *u) {
1101 Mount *m = MOUNT(u);
1102
1103 assert(m);
1104
1105 /* We cannot fulfill this request right now, try again later
1106 * please! */
1107 if (m->state == MOUNT_UNMOUNTING ||
1108 m->state == MOUNT_UNMOUNTING_SIGTERM ||
60b912f6
LP
1109 m->state == MOUNT_UNMOUNTING_SIGKILL ||
1110 m->state == MOUNT_MOUNTING_SIGTERM ||
1111 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1112 return -EAGAIN;
1113
1114 /* Already on it! */
60b912f6 1115 if (m->state == MOUNT_MOUNTING)
e537352b
LP
1116 return 0;
1117
fdf20a31 1118 assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
e537352b 1119
9d2f5178
LP
1120 m->result = MOUNT_SUCCESS;
1121 m->reload_result = MOUNT_SUCCESS;
1122
8d567588 1123 mount_enter_mounting(m);
e537352b
LP
1124 return 0;
1125}
1126
1127static int mount_stop(Unit *u) {
1128 Mount *m = MOUNT(u);
1129
1130 assert(m);
1131
e537352b
LP
1132 /* Already on it */
1133 if (m->state == MOUNT_UNMOUNTING ||
1134 m->state == MOUNT_UNMOUNTING_SIGKILL ||
60b912f6
LP
1135 m->state == MOUNT_UNMOUNTING_SIGTERM ||
1136 m->state == MOUNT_MOUNTING_SIGTERM ||
1137 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1138 return 0;
1139
3f6c78dc
LP
1140 assert(m->state == MOUNT_MOUNTING ||
1141 m->state == MOUNT_MOUNTING_DONE ||
1142 m->state == MOUNT_MOUNTED ||
3f6c78dc
LP
1143 m->state == MOUNT_REMOUNTING ||
1144 m->state == MOUNT_REMOUNTING_SIGTERM ||
1145 m->state == MOUNT_REMOUNTING_SIGKILL);
e537352b 1146
9d2f5178 1147 mount_enter_unmounting(m);
e537352b
LP
1148 return 0;
1149}
1150
1151static int mount_reload(Unit *u) {
1152 Mount *m = MOUNT(u);
1153
1154 assert(m);
1155
1156 if (m->state == MOUNT_MOUNTING_DONE)
1157 return -EAGAIN;
1158
1159 assert(m->state == MOUNT_MOUNTED);
1160
9d2f5178 1161 mount_enter_remounting(m);
e537352b
LP
1162 return 0;
1163}
1164
a16e1123
LP
1165static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
1166 Mount *m = MOUNT(u);
1167
1168 assert(m);
1169 assert(f);
1170 assert(fds);
1171
1172 unit_serialize_item(u, f, "state", mount_state_to_string(m->state));
9d2f5178
LP
1173 unit_serialize_item(u, f, "result", mount_result_to_string(m->result));
1174 unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result));
a16e1123
LP
1175
1176 if (m->control_pid > 0)
5925dd3c 1177 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) m->control_pid);
a16e1123
LP
1178
1179 if (m->control_command_id >= 0)
1180 unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
1181
c17ec25e
MS
1182 exec_context_serialize(&m->exec_context, UNIT(m), f);
1183
a16e1123
LP
1184 return 0;
1185}
1186
1187static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1188 Mount *m = MOUNT(u);
a16e1123
LP
1189
1190 assert(u);
1191 assert(key);
1192 assert(value);
1193 assert(fds);
1194
1195 if (streq(key, "state")) {
1196 MountState state;
1197
1198 if ((state = mount_state_from_string(value)) < 0)
66870f90 1199 log_debug_unit(u->id, "Failed to parse state value %s", value);
a16e1123
LP
1200 else
1201 m->deserialized_state = state;
9d2f5178
LP
1202 } else if (streq(key, "result")) {
1203 MountResult f;
a16e1123 1204
9d2f5178
LP
1205 f = mount_result_from_string(value);
1206 if (f < 0)
66870f90
ZJS
1207 log_debug_unit(UNIT(m)->id,
1208 "Failed to parse result value %s", value);
9d2f5178
LP
1209 else if (f != MOUNT_SUCCESS)
1210 m->result = f;
1211
1212 } else if (streq(key, "reload-result")) {
1213 MountResult f;
1214
1215 f = mount_result_from_string(value);
1216 if (f < 0)
66870f90
ZJS
1217 log_debug_unit(UNIT(m)->id,
1218 "Failed to parse reload result value %s", value);
9d2f5178
LP
1219 else if (f != MOUNT_SUCCESS)
1220 m->reload_result = f;
a16e1123
LP
1221
1222 } else if (streq(key, "control-pid")) {
5925dd3c 1223 pid_t pid;
a16e1123 1224
e364ad06 1225 if (parse_pid(value, &pid) < 0)
66870f90
ZJS
1226 log_debug_unit(UNIT(m)->id,
1227 "Failed to parse control-pid value %s", value);
a16e1123 1228 else
5925dd3c 1229 m->control_pid = pid;
a16e1123
LP
1230 } else if (streq(key, "control-command")) {
1231 MountExecCommand id;
1232
1233 if ((id = mount_exec_command_from_string(value)) < 0)
66870f90
ZJS
1234 log_debug_unit(UNIT(m)->id,
1235 "Failed to parse exec-command value %s", value);
a16e1123
LP
1236 else {
1237 m->control_command_id = id;
1238 m->control_command = m->exec_command + id;
1239 }
c17ec25e
MS
1240 } else if (streq(key, "tmp-dir")) {
1241 char *t;
1242
1243 t = strdup(value);
1244 if (!t)
1245 return log_oom();
1246
1247 m->exec_context.tmp_dir = t;
1248 } else if (streq(key, "var-tmp-dir")) {
1249 char *t;
1250
1251 t = strdup(value);
1252 if (!t)
1253 return log_oom();
a16e1123 1254
c17ec25e 1255 m->exec_context.var_tmp_dir = t;
a16e1123 1256 } else
66870f90
ZJS
1257 log_debug_unit(UNIT(m)->id,
1258 "Unknown serialization key '%s'", key);
a16e1123
LP
1259
1260 return 0;
1261}
1262
e537352b
LP
1263static UnitActiveState mount_active_state(Unit *u) {
1264 assert(u);
1265
1266 return state_translation_table[MOUNT(u)->state];
1267}
1268
10a94420
LP
1269static const char *mount_sub_state_to_string(Unit *u) {
1270 assert(u);
1271
a16e1123 1272 return mount_state_to_string(MOUNT(u)->state);
10a94420
LP
1273}
1274
701cc384
LP
1275static bool mount_check_gc(Unit *u) {
1276 Mount *m = MOUNT(u);
1277
1278 assert(m);
1279
6b1dc2bd 1280 return m->from_proc_self_mountinfo;
701cc384
LP
1281}
1282
e537352b
LP
1283static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1284 Mount *m = MOUNT(u);
9d2f5178 1285 MountResult f;
e537352b
LP
1286
1287 assert(m);
1288 assert(pid >= 0);
1289
8c47c732
LP
1290 if (pid != m->control_pid)
1291 return;
e537352b 1292
e537352b
LP
1293 m->control_pid = 0;
1294
96342de6 1295 if (is_clean_exit(code, status, NULL))
9d2f5178
LP
1296 f = MOUNT_SUCCESS;
1297 else if (code == CLD_EXITED)
1298 f = MOUNT_FAILURE_EXIT_CODE;
1299 else if (code == CLD_KILLED)
1300 f = MOUNT_FAILURE_SIGNAL;
1301 else if (code == CLD_DUMPED)
1302 f = MOUNT_FAILURE_CORE_DUMP;
1303 else
1304 assert_not_reached("Unknown code");
1305
1306 if (f != MOUNT_SUCCESS)
1307 m->result = f;
8c47c732 1308
a16e1123 1309 if (m->control_command) {
6ea832a2 1310 exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status);
9d2f5178 1311
a16e1123
LP
1312 m->control_command = NULL;
1313 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
1314 }
1315
66870f90
ZJS
1316 log_full_unit(f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE, u->id,
1317 "%s mount process exited, code=%s status=%i",
1318 u->id, sigchld_code_to_string(code), status);
e537352b
LP
1319
1320 /* Note that mount(8) returning and the kernel sending us a
1321 * mount table change event might happen out-of-order. If an
1322 * operation succeed we assume the kernel will follow soon too
1323 * and already change into the resulting state. If it fails
1324 * we check if the kernel still knows about the mount. and
1325 * change state accordingly. */
1326
1327 switch (m->state) {
1328
1329 case MOUNT_MOUNTING:
1330 case MOUNT_MOUNTING_DONE:
1331 case MOUNT_MOUNTING_SIGKILL:
1332 case MOUNT_MOUNTING_SIGTERM:
e537352b 1333
9d2f5178
LP
1334 if (f == MOUNT_SUCCESS)
1335 mount_enter_mounted(m, f);
e537352b 1336 else if (m->from_proc_self_mountinfo)
9d2f5178 1337 mount_enter_mounted(m, f);
e537352b 1338 else
9d2f5178 1339 mount_enter_dead(m, f);
e537352b
LP
1340 break;
1341
e2f3b44c
LP
1342 case MOUNT_REMOUNTING:
1343 case MOUNT_REMOUNTING_SIGKILL:
1344 case MOUNT_REMOUNTING_SIGTERM:
1345
9d2f5178 1346 m->reload_result = f;
e2f3b44c 1347 if (m->from_proc_self_mountinfo)
9d2f5178 1348 mount_enter_mounted(m, MOUNT_SUCCESS);
e2f3b44c 1349 else
9d2f5178 1350 mount_enter_dead(m, MOUNT_SUCCESS);
e2f3b44c
LP
1351
1352 break;
1353
e537352b
LP
1354 case MOUNT_UNMOUNTING:
1355 case MOUNT_UNMOUNTING_SIGKILL:
1356 case MOUNT_UNMOUNTING_SIGTERM:
1357
9d2f5178
LP
1358 if (f == MOUNT_SUCCESS)
1359 mount_enter_dead(m, f);
e537352b 1360 else if (m->from_proc_self_mountinfo)
9d2f5178 1361 mount_enter_mounted(m, f);
e537352b 1362 else
9d2f5178 1363 mount_enter_dead(m, f);
e537352b
LP
1364 break;
1365
1366 default:
1367 assert_not_reached("Uh, control process died at wrong time.");
1368 }
c4e2ceae
LP
1369
1370 /* Notify clients about changed exit status */
1371 unit_add_to_dbus_queue(u);
e537352b
LP
1372}
1373
1374static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
1375 Mount *m = MOUNT(u);
1376
1377 assert(m);
1378 assert(elapsed == 1);
1379 assert(w == &m->timer_watch);
1380
1381 switch (m->state) {
1382
1383 case MOUNT_MOUNTING:
1384 case MOUNT_MOUNTING_DONE:
66870f90
ZJS
1385 log_warning_unit(u->id,
1386 "%s mounting timed out. Stopping.", u->id);
9d2f5178 1387 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1388 break;
1389
1390 case MOUNT_REMOUNTING:
66870f90
ZJS
1391 log_warning_unit(u->id,
1392 "%s remounting timed out. Stopping.", u->id);
9d2f5178
LP
1393 m->reload_result = MOUNT_FAILURE_TIMEOUT;
1394 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1395 break;
1396
1397 case MOUNT_UNMOUNTING:
66870f90
ZJS
1398 log_warning_unit(u->id,
1399 "%s unmounting timed out. Stopping.", u->id);
9d2f5178 1400 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1401 break;
1402
1403 case MOUNT_MOUNTING_SIGTERM:
4819ff03 1404 if (m->kill_context.send_sigkill) {
66870f90
ZJS
1405 log_warning_unit(u->id,
1406 "%s mounting timed out. Killing.", u->id);
9d2f5178 1407 mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1408 } else {
66870f90
ZJS
1409 log_warning_unit(u->id,
1410 "%s mounting timed out. Skipping SIGKILL. Ignoring.",
1411 u->id);
ba035df2
LP
1412
1413 if (m->from_proc_self_mountinfo)
9d2f5178 1414 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1415 else
9d2f5178 1416 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1417 }
e537352b
LP
1418 break;
1419
1420 case MOUNT_REMOUNTING_SIGTERM:
4819ff03 1421 if (m->kill_context.send_sigkill) {
66870f90
ZJS
1422 log_warning_unit(u->id,
1423 "%s remounting timed out. Killing.", u->id);
9d2f5178 1424 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1425 } else {
66870f90
ZJS
1426 log_warning_unit(u->id,
1427 "%s remounting timed out. Skipping SIGKILL. Ignoring.",
1428 u->id);
ba035df2
LP
1429
1430 if (m->from_proc_self_mountinfo)
9d2f5178 1431 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1432 else
9d2f5178 1433 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1434 }
e537352b
LP
1435 break;
1436
1437 case MOUNT_UNMOUNTING_SIGTERM:
4819ff03 1438 if (m->kill_context.send_sigkill) {
66870f90
ZJS
1439 log_warning_unit(u->id,
1440 "%s unmounting timed out. Killing.", u->id);
9d2f5178 1441 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1442 } else {
66870f90
ZJS
1443 log_warning_unit(u->id,
1444 "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
1445 u->id);
ba035df2
LP
1446
1447 if (m->from_proc_self_mountinfo)
9d2f5178 1448 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1449 else
9d2f5178 1450 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1451 }
e537352b
LP
1452 break;
1453
1454 case MOUNT_MOUNTING_SIGKILL:
1455 case MOUNT_REMOUNTING_SIGKILL:
1456 case MOUNT_UNMOUNTING_SIGKILL:
66870f90
ZJS
1457 log_warning_unit(u->id,
1458 "%s mount process still around after SIGKILL. Ignoring.",
1459 u->id);
e537352b
LP
1460
1461 if (m->from_proc_self_mountinfo)
9d2f5178 1462 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
e537352b 1463 else
9d2f5178 1464 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1465 break;
1466
1467 default:
1468 assert_not_reached("Timeout at wrong time.");
1469 }
1470}
1471
1472static int mount_add_one(
1473 Manager *m,
1474 const char *what,
1475 const char *where,
1476 const char *options,
1477 const char *fstype,
9fff8a1f 1478 int passno,
e537352b 1479 bool set_flags) {
b08d03ff
LP
1480 int r;
1481 Unit *u;
1482 bool delete;
47a81ba2 1483 char *e, *w = NULL, *o = NULL, *f = NULL;
4e85aff4 1484 MountParameters *p;
b87705cd 1485 bool load_extras = false;
b08d03ff 1486
f50e0a01 1487 assert(m);
b08d03ff
LP
1488 assert(what);
1489 assert(where);
e537352b
LP
1490 assert(options);
1491 assert(fstype);
1492
e537352b
LP
1493 /* Ignore API mount points. They should never be referenced in
1494 * dependencies ever. */
33ff02c9 1495 if (mount_point_is_api(where) || mount_point_ignore(where))
57f2a956 1496 return 0;
b08d03ff 1497
8d567588
LP
1498 if (streq(fstype, "autofs"))
1499 return 0;
1500
4e85aff4
LP
1501 /* probably some kind of swap, ignore */
1502 if (!is_path(where))
b08d03ff
LP
1503 return 0;
1504
7d17cfbc
MS
1505 e = unit_name_from_path(where, ".mount");
1506 if (!e)
b08d03ff
LP
1507 return -ENOMEM;
1508
7d17cfbc
MS
1509 u = manager_get_unit(m, e);
1510 if (!u) {
b08d03ff
LP
1511 delete = true;
1512
7d17cfbc
MS
1513 u = unit_new(m, sizeof(Mount));
1514 if (!u) {
b08d03ff
LP
1515 free(e);
1516 return -ENOMEM;
1517 }
1518
1519 r = unit_add_name(u, e);
1520 free(e);
1521
1522 if (r < 0)
1523 goto fail;
1524
7d17cfbc
MS
1525 MOUNT(u)->where = strdup(where);
1526 if (!MOUNT(u)->where) {
07b0b134
ML
1527 r = -ENOMEM;
1528 goto fail;
1529 }
f50e0a01 1530
47a81ba2
UTL
1531 u->source_path = strdup("/proc/self/mountinfo");
1532 if (!u->source_path) {
1533 r = -ENOMEM;
1534 goto fail;
1535 }
1536
89b1d5e0
UTL
1537 r = unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_LOCAL_FS_TARGET, NULL, true);
1538 if (r < 0)
1539 goto fail;
1540
1541 r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
1542 if (r < 0)
1543 goto fail;
1544
f94ea366 1545 unit_add_to_load_queue(u);
b08d03ff
LP
1546 } else {
1547 delete = false;
1548 free(e);
8eba616f 1549
bcbd5405
WW
1550 if (!MOUNT(u)->where) {
1551 MOUNT(u)->where = strdup(where);
1552 if (!MOUNT(u)->where) {
1553 r = -ENOMEM;
1554 goto fail;
1555 }
1556 }
1557
8eba616f
MS
1558 if (u->load_state == UNIT_ERROR) {
1559 u->load_state = UNIT_LOADED;
1560 u->load_error = 0;
b87705cd
LP
1561
1562 /* Load in the extras later on, after we
1563 * finished initialization of the unit */
1564 load_extras = true;
8eba616f 1565 }
b08d03ff
LP
1566 }
1567
e537352b
LP
1568 if (!(w = strdup(what)) ||
1569 !(o = strdup(options)) ||
1570 !(f = strdup(fstype))) {
1571 r = -ENOMEM;
1572 goto fail;
1573 }
1574
6b1dc2bd
LP
1575 p = &MOUNT(u)->parameters_proc_self_mountinfo;
1576 if (set_flags) {
1577 MOUNT(u)->is_mounted = true;
1578 MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
1579 MOUNT(u)->just_changed = !streq_ptr(p->options, o);
ef734fd6 1580 }
f50e0a01 1581
6b1dc2bd
LP
1582 MOUNT(u)->from_proc_self_mountinfo = true;
1583
4e85aff4
LP
1584 free(p->what);
1585 p->what = w;
b08d03ff 1586
4e85aff4
LP
1587 free(p->options);
1588 p->options = o;
e537352b 1589
4e85aff4
LP
1590 free(p->fstype);
1591 p->fstype = f;
b08d03ff 1592
9fff8a1f
LP
1593 p->passno = passno;
1594
b87705cd
LP
1595 if (load_extras) {
1596 r = mount_add_extras(MOUNT(u));
1597 if (r < 0)
1598 goto fail;
1599 }
1600
c1e1601e
LP
1601 unit_add_to_dbus_queue(u);
1602
b08d03ff
LP
1603 return 0;
1604
1605fail:
e537352b
LP
1606 free(w);
1607 free(o);
1608 free(f);
1609
b08d03ff
LP
1610 if (delete && u)
1611 unit_free(u);
1612
4e85aff4 1613 return r;
b08d03ff
LP
1614}
1615
ef734fd6 1616static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
60b912f6 1617 int r = 0;
1ddff895 1618 unsigned i;
a2e0f3d3 1619 char *device, *path, *options, *options2, *fstype, *d, *p, *o;
b08d03ff
LP
1620
1621 assert(m);
1622
ef734fd6 1623 rewind(m->proc_self_mountinfo);
b08d03ff 1624
1ddff895 1625 for (i = 1;; i++) {
b08d03ff 1626 int k;
e537352b 1627
a2e0f3d3 1628 device = path = options = options2 = fstype = d = p = o = NULL;
b08d03ff 1629
ef734fd6 1630 if ((k = fscanf(m->proc_self_mountinfo,
b08d03ff
LP
1631 "%*s " /* (1) mount id */
1632 "%*s " /* (2) parent id */
1633 "%*s " /* (3) major:minor */
1634 "%*s " /* (4) root */
1635 "%ms " /* (5) mount point */
e537352b 1636 "%ms" /* (6) mount options */
b08d03ff 1637 "%*[^-]" /* (7) optional fields */
c899f8c6 1638 "- " /* (8) separator */
e537352b 1639 "%ms " /* (9) file system type */
ef734fd6 1640 "%ms" /* (10) mount source */
a2e0f3d3 1641 "%ms" /* (11) mount options 2 */
ef734fd6 1642 "%*[^\n]", /* some rubbish at the end */
b08d03ff 1643 &path,
e537352b
LP
1644 &options,
1645 &fstype,
a2e0f3d3
LP
1646 &device,
1647 &options2)) != 5) {
b08d03ff 1648
ef734fd6
LP
1649 if (k == EOF)
1650 break;
b08d03ff 1651
1ddff895
FF
1652 log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
1653 goto clean_up;
b08d03ff
LP
1654 }
1655
b7def684 1656 o = strjoin(options, ",", options2, NULL);
f7f21d33 1657 if (!o) {
a2e0f3d3
LP
1658 r = -ENOMEM;
1659 goto finish;
1660 }
1661
e537352b
LP
1662 if (!(d = cunescape(device)) ||
1663 !(p = cunescape(path))) {
1664 r = -ENOMEM;
1665 goto finish;
b08d03ff 1666 }
b08d03ff 1667
6b1dc2bd 1668 if ((k = mount_add_one(m, d, p, o, fstype, 0, set_flags)) < 0)
60b912f6 1669 r = k;
b08d03ff 1670
1ddff895 1671clean_up:
e537352b
LP
1672 free(device);
1673 free(path);
1674 free(options);
a2e0f3d3 1675 free(options2);
e537352b 1676 free(fstype);
b08d03ff
LP
1677 free(d);
1678 free(p);
a2e0f3d3 1679 free(o);
b08d03ff
LP
1680 }
1681
e537352b
LP
1682finish:
1683 free(device);
1684 free(path);
1685 free(options);
a2e0f3d3 1686 free(options2);
e537352b
LP
1687 free(fstype);
1688 free(d);
1689 free(p);
a2e0f3d3 1690 free(o);
e537352b
LP
1691
1692 return r;
1693}
1694
1695static void mount_shutdown(Manager *m) {
1696 assert(m);
1697
a16e1123 1698 if (m->proc_self_mountinfo) {
e537352b 1699 fclose(m->proc_self_mountinfo);
a16e1123
LP
1700 m->proc_self_mountinfo = NULL;
1701 }
b08d03ff
LP
1702}
1703
1704static int mount_enumerate(Manager *m) {
1705 int r;
1706 assert(m);
1707
a16e1123 1708 if (!m->proc_self_mountinfo) {
b92bea5d
ZJS
1709 struct epoll_event ev = {
1710 .events = EPOLLPRI,
1711 .data.ptr = &m->mount_watch,
1712 };
1713
e62d8c39
ZJS
1714 m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
1715 if (!m->proc_self_mountinfo)
a16e1123 1716 return -errno;
ef734fd6 1717
a16e1123
LP
1718 m->mount_watch.type = WATCH_MOUNT;
1719 m->mount_watch.fd = fileno(m->proc_self_mountinfo);
ef734fd6 1720
a16e1123
LP
1721 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
1722 return -errno;
1723 }
ef734fd6 1724
e62d8c39
ZJS
1725 r = mount_load_proc_self_mountinfo(m, false);
1726 if (r < 0)
b08d03ff
LP
1727 goto fail;
1728
1729 return 0;
1730
1731fail:
1732 mount_shutdown(m);
1733 return r;
5cb5a6ff
LP
1734}
1735
ef734fd6 1736void mount_fd_event(Manager *m, int events) {
595ed347 1737 Unit *u;
ef734fd6
LP
1738 int r;
1739
1740 assert(m);
4e434314 1741 assert(events & EPOLLPRI);
ef734fd6
LP
1742
1743 /* The manager calls this for every fd event happening on the
1744 * /proc/self/mountinfo file, which informs us about mounting
1745 * table changes */
1746
4f0eedb7
ZJS
1747 r = mount_load_proc_self_mountinfo(m, true);
1748 if (r < 0) {
e364ad06 1749 log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-r));
e537352b
LP
1750
1751 /* Reset flags, just in case, for later calls */
595ed347
MS
1752 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1753 Mount *mount = MOUNT(u);
e537352b
LP
1754
1755 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1756 }
1757
ef734fd6
LP
1758 return;
1759 }
1760
1761 manager_dispatch_load_queue(m);
1762
595ed347
MS
1763 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1764 Mount *mount = MOUNT(u);
ef734fd6 1765
e537352b
LP
1766 if (!mount->is_mounted) {
1767 /* This has just been unmounted. */
1768
ef734fd6 1769 mount->from_proc_self_mountinfo = false;
e537352b
LP
1770
1771 switch (mount->state) {
1772
1773 case MOUNT_MOUNTED:
9d2f5178 1774 mount_enter_dead(mount, MOUNT_SUCCESS);
e537352b
LP
1775 break;
1776
1777 default:
1778 mount_set_state(mount, mount->state);
1779 break;
1780
1781 }
1782
1783 } else if (mount->just_mounted || mount->just_changed) {
1784
60b912f6 1785 /* New or changed mount entry */
e537352b
LP
1786
1787 switch (mount->state) {
1788
1789 case MOUNT_DEAD:
fdf20a31 1790 case MOUNT_FAILED:
9d2f5178 1791 mount_enter_mounted(mount, MOUNT_SUCCESS);
e537352b
LP
1792 break;
1793
1794 case MOUNT_MOUNTING:
8d567588 1795 mount_enter_mounting_done(mount);
e537352b
LP
1796 break;
1797
1798 default:
1799 /* Nothing really changed, but let's
1800 * issue an notification call
1801 * nonetheless, in case somebody is
1802 * waiting for this. (e.g. file system
1803 * ro/rw remounts.) */
1804 mount_set_state(mount, mount->state);
1805 break;
1806 }
1807 }
1808
1809 /* Reset the flags for later calls */
1810 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1811 }
1812}
1813
fdf20a31 1814static void mount_reset_failed(Unit *u) {
5632e374
LP
1815 Mount *m = MOUNT(u);
1816
1817 assert(m);
1818
fdf20a31 1819 if (m->state == MOUNT_FAILED)
5632e374
LP
1820 mount_set_state(m, MOUNT_DEAD);
1821
9d2f5178
LP
1822 m->result = MOUNT_SUCCESS;
1823 m->reload_result = MOUNT_SUCCESS;
5632e374
LP
1824}
1825
c74f17d9 1826static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
814cc562 1827 return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
8a0867d6
LP
1828}
1829
a16e1123
LP
1830static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
1831 [MOUNT_DEAD] = "dead",
1832 [MOUNT_MOUNTING] = "mounting",
1833 [MOUNT_MOUNTING_DONE] = "mounting-done",
1834 [MOUNT_MOUNTED] = "mounted",
1835 [MOUNT_REMOUNTING] = "remounting",
1836 [MOUNT_UNMOUNTING] = "unmounting",
1837 [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
1838 [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
1839 [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
1840 [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
1841 [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
1842 [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
fdf20a31 1843 [MOUNT_FAILED] = "failed"
a16e1123
LP
1844};
1845
1846DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
1847
1848static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
1849 [MOUNT_EXEC_MOUNT] = "ExecMount",
1850 [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
1851 [MOUNT_EXEC_REMOUNT] = "ExecRemount",
1852};
1853
1854DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
1855
9d2f5178
LP
1856static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
1857 [MOUNT_SUCCESS] = "success",
1858 [MOUNT_FAILURE_RESOURCES] = "resources",
1859 [MOUNT_FAILURE_TIMEOUT] = "timeout",
1860 [MOUNT_FAILURE_EXIT_CODE] = "exit-code",
1861 [MOUNT_FAILURE_SIGNAL] = "signal",
1862 [MOUNT_FAILURE_CORE_DUMP] = "core-dump"
1863};
1864
1865DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
1866
87f0e418 1867const UnitVTable mount_vtable = {
7d17cfbc 1868 .object_size = sizeof(Mount),
3ef63c31 1869
f975e971
LP
1870 .sections =
1871 "Unit\0"
1872 "Mount\0"
1873 "Install\0",
5cb5a6ff 1874
71645aca
LP
1875 .exec_context_offset = offsetof(Mount, exec_context),
1876 .exec_section = "Mount",
1877
e537352b 1878 .no_alias = true,
9e2f7c11 1879 .no_instances = true,
e537352b
LP
1880
1881 .init = mount_init,
1882 .load = mount_load,
034c6ed7 1883 .done = mount_done,
e537352b 1884
f50e0a01
LP
1885 .coldplug = mount_coldplug,
1886
034c6ed7 1887 .dump = mount_dump,
5cb5a6ff 1888
e537352b
LP
1889 .start = mount_start,
1890 .stop = mount_stop,
1891 .reload = mount_reload,
1892
8a0867d6
LP
1893 .kill = mount_kill,
1894
a16e1123
LP
1895 .serialize = mount_serialize,
1896 .deserialize_item = mount_deserialize_item,
1897
f50e0a01 1898 .active_state = mount_active_state,
10a94420 1899 .sub_state_to_string = mount_sub_state_to_string,
b08d03ff 1900
701cc384
LP
1901 .check_gc = mount_check_gc,
1902
e537352b
LP
1903 .sigchld_event = mount_sigchld_event,
1904 .timer_event = mount_timer_event,
1905
fdf20a31 1906 .reset_failed = mount_reset_failed,
5632e374 1907
c4e2ceae 1908 .bus_interface = "org.freedesktop.systemd1.Mount",
4139c1b2 1909 .bus_message_handler = bus_mount_message_handler,
c4e2ceae 1910 .bus_invalidating_properties = bus_mount_invalidating_properties,
4139c1b2 1911
f50e0a01 1912 .enumerate = mount_enumerate,
c6918296
MS
1913 .shutdown = mount_shutdown,
1914
1915 .status_message_formats = {
1916 .starting_stopping = {
1917 [0] = "Mounting %s...",
1918 [1] = "Unmounting %s...",
1919 },
1920 .finished_start_job = {
1921 [JOB_DONE] = "Mounted %s.",
1922 [JOB_FAILED] = "Failed to mount %s.",
1923 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1924 [JOB_TIMEOUT] = "Timed out mounting %s.",
1925 },
1926 .finished_stop_job = {
1927 [JOB_DONE] = "Unmounted %s.",
1928 [JOB_FAILED] = "Failed unmounting %s.",
1929 [JOB_TIMEOUT] = "Timed out unmounting %s.",
1930 },
1931 },
5cb5a6ff 1932};