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