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