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