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