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