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