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