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