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