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