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