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