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