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